diff --git a/Package@swift-5.5.swift b/Package@swift-5.5.swift new file mode 100644 index 000000000..eb096c191 --- /dev/null +++ b/Package@swift-5.5.swift @@ -0,0 +1,76 @@ +// swift-tools-version:5.5 +//===----------------------------------------------------------*- swift -*-===// +// +// This source file is part of the Swift Argument Parser open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +import PackageDescription + +var package = Package( + name: "swift-argument-parser", + products: [ + .library( + name: "ArgumentParser", + targets: ["ArgumentParser"]), + ], + dependencies: [], + targets: [ + .target( + name: "ArgumentParser", + dependencies: ["ArgumentParserToolInfo"], + exclude: ["CMakeLists.txt"]), + .target( + name: "ArgumentParserTestHelpers", + dependencies: ["ArgumentParser", "ArgumentParserToolInfo"], + exclude: ["CMakeLists.txt"]), + .target( + name: "ArgumentParserToolInfo", + dependencies: [], + exclude: ["CMakeLists.txt"]), + + .executableTarget( + name: "roll", + dependencies: ["ArgumentParser"], + path: "Examples/roll"), + .executableTarget( + name: "math", + dependencies: ["ArgumentParser"], + path: "Examples/math"), + .executableTarget( + name: "repeat", + dependencies: ["ArgumentParser"], + path: "Examples/repeat"), + + .executableTarget( + name: "changelog-authors", + dependencies: ["ArgumentParser"], + path: "Tools/changelog-authors"), + + .testTarget( + name: "ArgumentParserEndToEndTests", + dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"], + exclude: ["CMakeLists.txt"]), + .testTarget( + name: "ArgumentParserUnitTests", + dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"], + exclude: ["CMakeLists.txt"]), + .testTarget( + name: "ArgumentParserExampleTests", + dependencies: ["ArgumentParserTestHelpers"]), + ] +) + +#if swift(>=5.2) +// Skip if < 5.2 to avoid issue with nested type synthesized 'CodingKeys' +package.targets.append( + .testTarget( + name: "ArgumentParserPackageManagerTests", + dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"], + exclude: ["CMakeLists.txt"])) +#endif diff --git a/Sources/ArgumentParser/Documentation.docc/ArgumentParser.md b/Sources/ArgumentParser/Documentation.docc/ArgumentParser.md new file mode 100644 index 000000000..04bb62300 --- /dev/null +++ b/Sources/ArgumentParser/Documentation.docc/ArgumentParser.md @@ -0,0 +1,104 @@ +# ``ArgumentParser`` + +Straightforward, type-safe argument parsing for Swift. + +## Overview + +By using `ArgumentParser`, you can create a command-line interface tool +by declaring simple Swift types. +Begin by declaring a type that defines +the information that you need to collect from the command line. +Decorate each stored property with one of `ArgumentParser`'s property wrappers, +declare conformance to ``ParsableCommand``, +and implement your command's logic in its `run()` method. + +```swift +import ArgumentParser + +@main +struct Repeat: ParsableCommand { + @Argument(help: "The phrase to repeat.") + var phrase: String + + @Option(help: "The number of times to repeat 'phrase'.") + var count: Int? + + mutating func run() throws { + let repeatCount = count ?? .max + for _ in 0..] + +ARGUMENTS: + The phrase to repeat. + +OPTIONS: + --count The number of times to repeat 'phrase'. + -h, --help Show help for this command. +$ repeat --count 3 +Error: Missing expected argument 'phrase'. +Help: The phrase to repeat. +Usage: repeat [--count ] + See 'repeat --help' for more information. +``` + +## Topics + +### Essentials + +- +- +- ``ParsableCommand`` + +### Arguments, Options, and Flags + +- +- ``Argument`` +- ``Option`` +- ``Flag`` +- ``OptionGroup`` +- ``ParsableArguments`` + +### Property Customization + +- +- ``ArgumentHelp`` +- ``NameSpecification`` + +### Custom Types + +- ``ExpressibleByArgument`` +- ``EnumerableFlag`` + +### Validation and Errors + +- +- ``ValidationError`` +- ``CleanExit`` +- ``ExitCode`` + +### Shell Completion Scripts + +- +- +- ``CompletionKind`` + +### Advanced Topics + +- diff --git a/Documentation/03 Commands and Subcommands.md b/Sources/ArgumentParser/Documentation.docc/Articles/CommandsAndSubcommands.md similarity index 98% rename from Documentation/03 Commands and Subcommands.md rename to Sources/ArgumentParser/Documentation.docc/Articles/CommandsAndSubcommands.md index 1825af795..e89cf5394 100644 --- a/Documentation/03 Commands and Subcommands.md +++ b/Sources/ArgumentParser/Documentation.docc/Articles/CommandsAndSubcommands.md @@ -1,5 +1,9 @@ # Defining Commands and Subcommands +Break complex command-line tools into a tree of subcommands. + +## Overview + When command-line programs grow larger, it can be useful to divide them into a group of smaller programs, providing an interface through subcommands. Utilities such as `git` and the Swift package manager are able to provide varied interfaces for each of their sub-functions by implementing subcommands such as `git branch` or `swift package init`. Generally, these subcommands each have their own configuration options, as well as options that are shared across several or all aspects of the larger program. diff --git a/Documentation/07 Completion Scripts.md b/Sources/ArgumentParser/Documentation.docc/Articles/CustomizingCompletions.md similarity index 51% rename from Documentation/07 Completion Scripts.md rename to Sources/ArgumentParser/Documentation.docc/Articles/CustomizingCompletions.md index 4cf0a411f..96137afe8 100644 --- a/Documentation/07 Completion Scripts.md +++ b/Sources/ArgumentParser/Documentation.docc/Articles/CustomizingCompletions.md @@ -1,64 +1,8 @@ -# Completion Scripts +# Customizing Completions -Generate customized completion scripts for your shell of choice. +Provide custom shell completions for your command-line tool's arguments and options. -## Generating and Installing Completion Scripts - -Command-line tools that you build with `ArgumentParser` include a built-in option for generating completion scripts, with support for Bash, Z shell, and Fish. To generate completions, run your command with the `--generate-completion-script` flag to generate completions for the autodetected shell, or with a value to generate completions for a specific shell. - -``` -$ example --generate-completion-script bash -#compdef example -local context state state_descr line -_example_commandname="example" -typeset -A opt_args - -_example() { - integer ret=1 - local -a args - ... -} - -_example -``` - -The correct method of installing a completion script depends on your shell and your configuration. - -### Installing Zsh Completions - -If you have [`oh-my-zsh`](https://ohmyz.sh) installed, you already have a directory of automatically loading completion scripts — `.oh-my-zsh/completions`. Copy your new completion script to that directory. - -``` -$ example --generate-completion-script zsh > ~/.oh-my-zsh/completions/_example -``` - -> Your completion script must have the following filename format: `_example`. - -Without `oh-my-zsh`, you'll need to add a path for completion scripts to your function path, and turn on completion script autoloading. First, add these lines to `~/.zshrc`: - -``` -fpath=(~/.zsh/completion $fpath) -autoload -U compinit -compinit -``` - -Next, create a directory at `~/.zsh/completion` and copy the completion script to the new directory. - -### Installing Bash Completions - -If you have [`bash-completion`](https://github.com/scop/bash-completion) installed, you can just copy your new completion script to the `/usr/local/etc/bash_completion.d` directory. - -Without `bash-completion`, you'll need to source the completion script directly. Copy it to a directory such as `~/.bash_completions/`, and then add the following line to `~/.bash_profile` or `~/.bashrc`: - -``` -source ~/.bash_completions/example.bash -``` - -### Installing Fish Completions - -Copy the completion script to any path listed in the environment variable `$fish_completion_path`. For example, a typical location is `~/.config/fish/completions/your_script.fish`. - -## Customizing Completions +## Overview `ArgumentParser` provides default completions for any types that it can. For example, an `@Option` property that is a `CaseIterable` type will automatically have the correct values as completion suggestions. diff --git a/Documentation/04 Customizing Help.md b/Sources/ArgumentParser/Documentation.docc/Articles/CustomizingHelp.md similarity index 99% rename from Documentation/04 Customizing Help.md rename to Sources/ArgumentParser/Documentation.docc/Articles/CustomizingHelp.md index f50546cdc..0bf674ad6 100644 --- a/Documentation/04 Customizing Help.md +++ b/Sources/ArgumentParser/Documentation.docc/Articles/CustomizingHelp.md @@ -2,6 +2,8 @@ Support your users (and yourself) by providing rich help for arguments and commands. +## Overview + You can provide help text when declaring any `@Argument`, `@Option`, or `@Flag` by passing a string literal as the `help` parameter: ```swift diff --git a/Documentation/02 Arguments, Options, and Flags.md b/Sources/ArgumentParser/Documentation.docc/Articles/DeclaringArguments.md similarity index 99% rename from Documentation/02 Arguments, Options, and Flags.md rename to Sources/ArgumentParser/Documentation.docc/Articles/DeclaringArguments.md index 886bc7fa4..e53834978 100644 --- a/Documentation/02 Arguments, Options, and Flags.md +++ b/Sources/ArgumentParser/Documentation.docc/Articles/DeclaringArguments.md @@ -2,6 +2,8 @@ Use the `@Argument`, `@Option` and `@Flag` property wrappers to declare the command-line interface for your command. +## Overview + When creating commands, you can define three primary kinds of command-line inputs: - *Arguments* are values given by a user and are read in order from first to last. For example, this command is called with three file names as arguments: diff --git a/Documentation/01 Getting Started.md b/Sources/ArgumentParser/Documentation.docc/Articles/GettingStarted.md similarity index 98% rename from Documentation/01 Getting Started.md rename to Sources/ArgumentParser/Documentation.docc/Articles/GettingStarted.md index 0a2e14e90..a9289637b 100644 --- a/Documentation/01 Getting Started.md +++ b/Sources/ArgumentParser/Documentation.docc/Articles/GettingStarted.md @@ -1,10 +1,12 @@ -# Getting Started with `ArgumentParser` +# Getting Started with ArgumentParser Learn to set up and customize a simple command-line tool. +## Overview + This guide walks through building an example command. You'll learn about the different tools that `ArgumentParser` provides for defining a command's options, customizing the interface, and providing help text for your user. -## Adding `ArgumentParser` as a Dependency +## Adding ArgumentParser as a Dependency Let's write a tool called `count` that reads an input file, counts the words, and writes the result to an output file. @@ -19,7 +21,7 @@ import PackageDescription let package = Package( name: "random", dependencies: [ - .package(url: "https://github.com/apple/swift-argument-parser.git", from: "0.5.0"), + .package(url: "https://github.com/apple/swift-argument-parser.git", from: "0.4.0"), ], targets: [ .target( diff --git a/Sources/ArgumentParser/Documentation.docc/Articles/InstallingCompletionScripts.md b/Sources/ArgumentParser/Documentation.docc/Articles/InstallingCompletionScripts.md new file mode 100644 index 000000000..24265bcaf --- /dev/null +++ b/Sources/ArgumentParser/Documentation.docc/Articles/InstallingCompletionScripts.md @@ -0,0 +1,59 @@ +# Generating and Installing Completion Scripts + +Install shell completion scripts generated by your command-line tool. + +## Overview + +Command-line tools that you build with `ArgumentParser` include a built-in option for generating completion scripts, with support for Bash, Z shell, and Fish. To generate completions, run your command with the `--generate-completion-script` option to generate completions for your specific shell. + +``` +$ example --generate-completion-script bash +#compdef example +local context state state_descr line +_example_commandname="example" +typeset -A opt_args + +_example() { + integer ret=1 + local -a args + ... +} + +_example +``` + +The correct method of installing a completion script can depend on both your shell and your configuration. + +### Installing Zsh Completions + +If you have [`oh-my-zsh`](https://ohmyz.sh) installed, you already have a directory of automatically loading completion scripts — `.oh-my-zsh/completions`. Copy your new completion script to that directory. + +``` +$ example --generate-completion-script zsh > ~/.oh-my-zsh/completions/_example +``` + +> Your completion script must have the following filename format: `_example`. + +Without `oh-my-zsh`, you'll need to add a path for completion scripts to your function path, and turn on completion script autoloading. First, add these lines to `~/.zshrc`: + +``` +fpath=(~/.zsh/completion $fpath) +autoload -U compinit +compinit +``` + +Next, create a directory at `~/.zsh/completion` and copy the completion script to the new directory. + +### Installing Bash Completions + +If you have [`bash-completion`](https://github.com/scop/bash-completion) installed, you can just copy your new completion script to the `/usr/local/etc/bash_completion.d` directory. + +Without `bash-completion`, you'll need to source the completion script directly. Copy it to a directory such as `~/.bash_completions/`, and then add the following line to `~/.bash_profile` or `~/.bashrc`: + +``` +source ~/.bash_completions/example.bash +``` + +### Installing Fish Completions + +Copy the completion script to any path listed in the environment variable `$fish_completion_path`. For example, a typical location is `~/.config/fish/completions/your_script.fish`. diff --git a/Documentation/06 Manual Parsing and Testing.md b/Sources/ArgumentParser/Documentation.docc/Articles/ManualParsing.md similarity index 98% rename from Documentation/06 Manual Parsing and Testing.md rename to Sources/ArgumentParser/Documentation.docc/Articles/ManualParsing.md index b7fc564b4..79a5f7da4 100644 --- a/Documentation/06 Manual Parsing and Testing.md +++ b/Sources/ArgumentParser/Documentation.docc/Articles/ManualParsing.md @@ -2,6 +2,8 @@ Provide your own array of command-line inputs and work with parsed results by calling alternatives to `main()`. +## Overview + For most programs, calling the static `main()` method on the root command type is all that's necessary. That single call parses the command-line arguments to find the correct command from your tree of nested subcommands, instantiates and validates the result, and executes the chosen command. For more control, however, you can perform each of those steps manually. ## Parsing Arguments @@ -28,7 +30,7 @@ The static `parseOrExit()` method either returns a fully initialized instance of We can perform validation on the inputs and exit the script if necessary: ```swift -guard options.elements.count >= options.count else { +guard let options.elements.count >= options.count else { let error = ValidationError("Please specify a 'count' less than the number of elements.") SelectOptions.exit(withError: error) } @@ -101,12 +103,3 @@ howdy howdy hi ``` - - - - - - - - - diff --git a/Documentation/05 Validation and Errors.md b/Sources/ArgumentParser/Documentation.docc/Articles/Validation.md similarity index 98% rename from Documentation/05 Validation and Errors.md rename to Sources/ArgumentParser/Documentation.docc/Articles/Validation.md index 941df831b..1aa0a87c9 100644 --- a/Documentation/05 Validation and Errors.md +++ b/Sources/ArgumentParser/Documentation.docc/Articles/Validation.md @@ -1,11 +1,13 @@ -# Validation and Errors +# Providing Custom Validation Provide helpful feedback to users when things go wrong. -## Validating Command-Line Input +## Overview While `ArgumentParser` validates that the inputs given by your user match the requirements and types that you define in each command, there are some requirements that can't easily be described in Swift's type system, such as the number of elements in an array, or an expected integer value. +### Validating Command-Line Input + To validate your commands properties after parsing, implement the `validate()` method on any `ParsableCommand` or `ParsableArguments` type. Throwing an error from the `validate()` method causes the program to print a message to standard error and exit with an error code, preventing the `run()` method from being called with invalid inputs. Here's a command that prints out one or more random elements from the list you provide. Its `validate()` method catches three different errors that a user can make and throws a relevant error for each one. diff --git a/Sources/ArgumentParser/Documentation.docc/Extensions/Argument.md b/Sources/ArgumentParser/Documentation.docc/Extensions/Argument.md new file mode 100644 index 000000000..63162d3f7 --- /dev/null +++ b/Sources/ArgumentParser/Documentation.docc/Extensions/Argument.md @@ -0,0 +1,25 @@ +# ``ArgumentParser/Argument`` + +## Topics + +### Single Arguments + +- ``init(help:completion:)-6pqzn`` +- ``init(help:completion:transform:)`` +- ``init(help:completion:)-4p94d`` +- ``init(wrappedValue:help:completion:)`` +- ``init(wrappedValue:help:completion:transform:)`` + +### Array Arguments + +- ``init(parsing:help:completion:)`` +- ``init(parsing:help:completion:transform:)`` +- ``init(wrappedValue:parsing:help:completion:)`` +- ``init(wrappedValue:parsing:help:completion:transform:)`` +- ``ArgumentArrayParsingStrategy`` + +### Infrequently Used APIs + +- ``init()`` +- ``init(from:)`` +- ``wrappedValue`` diff --git a/Sources/ArgumentParser/Documentation.docc/Extensions/Flag.md b/Sources/ArgumentParser/Documentation.docc/Extensions/Flag.md new file mode 100644 index 000000000..d2be6d8cd --- /dev/null +++ b/Sources/ArgumentParser/Documentation.docc/Extensions/Flag.md @@ -0,0 +1,43 @@ +# ``ArgumentParser/Flag`` + +## Topics + +### Boolean Flags + +- ``init(wrappedValue:name:help:)`` + +### Boolean Flags with Inversions + +- ``init(wrappedValue:name:inversion:exclusivity:help:)`` +- ``init(name:inversion:exclusivity:help:)-12okg`` +- ``init(name:inversion:exclusivity:help:)-1h8f7`` +- ``FlagInversion`` + +### Counted Flags + +- ``init(name:help:)-87c7k`` + +### Custom Enumerable Flags + +- ``init(help:)`` +- ``init(exclusivity:help:)-38n7u`` +- ``init(exclusivity:help:)-5fggj`` +- ``init(wrappedValue:exclusivity:help:)`` +- ``init(wrappedValue:help:)`` + +### Infrequently Used APIs + +- ``init(from:)`` +- ``wrappedValue`` + +### Supporting Types + +- ``FlagExclusivity`` + +### Deprecated APIs + +- ``init()`` +- ``init(name:default:exclusivity:help:)`` +- ``init(name:help:)-5iirr`` +- ``init(name:exclusivity:help:)`` +- ``init(name:exclusivity:help:)`` diff --git a/Sources/ArgumentParser/Documentation.docc/Extensions/Option.md b/Sources/ArgumentParser/Documentation.docc/Extensions/Option.md new file mode 100644 index 000000000..3fb9983fc --- /dev/null +++ b/Sources/ArgumentParser/Documentation.docc/Extensions/Option.md @@ -0,0 +1,26 @@ +# ``ArgumentParser/Option`` + +## Topics + +### Single Options + +- ``init(name:parsing:help:completion:)-4yske`` +- ``init(name:parsing:help:completion:)-7slrf`` +- ``init(name:parsing:help:completion:transform:)-2wf44`` +- ``init(wrappedValue:name:parsing:completion:help:)`` +- ``init(wrappedValue:name:parsing:help:completion:transform:)-2llve`` +- ``SingleValueParsingStrategy`` + +### Array Options + +- ``init(name:parsing:help:completion:)-238hg`` +- ``init(name:parsing:help:completion:transform:)-74hnp`` +- ``init(wrappedValue:name:parsing:help:completion:)`` +- ``init(wrappedValue:name:parsing:help:completion:transform:)-1kpto`` +- ``ArrayParsingStrategy`` + +### Infrequently Used APIs + +- ``init()`` +- ``init(from:)`` +- ``wrappedValue`` diff --git a/Sources/ArgumentParser/Documentation.docc/Extensions/ParsableArguments.md b/Sources/ArgumentParser/Documentation.docc/Extensions/ParsableArguments.md new file mode 100644 index 000000000..e4c0ece92 --- /dev/null +++ b/Sources/ArgumentParser/Documentation.docc/Extensions/ParsableArguments.md @@ -0,0 +1,37 @@ +# ``ArgumentParser/ParsableArguments`` + +## Topics + + + +### Handling Validation + +- ``validate()-5r0ge`` + +### Parsing a Type + +- ``parse(_:)`` +- ``parseOrExit(_:)`` + +### Exiting a Program + +- ``exit(withError:)`` + +### Generating Help Text + +- ``helpMessage(columns:)`` + +### Handling Errors + +- ``message(for:)`` +- ``fullMessage(for:)`` +- ``exitCode(for:)`` + +### Generating Completion Scripts + +- ``completionScript(for:)`` +- ``CompletionShell`` + +### Infrequently Used APIs + +- ``init()`` diff --git a/Sources/ArgumentParser/Documentation.docc/Extensions/ParsableCommand.md b/Sources/ArgumentParser/Documentation.docc/Extensions/ParsableCommand.md new file mode 100644 index 000000000..d7e3400d3 --- /dev/null +++ b/Sources/ArgumentParser/Documentation.docc/Extensions/ParsableCommand.md @@ -0,0 +1,26 @@ +# ``ArgumentParser/ParsableCommand`` + +## Topics + +### Implementing a Command's Behavior + +- ``run()-7p2fr`` + +### Customizing a Command + +- ``configuration-35km1`` +- ``CommandConfiguration`` + +### Generating Help Text + +- ``helpMessage(for:columns:)`` + +### Starting the Program + +- ``main(_:)`` +- ``main()`` + +### Manually Parsing Input + +- ``parseAsRoot(_:)`` + diff --git a/Sources/ArgumentParser/Parsable Properties/Argument.swift b/Sources/ArgumentParser/Parsable Properties/Argument.swift index 9a4a1e8e9..d6eb9c2f3 100644 --- a/Sources/ArgumentParser/Parsable Properties/Argument.swift +++ b/Sources/ArgumentParser/Parsable Properties/Argument.swift @@ -9,19 +9,36 @@ // //===----------------------------------------------------------------------===// -/// A wrapper that represents a positional command-line argument. +/// A property wrapper that represents a positional command-line argument. /// -/// Positional arguments are specified without a label and must appear in -/// the command-line arguments in declaration order. +/// Use the `@Argument` wrapper to define a property of your custom command as +/// a positional argument. A *positional argument* for a command-line tool is +/// specified without a label and must appear in declaration order. `@Argument` +/// properties with `Optional` type or a default value are optional for the user +/// of your command-line tool. /// -/// struct Options: ParsableArguments { +/// For example, the following program has two positional arguments. The `name` +/// argument is required, while `greeting` is optional because it has a default +/// value. +/// +/// @main +/// struct Greet: ParsableCommand { /// @Argument var name: String -/// @Argument var greeting: String? +/// @Argument var greeting: String = "Hello" +/// +/// mutating func run() { +/// print("\(greeting) \(name)!") +/// } /// } /// -/// This program has two positional arguments; `name` is required, while -/// `greeting` is optional. It can be evoked as either `command Joseph Hello` -/// or simply `command Joseph`. +/// You can call this program with just a name or with a name and a +/// greeting. When you supply both arguments, the first argument is always +/// treated as the name, due to the order of the property declarations. +/// +/// $ greet Nadia +/// Hello Nadia! +/// $ greet Tamara Hi +/// Hi Tamara! @propertyWrapper public struct Argument: Decodable, ParsedWrapper diff --git a/Sources/ArgumentParser/Parsable Properties/Flag.swift b/Sources/ArgumentParser/Parsable Properties/Flag.swift index 3379147c7..3415e5199 100644 --- a/Sources/ArgumentParser/Parsable Properties/Flag.swift +++ b/Sources/ArgumentParser/Parsable Properties/Flag.swift @@ -9,33 +9,63 @@ // //===----------------------------------------------------------------------===// -/// A wrapper that represents a command-line flag. +/// A property wrapper that represents a command-line flag. /// -/// A flag is a defaulted Boolean or integer value that can be changed by -/// specifying the flag on the command line. For example: +/// Use the `@Flag` wrapper to define a property of your custom type as a +/// command-line flag. A *flag* is a dash-prefixed label that can be provided on +/// the command line, such as `-d` and `--debug`. /// -/// struct Options: ParsableArguments { -/// @Flag var verbose: Bool +/// For example, the following program declares a flag that lets a user indicate +/// that seconds should be included when printing the time. +/// +/// @main +/// struct Time: ParsableCommand { +/// @Flag var includeSeconds = false +/// +/// mutating func run() { +/// if includeSeconds { +/// print(Date.now.formatted(.dateTime.hour().minute().second())) +/// } else { +/// print(Date.now.formatted(.dateTime.hour().minute())) +/// } +/// } /// } /// -/// `verbose` has a default value of `false`, but becomes `true` if `--verbose` -/// is provided on the command line. +/// `includeSeconds` has a default value of `false`, but becomes `true` if +/// `--include-seconds` is provided on the command line. +/// +/// $ time +/// 11:09 AM +/// $ time --include-seconds +/// 11:09:15 AM /// /// A flag can have a value that is a `Bool`, an `Int`, or any `EnumerableFlag` /// type. When using an `EnumerableFlag` type as a flag, the individual cases /// form the flags that are used on the command line. /// -/// struct Options { +/// @main +/// struct Math: ParsableCommand { /// enum Operation: EnumerableFlag { /// case add /// case multiply /// } /// /// @Flag var operation: Operation +/// +/// mutating func run() { +/// print("Time to \(operation)!") +/// } /// } /// -/// // usage: command --add -/// // or: command --multiply +/// Instead of using the name of the `operation` property as the flag in this +/// case, the two cases of the `Operation` enumeration become valid flags. +/// The `operation` property is neither optional nor given a default value, so +/// one of the two flags is required. +/// +/// $ math --add +/// Time to add! +/// $ math +/// Error: Missing one of: '--add', '--multiply' @propertyWrapper public struct Flag: Decodable, ParsedWrapper { internal var _parsedValue: Parsed diff --git a/Sources/ArgumentParser/Parsable Properties/NameSpecification.swift b/Sources/ArgumentParser/Parsable Properties/NameSpecification.swift index aa6747427..7a71c24a7 100644 --- a/Sources/ArgumentParser/Parsable Properties/NameSpecification.swift +++ b/Sources/ArgumentParser/Parsable Properties/NameSpecification.swift @@ -12,6 +12,7 @@ /// A specification for how to represent a property as a command-line argument /// label. public struct NameSpecification: ExpressibleByArrayLiteral { + /// An individual property name translation. public struct Element: Hashable { internal enum Representation: Hashable { case long diff --git a/Sources/ArgumentParser/Parsable Properties/Option.swift b/Sources/ArgumentParser/Parsable Properties/Option.swift index da61f3823..7ef15f9c6 100644 --- a/Sources/ArgumentParser/Parsable Properties/Option.swift +++ b/Sources/ArgumentParser/Parsable Properties/Option.swift @@ -9,23 +9,43 @@ // //===----------------------------------------------------------------------===// -/// A wrapper that represents a command-line option. +/// A property wrapper that represents a command-line option. /// -/// An option is a value that can be specified as a named value on the command -/// line. An option can have a default values specified as part of its +/// Use the `@Option` wrapper to define a property of your custom command as a +/// command-line option. An *option* is a named value passed to a command-line +/// tool, like `--configuration debug`. Options can be specified in any order. +/// +/// An option can have a default value specified as part of its /// declaration; options with optional `Value` types implicitly have `nil` as -/// their default value. +/// their default value. Options that are neither declared as `Optional` nor +/// given a default value are required for users of your command-line tool. /// -/// struct Options: ParsableArguments { -/// @Option(default: "Hello") var greeting: String -/// @Option var name: String +/// For example, the following program defines three options: +/// +/// @main +/// struct Greet: ParsableCommand { +/// @Option var greeting = "Hello" /// @Option var age: Int? +/// @Option var name: String +/// +/// mutating func run() { +/// print("\(greeting) \(name)!") +/// if let age = age { +/// print("Congrats on making it to the ripe old age of \(age)!") +/// } +/// } /// } /// /// `greeting` has a default value of `"Hello"`, which can be overridden by -/// providing a different string as an argument. `age` defaults to `nil`, while -/// `name` is a required argument because it is non-`nil` and has no default +/// providing a different string as an argument, while `age` defaults to `nil`. +/// `name` is a required option because it is non-`nil` and has no default /// value. +/// +/// $ greet --name Alicia +/// Hello Alicia! +/// $ greet --age 28 --name Seungchin --greeting Hi +/// Hi Seungchin! +/// Congrats on making it to the ripe old age of 28! @propertyWrapper public struct Option: Decodable, ParsedWrapper { internal var _parsedValue: Parsed