Skip to content

Commit 35ceb59

Browse files
authored
Nate/continue default initialization (#193)
* Use type inference for flags / options * Use default value syntax for arg/option arrays * Allow a default for flag arrays * Fix some whitespace * Allow arguments validations to warn instead of fail * Move nonsense flag warning to argument validation * Update guides/readme with default literal syntax
1 parent c0f9a5f commit 35ceb59

29 files changed

+462
-265
lines changed

Documentation/01 Getting Started.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct Count: ParsableCommand {
133133
var outputFile: String
134134

135135
@Flag()
136-
var verbose: Bool
136+
var verbose = false
137137

138138
mutating func run() throws {
139139
if verbose {
@@ -175,7 +175,7 @@ struct Count: ParsableCommand {
175175
var outputFile: String
176176

177177
@Flag(name: .shortAndLong)
178-
var verbose: Bool
178+
var verbose = false
179179

180180
mutating func run() throws { ... }
181181
}
@@ -209,7 +209,7 @@ struct Count: ParsableCommand {
209209
var outputFile: String
210210

211211
@Flag(name: .shortAndLong, help: "Print status updates while counting.")
212-
var verbose: Bool
212+
var verbose = false
213213

214214
mutating func run() throws { ... }
215215
}
@@ -244,7 +244,7 @@ struct Count: ParsableCommand {
244244
var outputFile: String
245245

246246
@Flag(name: .shortAndLong, help: "Print status updates while counting.")
247-
var verbose: Bool
247+
var verbose = false
248248

249249
mutating func run() throws {
250250
if verbose {

Documentation/02 Arguments, Options, and Flags.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,24 @@ The three preceding examples could be calls of this `Example` command:
2626

2727
```swift
2828
struct Example: ParsableCommand {
29-
@Argument() var files: [String]
29+
@Argument() var files: [String] = []
3030

3131
@Option() var count: Int?
3232

33-
@Option var index: Int = 0
33+
@Option() var index = 0
3434

35-
@Flag() var verbose: Bool
35+
@Flag() var verbose = false
3636

37-
@Flag() var stripWhitespace: Bool
37+
@Flag() var stripWhitespace = false
3838
}
3939
```
4040

4141
This example shows how `ArgumentParser` provides defaults that speed up your initial development process:
4242

4343
- Option and flag names are derived from the names of your command's properties.
44-
- Whether arguments are required and what kinds of inputs are valid is based on your properties' types.
44+
- What kinds of inputs are valid, and whether arguments are required, is based on your properties' types and default values.
4545

46-
In this example, all of the properties have default values — Boolean flags always default to `false`, optional properties default to `nil`, and arrays default to an empty array. An option, flag, or argument with a `default` parameter can also be omitted by the user.
46+
In this example, all of the properties have default values (optional properties default to `nil`).
4747

4848
Users must provide values for all properties with no implicit or specified default. For example, this command would require one integer argument and a string with the key `--user-name`.
4949

@@ -70,12 +70,12 @@ Usage: example --user-name <user-name> <value>
7070
See 'example --help' for more information.
7171
```
7272

73-
When using the `default` parameter for an array property, the default values will not be included if additional values are passed on the command line.
73+
When providing a default value for an array property, any user-supplied values replace the entire default.
7474

75-
```
75+
```swift
7676
struct Lucky: ParsableCommand {
77-
@Argument(default: [7, 14, 21])
78-
var numbers: [Int]
77+
@Argument()
78+
var numbers = [7, 14, 21]
7979

8080
mutating func run() throws {
8181
print("""
@@ -104,10 +104,10 @@ You can override this default by specifying one or more name specifications in t
104104
```swift
105105
struct Example: ParsableCommand {
106106
@Flag(name: .long) // Same as the default
107-
var stripWhitespace: Bool
107+
var stripWhitespace = false
108108

109109
@Flag(name: .short)
110-
var verbose: Bool
110+
var verbose = false
111111

112112
@Option(name: .customLong("count"))
113113
var iterationCount: Int
@@ -214,7 +214,7 @@ Flags are most frequently used for `Bool` properties. You can generate a `true`/
214214
```swift
215215
struct Example: ParsableCommand {
216216
@Flag(inversion: .prefixedNo)
217-
var index: Bool = true
217+
var index = true
218218

219219
@Flag(inversion: .prefixedEnableDisable)
220220
var requiredElement: Bool
@@ -225,7 +225,7 @@ struct Example: ParsableCommand {
225225
}
226226
```
227227

228-
When providing a flag inversion, you can pass your own default with normal property initialization syntax (`@Flag var foo: Bool = true`). If you want to require that the user specify one of the two inversions, use a non-Optional type and do not pass a default value.
228+
When declaring a flag with an inversion, set the default by specifying `true` or `false` as the property's initial value. If you want to require that the user specify one of the two inversions, leave off the default value.
229229

230230
In the `Example` command defined above, a flag is required for the `requiredElement` property. The specified prefixes are prepended to the long names for the flags:
231231

@@ -241,19 +241,19 @@ Error: Missing one of: '--enable-required-element', '--disable-required-element'
241241
To create a flag with custom names for a Boolean value, to provide an exclusive choice between more than two names, or for collecting multiple values from a set of defined choices, define an enumeration that conforms to the `EnumerableFlag` protocol.
242242

243243
```swift
244-
enum CacheMethod: EnumerableFlag {
244+
enum CacheMethod: String, EnumerableFlag {
245245
case inMemoryCache
246246
case persistentCache
247247
}
248248

249-
enum Color: EnumerableFlag {
249+
enum Color: String, EnumerableFlag {
250250
case pink, purple, silver
251251
}
252252

253253
struct Example: ParsableCommand {
254254
@Flag() var cacheMethod: CacheMethod
255255

256-
@Flag() var colors: [Color]
256+
@Flag() var colors: [Color] = []
257257

258258
mutating func run() throws {
259259
print(cacheMethod)
@@ -302,7 +302,7 @@ For example, this command defines a `--verbose` flag, a `--name` option, and an
302302

303303
```swift
304304
struct Example: ParsableCommand {
305-
@Flag() var verbose: Bool
305+
@Flag() var verbose = false
306306
@Option() var name: String
307307
@Argument() var file: String?
308308

@@ -349,8 +349,8 @@ The default strategy for parsing options as arrays is to read each value from a
349349

350350
```swift
351351
struct Example: ParsableCommand {
352-
@Option() var file: [String]
353-
@Flag() var verbose: Bool
352+
@Option() var file: [String] = []
353+
@Flag() var verbose = false
354354

355355
mutating func run() throws {
356356
print("Verbose: \(verbose), files: \(file)")
@@ -400,8 +400,8 @@ The default strategy for parsing arrays of positional arguments is to ignore al
400400

401401
```swift
402402
struct Example: ParsableCommand {
403-
@Flag() var verbose: Bool
404-
@Argument() var files: [String]
403+
@Flag() var verbose = false
404+
@Argument() var files: [String] = []
405405

406406
mutating func run() throws {
407407
print("Verbose: \(verbose), files: \(files)")

Documentation/03 Commands and Subcommands.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ In this case, the `Options` type accepts a `--hexadecimal-output` flag and expec
5656
```swift
5757
struct Options: ParsableArguments {
5858
@Flag(name: [.long, .customShort("x")], help: "Use hexadecimal notation for the result.")
59-
var hexadecimalOutput: Bool
59+
var hexadecimalOutput = false
6060

6161
@Argument(help: "A group of integers to operate on.")
6262
var values: [Int]
@@ -124,7 +124,7 @@ extension Math.Statistics {
124124
var kind: Kind = .mean
125125

126126
@Argument(help: "A group of floating-point values to operate on.")
127-
var values: [Double]
127+
var values: [Double] = []
128128

129129
func calculateMean() -> Double { ... }
130130
func calculateMedian() -> Double { ... }
@@ -151,7 +151,7 @@ extension Math.Statistics {
151151
abstract: "Print the standard deviation of the values.")
152152

153153
@Argument(help: "A group of floating-point values to operate on.")
154-
var values: [Double]
154+
var values: [Double] = []
155155

156156
mutating func run() {
157157
if values.isEmpty {

Documentation/04 Customizing Help.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ You can provide help text when declaring any `@Argument`, `@Option`, or `@Flag`
77
```swift
88
struct Example: ParsableCommand {
99
@Flag(help: "Display extra information while processing.")
10-
var verbose: Bool
10+
var verbose = false
1111

1212
@Option(help: "The number of extra lines to show.")
13-
var extraLines: Int = 0
13+
var extraLines = 0
1414

1515
@Argument(help: "The input file.")
1616
var inputFile: String?
@@ -42,12 +42,12 @@ Here's the same command with some extra customization:
4242
```swift
4343
struct Example: ParsableCommand {
4444
@Flag(help: "Display extra information while processing.")
45-
var verbose: Bool
45+
var verbose = false
4646

4747
@Option(help: ArgumentHelp(
4848
"The number of extra lines to show.",
4949
valueName: "n"))
50-
var extraLines: Int = 0
50+
var extraLines = 0
5151

5252
@Argument(help: ArgumentHelp(
5353
"The input file.",

Documentation/05 Validation and Errors.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct Select: ParsableCommand {
1616
var count: Int = 1
1717

1818
@Argument()
19-
var elements: [String]
19+
var elements: [String] = []
2020

2121
mutating func validate() throws {
2222
guard count >= 1 else {
@@ -127,12 +127,11 @@ struct ExampleDataModel: Codable {
127127
}
128128

129129
struct Example: ParsableCommand {
130-
131130
// Reads in the argument string and attempts to transform it to
132131
// an `ExampleDataModel` object using the `JSONDecoder`. If the
133132
// string is not valid JSON, `decode` will throw an error and
134133
// parsing will halt.
135-
@Argument(transform: ExampleDataModel.dataModel )
134+
@Argument(transform: ExampleDataModel.dataModel)
136135
var inputJSON: ExampleDataModel
137136

138137
// Specifiying this option will always cause the parser to exit

Documentation/06 Manual Parsing and Testing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ Let's implement the `Select` command discussed in [Validation and Errors](05%20V
1212

1313
```swift
1414
struct SelectOptions: ParsableArguments {
15-
@Option
15+
@Option()
1616
var count: Int = 1
1717

1818
@Argument()
19-
var elements: [String]
19+
var elements: [String] = []
2020
}
2121
```
2222

Examples/math/main.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ struct Math: ParsableCommand {
3535
struct Options: ParsableArguments {
3636
@Flag(name: [.customLong("hex-output"), .customShort("x")],
3737
help: "Use hexadecimal notation for the result.")
38-
var hexadecimalOutput: Bool = false
38+
var hexadecimalOutput = false
3939

4040
@Argument(
4141
help: "A group of integers to operate on.")
42-
var values: [Int]
42+
var values: [Int] = []
4343
}
4444

4545
extension Math {
@@ -103,7 +103,7 @@ extension Math.Statistics {
103103
var kind: Kind = .mean
104104

105105
@Argument(help: "A group of floating-point values to operate on.")
106-
var values: [Double]
106+
var values: [Double] = []
107107

108108
func validate() throws {
109109
if (kind == .median || kind == .mode) && values.isEmpty {
@@ -166,7 +166,7 @@ extension Math.Statistics {
166166
abstract: "Print the standard deviation of the values.")
167167

168168
@Argument(help: "A group of floating-point values to operate on.")
169-
var values: [Double]
169+
var values: [Double] = []
170170

171171
mutating func run() {
172172
if values.isEmpty {
@@ -189,15 +189,15 @@ extension Math.Statistics {
189189
abstract: "Print the quantiles of the values (TBD).")
190190

191191
@Argument(help: "A group of floating-point values to operate on.")
192-
var values: [Double]
192+
var values: [Double] = []
193193

194194
// These args and the validation method are for testing exit codes:
195195
@Flag(help: .hidden)
196-
var testSuccessExitCode: Bool = false
196+
var testSuccessExitCode = false
197197
@Flag(help: .hidden)
198-
var testFailureExitCode: Bool = false
198+
var testFailureExitCode = false
199199
@Flag(help: .hidden)
200-
var testValidationExitCode: Bool = false
200+
var testValidationExitCode = false
201201
@Option(help: .hidden)
202202
var testCustomExitCode: Int32?
203203

Examples/repeat/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct Repeat: ParsableCommand {
1616
var count: Int?
1717

1818
@Flag(help: "Include a counter with each repetition.")
19-
var includeCounter: Bool = false
19+
var includeCounter = false
2020

2121
@Argument(help: "The phrase to repeat.")
2222
var phrase: String

Examples/roll/main.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ import ArgumentParser
1313

1414
struct RollOptions: ParsableArguments {
1515
@Option(help: ArgumentHelp("Rolls the dice <n> times.", valueName: "n"))
16-
var times: Int = 1
16+
var times = 1
1717

1818
@Option(help: ArgumentHelp(
1919
"Rolls an <m>-sided dice.",
2020
discussion: "Use this option to override the default value of a six-sided die.",
2121
valueName: "m"))
22-
var sides: Int = 6
22+
var sides = 6
2323

2424
@Option(help: "A seed to use for repeatable random generation.")
2525
var seed: Int?
2626

2727
@Flag(name: .shortAndLong, help: "Show all roll results.")
28-
var verbose: Bool = false
28+
var verbose = false
2929
}
3030

3131
// If you prefer writing in a "script" style, you can call `parseOrExit()` to

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import ArgumentParser
1313

1414
struct Repeat: ParsableCommand {
1515
@Flag(help: "Include a counter with each repetition.")
16-
var includeCounter: Bool
16+
var includeCounter = false
1717

1818
@Option(name: .shortAndLong, help: "The number of times to repeat 'phrase'.")
1919
var count: Int?

0 commit comments

Comments
 (0)