CLI фреймворк для Swift: создание консольных утилит на iOS и macOS
Разработка консольных приложений (CLI — Command Line Interface) для экосистемы Apple долгое время оставалась прерогативой Python, Ruby или Bash. Однако с появлением Swift и его мощного инструментария, включая Swift Package Manager (SPM), появилась возможность создавать быстрые, типизированные и легко поддерживаемые консольные утилиты на родном для iOS/macOS языке. В этой статье мы подробно рассмотрим основной фреймворк для построения CLI на Swift — Apple's ArgumentParser, а также альтернативные решения.
Что такое CLI фреймворк для Swift?
CLI-фреймворк — это библиотека, которая берёт на себя рутинные задачи по парсингу аргументов командной строки, генерации справки, обработке ошибок и организации команд. В мире Swift стандартом де-факто является ArgumentParser, разработанный Apple и входящий в состав Swift Open Source. Он позволяет декларативно описывать интерфейс вашей утилиты, а всё остальное делает автоматически.
Основные возможности ArgumentParser:
- Декларативное определение команд — вы описываете структуру, а фреймворк сам парсит аргументы.
- Автоматическая справка — флаги
--helpи-hгенерируются автоматически. - Поддержка вложенных команд (как в
gitилиswift). - Валидация типов — если ожидается число, а передана строка, будет выведена понятная ошибка.
- Интеграция с SPM — достаточно добавить зависимость в
Package.swift.
Установка и настройка
Для работы вам потребуется Swift 5.5+ (рекомендуется 5.7 или новее). Создайте новый консольный проект через SPM:
mkdir MyCLI
cd MyCLI
swift package init --type executable
Затем отредактируйте Package.swift, добавив зависимость от ArgumentParser:
// swift-tools-version:5.7
import PackageDescription
let package = Package(
name: "MyCLI",
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.0")
],
targets: [
.executableTarget(
name: "MyCLI",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser")
]
)
]
)
Теперь обновите зависимости и откройте проект:
swift package update
open Package.swift # откроет в Xcode
Создание первой команды
Создайте файл main.swift (или Sources/MyCLI/main.swift) со следующим содержимым:
import ArgumentParser
struct Greet: ParsableCommand {
static let configuration = CommandConfiguration(
abstract: "Приветствие пользователя",
discussion: "Эта команда выводит персонализированное приветствие."
)
@Argument(help: "Имя пользователя")
var name: String
@Option(name: .shortAndLong, help: "Количество повторов")
var count: Int = 1
@Flag(name: .shortAndLong, help: "Показать версию")
var verbose: Bool = false
mutating func run() throws {
if verbose {
print("Версия 1.0.0")
}
for _ in 0..<count {
print("Привет, \(name)!")
}
}
}
Greet.main()
Теперь соберите и запустите:
swift run MyCLI Swift --count 3
# Вывод:
# Привет, Swift!
# Привет, Swift!
# Привет, Swift!
swift run MyCLI --help
# Usage: MyCLI <name> [--count <count>] [--verbose]
# Приветствие пользователя
# ...
Вложенные команды (подкоманды)
Для создания сложных утилит (как swift package или git) используйте вложенные команды. Пример структуры для работы с файлами:
struct FileTool: ParsableCommand {
static let configuration = CommandConfiguration(
commandName: "filetool",
subcommands: [Read.self, Write.self, Delete.self],
defaultSubcommand: Read.self
)
}
struct Read: ParsableCommand {
@Argument(help: "Путь к файлу")
var path: String
func run() throws {
let content = try String(contentsOfFile