Swiftpack.co - Package - SDGGiesbrecht/SDGCommandLine


macOS • Linux

APIs: SDGCommandLine


SDGCommandLine provides tools for implementing a command line interface.

יְהַלְלוּ אֶת־שֵׁם יהוה כִּי הוּא צִוָּה וְנִבְרָאוּ׃
May they praise the name of the Lord, for He commanded and they came into being!

                                                                                                    ―a psalmist


  • Automatic parsing of options and subcommands
  • Automatic help subcommand
  • Testable output
  • Colour formatting tools
    • Automatic •no‐colour option
  • Interface localization
    • Automatic set‐language subcommand to set language preferences.
    • Automatic •language option to run in a specific language only once.
  • Versioning tools
    • Automatic version subcommand
    • Automatic •use‐version option to attempt to download and temporarily use a specific version instead of the one which is installed (only for public Swift packages).

(For a list of related projects, see here.)


SDGCommandLine is intended for use with the Swift Package Manager.

Simply add SDGCommandLine as a dependency in Package.swift:

let package = Package(
    name: "MyPackage",
    dependencies: [
        .package(url: "https://github.com/SDGGiesbrecht/SDGCommandLine", .upToNextMinor(from: Version(0, 1, 4))),
    targets: [
        .target(name: "MyTarget", dependencies: [
            .productItem(name: "SDGCommandLine", package: "SDGCommandLine"),

SDGCommandLine can then be imported in source files:

import SDGCommandLine

Example Usage

This example creates a tool with the following interface:

 $ parrot speak

 $ parrot speak •phrase "Hello, world!"
 Hello, world!

main.swift must consist of the following lines:

SDGCommandLine.initialize(applicationIdentifier: "tld.Developper.Parrot", version: Version(1, 0, 0), packageURL: URL(string: "https://website.tld/Parrot"))

The rest can be anywhere in the project (but putting it in a separate, testable library module is recommended):

import SDGCornerstone // See https://sdggiesbrecht.github.io/SDGCornerstone/macOS/
import SDGCommandLine

public let parrot = Command(name: UserFacingText<MyLocalizations, Void>({ _, _ in "parrot" }),
                            description: UserFacingText<MyLocalizations, Void>({ _, _ in "behaves like a parrot." }),
                            subcommands: [speak])

let speak = Command(name: UserFacingText<MyLocalizations, Void>({ _, _ in "speak" }),
                    description: UserFacingText<MyLocalizations, Void>({ _, _ in "speaks." }),
                    directArguments: [],
                    options: [phrase],
                    execution: { (_, options: Options, output: inout Command.Output) throws -> Void in

                        if let specific = options.value(for: phrase) {
                            print(specific, to: &output)
                        } else {
                            print("Squawk!", to: &output)

let phrase = Option<StrictString>(name: UserFacingText<MyLocalizations, Void>({ _, _ in "phrase" }),
                                  description: UserFacingText<MyLocalizations, Void>({ _, _ in "A custom phrase to speak." }),
                                  type: ArgumentType.string)

enum MyLocalizations : String, InputLocalization {
    case english = "en"
    internal static let cases: [MyLocalizations] = [.english]
    internal static let fallbackLocalization: MyLocalizations = .english

Tests are easy to set up:

func testParrot() {
    do {
        let output = try parrot.execute(with: ["speak", "•phrase", "Hello, world!"])
        XCTAssertEqual(output, "Hello, world!")
    } catch {
        XCTFail("The parrot is not co‐operating.")


The SDGCommandLine project is maintained by Jeremy David Giesbrecht.

If SDGCommandLine saves you money, consider giving some of it as a donation.

If SDGCommandLine saves you time, consider devoting some of it to contributing back to the project.

Ἄξιος γὰρ ὁ ἐργάτης τοῦ μισθοῦ αὐτοῦ ἐστι.
For the worker is worthy of his wages.



Stars: 1
Help us keep the lights on



0.1.4 - Dec 14, 2017

Bug Fixes

  • Performance optimizations to the build process used by •use‐version.

0.1.3 - Nov 22, 2017

Bug Fixes

  • Stability improvements to the build process used by •use‐version.

0.1.2 - Nov 11, 2017

No differences to published API.

0.1.1 - Nov 3, 2017

New Features

  • A new Command method, execute(withArguments:options:output), makes it easier to run one command within the execution of another.

0.1.0 - Oct 18, 2017

Initial Release