CLI утилиты на Swift: создаем инструменты командной строки с нуля

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Ваш первый CLI на Swift: от идеи до готового инструмента

Вы когда-нибудь задумывались, как создаются те самые удобные утилиты в терминале — curl, git, brew? Оказывается, написать свою собственную CLI утилиту на Swift не сложнее, чем сделать простое iOS-приложение. Более того, Swift идеально подходит для этого: он быстр, безопасен по памяти и отлично работает как на macOS, так и на Linux.

В этой статье мы с нуля создадим полноценный консольный инструмент, который будет парсить аргументы, выводить цветной текст и даже обрабатывать ошибки. Вы узнаете, как настроить проект через Swift Package Manager, подключить мощную библиотеку ArgumentParser и подготовить утилиту к публикации в Homebrew. Готовы? Погнали!

Почему Swift для CLI — это круто?

Когда речь заходит о создании инструментов командной строки, многие сразу думают о Python, Bash или Go. Но Swift — тёмная лошадка, которая удивляет:

  • Скорость на уровне C — ваша утилита будет летать.
  • Безопасная работа с памятью — никаких segfault и утечек.
  • Кроссплатформенность — Swift отлично работает на Linux, а значит, ваш CLI можно запускать даже на серверах.
  • Современный синтаксис — код читается как хорошая проза.
  • Огромная экосистема — Swift Package Manager (SPM) даёт доступ к тысячам библиотек.

Кстати, если вы уже пишете на Python и хотите попробовать что-то новое для CLI, Swift станет отличным выбором: вы получите нативный бинарник без зависимостей и с минимальным потреблением памяти.

Настройка проекта: Swift Package Manager

Первым делом создадим новый проект. Откройте терминал и выполните:

mkdir MyCLI
cd MyCLI
swift package init --type executable

Команда создаст стандартную структуру SPM. Обратите внимание на файл Package.swift — это сердце вашего проекта. Отредактируем его, чтобы добавить зависимость от Apple/Swift ArgumentParser:

// swift-tools-version:5.9
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 build. SPM сам скачает библиотеку и соберёт проект. Если всё прошло успешно — вы готовы писать код!

Пишем первую команду: Hello World на стероидах

Откроем Sources/MyCLI/main.swift и напишем простейшую команду, которая выводит приветствие. Но не просто "Hello, World!", а с использованием аргументов:

import ArgumentParser

struct HelloCommand: ParsableCommand {
    static let configuration = CommandConfiguration(
        commandName: "hello",
        abstract: "Выводит приветствие",
        discussion: "Используйте эту команду, чтобы поприветствовать мир или конкретного человека."
    )

    @Argument(help: "Имя человека, которого нужно поприветствовать")
    var name: String = "World"

    @Option(name: .shortAndLong, help: "Количество повторов")
    var count: Int = 1

    func run() throws {
        for _ in 0..<count {
            print("Привет, \(name)! 👋")
        }
    }
}

HelloCommand.main()

Запустите: swift run MyCLI hello --count 3 "iOS Developer". Вы увидите:

Привет, iOS Developer! 👋
Привет, iOS Developer! 👋
Привет, iOS Developer! 👋

Обратите внимание: ArgumentParser сам сгенерировал справку. Попробуйте swift run MyCLI hello --help — вы получите красиво отформатированную документацию по вашей команде. Это одна из главных фишек создания CLI утилит на Swift — минимум кода, максимум пользы.

Продвинутый парсинг аргументов: флаги, подкоманды и валидация

Настоящие утилиты редко ограничиваются одной командой. Давайте добавим подкоманды и флаги. Представьте, что мы делаем инструмент для управления задачами (как мини-Todoist).

Структура подкоманд

import ArgumentParser

struct MyCLI: ParsableCommand {
    static let configuration = CommandConfiguration(
        commandName: "mytask",
        subcommands: [Add.self, List.self, Done.self],
        defaultSubcommand: List.self
    )
}

struct Add: ParsableCommand {
    static let configuration = CommandConfiguration(
        commandName: "add",
        abstract: "Добавить новую задачу"
    )

    @Argument(help: "Текст задачи")
    var task: String

    @Option(name: .shortAndLong, help: "Приоритет (1-5)")
    var priority: Int = 3

    func run() throws {
        guard priority >= 1 && priority <= 5 else {
            throw ValidationError("Приоритет должен быть от 1 до 5")
        }
        print("✅ Добавлена задача: \(task) [приоритет: \(priority)]")
    }
}

struct List: ParsableCommand {
    static let configuration = CommandConfiguration(
        commandName: "list",
        abstract: "Показать все задачи"
    )

    @Flag(name: .shortAndLong, help: "Показать только выполненные")
    var done: Bool = false

    func run() throws {
        if done {
            print("📋 Выполненные задачи:")
        } else {
            print("📋 Текущие задачи:")
        }
    }
}

struct Done: ParsableCommand {
    static let configuration = CommandConfiguration(
        commandName: "done",
        abstract: "Отметить задачу как выполненную"
    )

    @Argument(help: "ID задачи")
    var id: Int

    func run() throws {
        print("✅ Задача #\(id) выполнена!")
    }
}

MyCLI.main()

Теперь у нас три команды: mytask add, mytask list, mytask done. Флаг --done в команде list — это булевый флаг. Валидация встроена: если передать приоритет 6, вы получите понятную ошибку.

Такой подход делает создание инструментов командной строки на Swift невероятно удобным — вы сосредотачиваетесь на логике, а не на парсинге строк.

Цветной вывод и интерактивность

Скучный чёрно-белый вывод — прошлый век. Давайте добавим цвета с помощью ANSI-кодов. Это особенно полезно для CLI утилит на Swift, которые работают в современных терминалах.

                

Блоги

Рекомендаций по книгам