├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── CommandLineKit.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ ├── CommandLineKit.xcscheme
│ └── CommandLineKitDemo.xcscheme
├── CommandLineKitDemo
└── main.swift
├── LICENSE
├── Package.swift
├── README.md
├── Sources
├── CommandLineKit
│ ├── AnsiCodes.swift
│ ├── BackgroundColor.swift
│ ├── Command.swift
│ ├── CommandLineKit.h
│ ├── ControlCharacters.swift
│ ├── ConvertibleFromString.swift
│ ├── EditState.swift
│ ├── Flag.swift
│ ├── FlagError.swift
│ ├── FlagWrapper.swift
│ ├── Flags.swift
│ ├── Info.plist
│ ├── LineReader.swift
│ ├── LineReaderError.swift
│ ├── LineReaderHistory.swift
│ ├── Terminal.swift
│ ├── TextColor.swift
│ ├── TextProperties.swift
│ └── TextStyle.swift
└── CommandLineKitDemo
│ ├── Info.plist
│ ├── LinuxMain.swift
│ └── main.swift
└── Tests
├── CommandLineKitTests
├── AnsiCodesTests.swift
├── EditStateTests.swift
├── FlagTests.swift
├── Info.plist
└── LineReaderHistoryTests.swift
└── LinuxMain.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | .build
36 | Packages
37 |
38 | # CocoaPods
39 | #
40 | # We recommend against adding the Pods directory to your .gitignore. However
41 | # you should judge for yourself, the pros and cons are mentioned at:
42 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
43 | #
44 | # Pods/
45 |
46 | # Carthage
47 | #
48 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
49 | # Carthage/Checkouts
50 |
51 | Carthage/Build
52 |
53 | # macOS
54 | .DS_Store
55 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | # 0.3.5 (2023-01-29)
4 | - Be more clever about detecting color terminals
5 | - Migrate project to Xcode 14.2
6 |
7 | ## 0.3.4 (2021-05-12)
8 | - Minor bug fixes
9 | - Migrated project to Xcode 12.5
10 |
11 | ## 0.3.3 (2020-10-04)
12 | - Ported code to Swift 5.3
13 | - Migrated project to Xcode 12.0
14 |
15 | ## 0.3.2 (2020-02-01)
16 | - Fixed line reader to handle buffered output
17 | - Migrated project to Xcode 11.3
18 |
19 | ## 0.3.1 (2019-09-23)
20 | - Migrated project to Xcode 11.0
21 | - Ported code to Swift 5.1
22 |
23 | ## 0.3 (2019-03-30)
24 | - Migrated library to Xcode 10.2
25 | - Ported code to Swift 5
26 |
27 | ## 0.2 (2018-06-10)
28 | - Bug fixes
29 | - Support of usage descriptions
30 | - Initial documentation
31 |
32 | ## 0.1 (2018-05-14)
33 | - Initial version
34 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
25 | ## Community Guidelines
26 |
27 | This project follows [Google's Open Source Community
28 | Guidelines](https://opensource.google.com/conduct/).
29 |
--------------------------------------------------------------------------------
/CommandLineKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CommandLineKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CommandLineKit.xcodeproj/xcshareddata/xcschemes/CommandLineKit.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
63 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/CommandLineKit.xcodeproj/xcshareddata/xcschemes/CommandLineKitDemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
64 |
70 |
71 |
72 |
73 |
77 |
78 |
79 |
80 |
86 |
88 |
94 |
95 |
96 |
97 |
99 |
100 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/CommandLineKitDemo/main.swift:
--------------------------------------------------------------------------------
1 | //
2 | // main.swift
3 | // CommandLineKitDemo
4 | //
5 | // Created by Matthias Zenger on 26/10/2023.
6 | // Copyright © 2023 Matthias Zenger. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | print("Hello, World!")
12 |
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright © 2018-2019 Google LLC
2 | Copyright © 2017 Andy Best
3 | Copyright © 2010-2014 Salvatore Sanfilippo
4 | Copyright © 2010-2013 Pieter Noordhuis
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice,
10 | this list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its contributors
17 | may be used to endorse or promote products derived from this software without
18 | specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
24 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.4
2 | //
3 | // Package.swift
4 | // CommandLineKit
5 | //
6 | // Build targets by calling the Swift Package Manager in the following way for debug purposes:
7 | // swift build
8 | //
9 | // A release can be built with these options:
10 | // swift build -c release
11 | //
12 | // Created by Matthias Zenger on 06/05/2017.
13 | // Copyright © 2018-2023 Google LLC
14 | //
15 | // Redistribution and use in source and binary forms, with or without
16 | // modification, are permitted provided that the following conditions are met:
17 | //
18 | // * Redistributions of source code must retain the above copyright notice,
19 | // this list of conditions and the following disclaimer.
20 | //
21 | // * Redistributions in binary form must reproduce the above copyright notice,
22 | // this list of conditions and the following disclaimer in the documentation
23 | // and/or other materials provided with the distribution.
24 | //
25 | // * Neither the name of the copyright holder nor the names of its contributors
26 | // may be used to endorse or promote products derived from this software without
27 | // specific prior written permission.
28 | //
29 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
33 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
36 | // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 | //
40 |
41 | import PackageDescription
42 |
43 | let package = Package(
44 | name: "CommandLineKit",
45 | platforms: [
46 | .macOS(.v11)
47 | ],
48 | products: [
49 | .library(name: "CommandLineKit", targets: ["CommandLineKit"]),
50 | .executable(name: "CommandLineKitDemo", targets: ["CommandLineKitDemo"])
51 | ],
52 | dependencies: [
53 | ],
54 | targets: [
55 | .target(name: "CommandLineKit",
56 | dependencies: [],
57 | exclude: ["Info.plist"]),
58 | .executableTarget(name: "CommandLineKitDemo",
59 | dependencies: ["CommandLineKit"],
60 | exclude: []),
61 | .testTarget(name: "CommandLineKitTests",
62 | dependencies: ["CommandLineKit"],
63 | exclude: ["Info.plist"])
64 | ],
65 | swiftLanguageVersions: [.v5]
66 | )
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift CommandLineKit
2 |
3 | [](https://developer.apple.com/osx/)
4 | [](https://www.ubuntu.com/)
5 | [](https://developer.apple.com/swift/)
6 | [](https://developer.apple.com/xcode/)
7 | [](https://github.com/Carthage/Carthage)
8 | [](https://developers.google.com/open-source/licenses/bsd)
9 |
10 | ## Overview
11 |
12 | This is a library supporting the development of command-line tools in
13 | the programming language Swift on macOS. It also compiles under Linux.
14 | The library provides the following functionality:
15 |
16 | - Management of command-line arguments,
17 | - Usage of escape sequences on terminals, and
18 | - Reading strings on terminals using a lineread-inspired implementation
19 | based on the library [Linenoise-Swift](https://github.com/andybest/linenoise-swift),
20 | but supporting unicode input, multiple lines, and styled text.
21 |
22 | ## Command-line arguments
23 |
24 | ### Basics
25 |
26 | CommandLineKit handles command-line arguments with the following protocol:
27 |
28 | 1. A new [Flags](https://github.com/objecthub/swift-commandlinekit/blob/master/Sources/CommandLineKit/Flags.swift)
29 | object gets created either for the system-provided command-line arguments or for a
30 | custom sequence of arguments.
31 | 2. For every flag, a [Flag](https://github.com/objecthub/swift-commandlinekit/blob/master/Sources/CommandLineKit/Flag.swift)
32 | object is being created and registered in the `Flags` object.
33 | 3. Once all flag objects are declared and registered, the command-line gets parsed. After parsing
34 | is complete, the flag objects can be used to access the extracted options and arguments.
35 |
36 | CommandLineKit defines different types of
37 | [Flag](https://github.com/objecthub/swift-commandlinekit/blob/master/Sources/CommandLineKit/Flag.swift)
38 | subclasses for handling _options_ (i.e. flags without
39 | parameters) and _arguments_ (i.e. flags with parameters). Arguments are either _singleton arguments_ (i.e. they
40 | have exactly one value) or they are _repeated arguments_ (i.e. they have many values). Arguments are
41 | parameterized with a type which defines how to parse values. The framework natively supports _int_,
42 | _double_, _string_, and _enum_ types, which means that in practice, just using the built-in flag classes
43 | are almost always sufficient. Nevertheless,
44 | [the framework is extensible](https://github.com/objecthub/swift-commandlinekit/tree/master/Sources/CommandLineKit)
45 | and supports arbitrary argument types.
46 |
47 | A flag is identified by a _short name_ character and a _long name_ string. At least one of the two needs to be
48 | defined. For instance, the "help" option could be defined by the short name "h" and the long name "help".
49 | On the command-line, a user could either use `-h` or `--help` to refer to this option; i.e. short names are
50 | prefixed with a single dash, long names are prefixed with a double dash.
51 |
52 | An argument is a parameterized flag. The parameters follow directly the flag identifier (typically separated by
53 | a space). For instance, an integer argument with long name "size" could be defined as: `--size 64`. If the
54 | argument is repeated, then multiple parameters may follow the flag identifier, as in this
55 | example: `--size 2 4 8 16`. The sequence is terminated by either the end of the command-line arguments,
56 | another flag, or the terminator "---". All command-line arguments following the terminator are not being parsed
57 | and are returned in the `parameters` field of the `Flags` object.
58 |
59 | ### Programmatic API
60 |
61 | Here is an [example](https://github.com/objecthub/swift-lispkit/blob/master/Sources/LispKitRepl/main.swift)
62 | from the [LispKit](https://github.com/objecthub/swift-lispkit) project. It uses factory methods (like `flags.string`,
63 | `flags.int`, `flags.option`, `flags.strings`, etc.) provided by the
64 | [Flags](https://github.com/objecthub/swift-commandlinekit/blob/master/Sources/CommandLineKit/Flags.swift)
65 | class to create and register individual flags.
66 |
67 | ```swift
68 | // Create a new flags object for the system-provided command-line arguments
69 | var flags = Flags()
70 |
71 | // Define the various flags
72 | let filePaths = flags.strings("f", "filepath",
73 | description: "Adds file path in which programs are searched for.")
74 | let libPaths = flags.strings("l", "libpath",
75 | description: "Adds file path in which libraries are searched for.")
76 | let heapSize = flags.int("x", "heapsize",
77 | description: "Initial capacity of the heap", value: 1000)
78 | let importLibs = flags.strings("i", "import",
79 | description: "Imports library automatically after startup.")
80 | let prelude = flags.string("p", "prelude",
81 | description: "Path to prelude file which gets executed after " +
82 | "loading all provided libraries.")
83 | let prompt = flags.string("r", "prompt",
84 | description: "String used as prompt in REPL.", value: "> ")
85 | let quiet = flags.option("q", "quiet",
86 | description: "In quiet mode, optional messages are not printed.")
87 | let help = flags.option("h", "help",
88 | description: "Show description of usage and options of this tools.")
89 |
90 | // Parse the command-line arguments and return error message if parsing fails
91 | if let failure = flags.parsingFailure() {
92 | print(failure)
93 | exit(1)
94 | }
95 | ```
96 |
97 | The framework supports printing the supported options via the `Flags.usageDescription` function. For the
98 | command-line flags as defined above, this function returns the following usage description:
99 |
100 | ```
101 | usage: LispKitRepl [