Skip to content

Commit 2fef2e8

Browse files
committed
Add a custom default value property to encode defaults
1 parent 912888d commit 2fef2e8

29 files changed

+274
-103
lines changed

Sources/ArgumentParser/Parsing/ArgumentSet.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ extension ArgumentSet {
7777
// The flag is required if initialValue is `nil`, otherwise it's optional
7878
let helpOptions: ArgumentDefinition.Help.Options =
7979
initialValue != nil ? .isOptional : []
80-
let defaultValueString = initialValue == true ? "true" : nil
80+
let defaultValueString = initialValue.map { String(describing: $0) }
8181

8282
let help = ArgumentDefinition.Help(
8383
allValueStrings: [],

Sources/ArgumentParser/Usage/OpenCLIv0_1Generator.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ extension OpenCLIv0_1.Option {
145145
let argument = OpenCLIv0_1.Argument(
146146
name: argDef.valueName,
147147
required: !argDef.help.options.contains(.isOptional) ? true : nil,
148-
description: argDef.help.abstract.isEmpty ? nil : argDef.help.abstract
148+
description: argDef.help.abstract.isEmpty ? nil : argDef.help.abstract,
149+
swiftArgumentParserDefaultValue: argDef.help.defaultValue
149150
)
150151
optionArguments = [argument]
151152
case .nullary:
@@ -172,7 +173,8 @@ extension OpenCLIv0_1.Option {
172173
case .directory: return true
173174
default: return nil
174175
}
175-
}()
176+
}(),
177+
swiftArgumentParserDefaultValue: argDef.help.defaultValue
176178
)
177179
}
178180
}
@@ -197,7 +199,8 @@ extension OpenCLIv0_1.Argument {
197199
case .directory: return true
198200
default: return nil
199201
}
200-
}()
202+
}(),
203+
swiftArgumentParserDefaultValue: argDef.help.defaultValue
201204
)
202205
}
203206
}

Sources/ArgumentParserOpenCLI/OpenCLIv0_1.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,15 @@ public struct OpenCLIv0_1: Codable, Equatable {
8989
public let metadata: [Metadata]?
9090
public let swiftArgumentParserFile: Bool?
9191
public let swiftArgumentParserDirectory: Bool?
92+
public let swiftArgumentParserDefaultValue: String?
9293

9394
public init(
9495
name: String, required: Bool? = nil, arity: Arity? = nil,
9596
acceptedValues: [String]? = nil, group: String? = nil,
9697
description: String? = nil, hidden: Bool? = nil,
9798
metadata: [Metadata]? = nil, swiftArgumentParserFile: Bool? = nil,
98-
swiftArgumentParserDirectory: Bool? = nil
99+
swiftArgumentParserDirectory: Bool? = nil,
100+
swiftArgumentParserDefaultValue: String? = nil
99101
) {
100102
self.name = name
101103
self.required = required
@@ -107,6 +109,7 @@ public struct OpenCLIv0_1: Codable, Equatable {
107109
self.metadata = metadata
108110
self.swiftArgumentParserFile = swiftArgumentParserFile
109111
self.swiftArgumentParserDirectory = swiftArgumentParserDirectory
112+
self.swiftArgumentParserDefaultValue = swiftArgumentParserDefaultValue
110113
}
111114
}
112115

@@ -123,6 +126,7 @@ public struct OpenCLIv0_1: Codable, Equatable {
123126
public let swiftArgumentParserRepeating: Bool?
124127
public let swiftArgumentParserFile: Bool?
125128
public let swiftArgumentParserDirectory: Bool?
129+
public let swiftArgumentParserDefaultValue: String?
126130

127131
public init(
128132
name: String, required: Bool? = nil, aliases: [String]? = nil,
@@ -131,7 +135,8 @@ public struct OpenCLIv0_1: Codable, Equatable {
131135
hidden: Bool? = nil,
132136
metadata: [Metadata]? = nil, swiftArgumentParserRepeating: Bool? = nil,
133137
swiftArgumentParserFile: Bool? = nil,
134-
swiftArgumentParserDirectory: Bool? = nil
138+
swiftArgumentParserDirectory: Bool? = nil,
139+
swiftArgumentParserDefaultValue: String? = nil
135140
) {
136141
self.name = name
137142
self.required = required
@@ -145,6 +150,7 @@ public struct OpenCLIv0_1: Codable, Equatable {
145150
self.swiftArgumentParserRepeating = swiftArgumentParserRepeating
146151
self.swiftArgumentParserFile = swiftArgumentParserFile
147152
self.swiftArgumentParserDirectory = swiftArgumentParserDirectory
153+
self.swiftArgumentParserDefaultValue = swiftArgumentParserDefaultValue
148154
}
149155
}
150156

Tests/ArgumentParserEndToEndTests/OpenCLIDumpHelpGenerationTests.swift

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,76 @@ final class OpenCLIDumpHelpGenerationTests: XCTestCase {
232232
dirArg?.swiftArgumentParserFile,
233233
"Expected directory argument to have swiftArgumentParserFile as nil")
234234
}
235+
236+
func testDefaultValueProperties() throws {
237+
// Test that swiftArgumentParserDefaultValue is set correctly for arguments and options with defaults
238+
let actual: String
239+
do {
240+
_ = try CommandWithDefaultValues.parse(["--help-dump-opencli-v0.1"])
241+
XCTFail("Expected parsing to fail with OpenCLI dump request")
242+
return
243+
} catch {
244+
actual = CommandWithDefaultValues.fullMessage(for: error)
245+
}
246+
247+
// Parse the JSON output
248+
let jsonData = actual.data(using: .utf8)!
249+
let openCLI = try JSONDecoder().decode(OpenCLIv0_1.self, from: jsonData)
250+
251+
// Find the option with default value
252+
guard let options = openCLI.options else {
253+
XCTFail("Expected options to be present")
254+
return
255+
}
256+
257+
let countOption = options.first { $0.name == "--count" }
258+
XCTAssertNotNil(countOption, "Expected to find --count option")
259+
XCTAssertEqual(
260+
countOption?.swiftArgumentParserDefaultValue, "5",
261+
"Expected count option to have swiftArgumentParserDefaultValue set to '5'"
262+
)
263+
264+
let nameOption = options.first { $0.name == "--name" }
265+
XCTAssertNotNil(nameOption, "Expected to find --name option")
266+
XCTAssertEqual(
267+
nameOption?.swiftArgumentParserDefaultValue, "default",
268+
"Expected name option to have swiftArgumentParserDefaultValue set to 'default'"
269+
)
270+
271+
let verboseOption = options.first { $0.name == "--verbose" }
272+
XCTAssertNotNil(verboseOption, "Expected to find --verbose option")
273+
XCTAssertEqual(
274+
verboseOption?.swiftArgumentParserDefaultValue, "false",
275+
"Expected verbose option to have swiftArgumentParserDefaultValue set to 'false'"
276+
)
277+
278+
// Find an option without default to verify it doesn't have the property set
279+
let requiredOption = options.first { $0.name == "--required-option" }
280+
XCTAssertNotNil(requiredOption, "Expected to find --required-option")
281+
XCTAssertNil(
282+
requiredOption?.swiftArgumentParserDefaultValue,
283+
"Expected required option to have swiftArgumentParserDefaultValue as nil")
284+
285+
// Check arguments
286+
guard let arguments = openCLI.arguments else {
287+
XCTFail("Expected arguments to be present")
288+
return
289+
}
290+
291+
let outputArg = arguments.first { $0.name == "output" }
292+
XCTAssertNotNil(outputArg, "Expected to find output argument")
293+
XCTAssertEqual(
294+
outputArg?.swiftArgumentParserDefaultValue, "output.txt",
295+
"Expected output argument to have swiftArgumentParserDefaultValue set to 'output.txt'"
296+
)
297+
298+
let inputArg = arguments.first { $0.name == "input" }
299+
XCTAssertNotNil(inputArg, "Expected to find input argument")
300+
XCTAssertNil(
301+
inputArg?.swiftArgumentParserDefaultValue,
302+
"Expected required input argument to have swiftArgumentParserDefaultValue as nil"
303+
)
304+
}
235305
}
236306

237307
extension OpenCLIDumpHelpGenerationTests {
@@ -402,4 +472,29 @@ extension OpenCLIDumpHelpGenerationTests {
402472
@Argument(help: "Output directory", completion: .directory)
403473
var outputDir: String
404474
}
475+
476+
struct CommandWithDefaultValues: ParsableCommand {
477+
static let configuration = CommandConfiguration(
478+
commandName: "default-values",
479+
abstract: "Command with various default values"
480+
)
481+
482+
@Option(help: "Count value with default")
483+
var count: Int = 5
484+
485+
@Option(help: "Name with default value")
486+
var name: String = "default"
487+
488+
@Flag(help: "Verbose flag with default")
489+
var verbose: Bool = false
490+
491+
@Option(help: "Required option without default")
492+
var requiredOption: String
493+
494+
@Argument(help: "Required input argument")
495+
var input: String
496+
497+
@Argument(help: "Output file with default")
498+
var output: String = "output.txt"
499+
}
405500
}

Tests/ArgumentParserEndToEndTests/Snapshots/testADumpOpenCLI().json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
},
1212
{
1313
"description" : "argument with default value",
14-
"name" : "arg-with-default-value"
14+
"name" : "arg-with-default-value",
15+
"swiftArgumentParserDefaultValue" : "1"
1516
}
1617
],
1718
"info" : {
@@ -34,11 +35,13 @@
3435
{
3536
"arguments" : [
3637
{
37-
"name" : "enumerated-option-with-default-value"
38+
"name" : "enumerated-option-with-default-value",
39+
"swiftArgumentParserDefaultValue" : "two"
3840
}
3941
],
4042
"name" : "--enumerated-option-with-default-value",
41-
"recursive" : false
43+
"recursive" : false,
44+
"swiftArgumentParserDefaultValue" : "two"
4245
},
4346
{
4447
"arguments" : [
@@ -68,12 +71,14 @@
6871
"arguments" : [
6972
{
7073
"description" : "int value option with default value",
71-
"name" : "int-option-with-default-value"
74+
"name" : "int-option-with-default-value",
75+
"swiftArgumentParserDefaultValue" : "0"
7276
}
7377
],
7478
"description" : "int value option with default value",
7579
"name" : "--int-option-with-default-value",
76-
"recursive" : false
80+
"recursive" : false,
81+
"swiftArgumentParserDefaultValue" : "0"
7782
},
7883
{
7984
"aliases" : [

Tests/ArgumentParserEndToEndTests/Snapshots/testBDumpOpenCLI().json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"options" : [
88
{
99
"name" : "--verbose",
10-
"recursive" : false
10+
"recursive" : false,
11+
"swiftArgumentParserDefaultValue" : "false"
1112
},
1213
{
1314
"arguments" : [

Tests/ArgumentParserEndToEndTests/Snapshots/testCDumpOpenCLI().json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
"arguments" : [
2323
{
2424
"description" : "Another color to select!",
25-
"name" : "default-color"
25+
"name" : "default-color",
26+
"swiftArgumentParserDefaultValue" : "red"
2627
}
2728
],
2829
"description" : "Another color to select!",
2930
"name" : "--default-color",
30-
"recursive" : false
31+
"recursive" : false,
32+
"swiftArgumentParserDefaultValue" : "red"
3133
},
3234
{
3335
"arguments" : [

Tests/ArgumentParserEndToEndTests/Snapshots/testCommandWithOptionsDumpOpenCLI().json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
],
2424
"description" : "Help flag",
2525
"name" : "--help",
26-
"recursive" : false
26+
"recursive" : false,
27+
"swiftArgumentParserDefaultValue" : "false"
2728
},
2829
{
2930
"aliases" : [

Tests/ArgumentParserEndToEndTests/Snapshots/testMathAddDumpOpenCLI().json

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
],
2323
"description" : "Use hexadecimal notation for the result.",
2424
"name" : "--hex-output",
25-
"recursive" : false
25+
"recursive" : false,
26+
"swiftArgumentParserDefaultValue" : "false"
2627
},
2728
{
2829
"description" : "Show the version.",
@@ -58,7 +59,8 @@
5859
],
5960
"description" : "Use hexadecimal notation for the result.",
6061
"name" : "--hex-output",
61-
"recursive" : false
62+
"recursive" : false,
63+
"swiftArgumentParserDefaultValue" : "false"
6264
},
6365
{
6466
"description" : "Show the version.",
@@ -94,12 +96,14 @@
9496
"arguments" : [
9597
{
9698
"description" : "The kind of average to provide.",
97-
"name" : "kind"
99+
"name" : "kind",
100+
"swiftArgumentParserDefaultValue" : "mean"
98101
}
99102
],
100103
"description" : "The kind of average to provide.",
101104
"name" : "--kind",
102-
"recursive" : false
105+
"recursive" : false,
106+
"swiftArgumentParserDefaultValue" : "mean"
103107
},
104108
{
105109
"description" : "Show the version.",
@@ -163,17 +167,20 @@
163167
{
164168
"hidden" : true,
165169
"name" : "--test-success-exit-code",
166-
"recursive" : false
170+
"recursive" : false,
171+
"swiftArgumentParserDefaultValue" : "false"
167172
},
168173
{
169174
"hidden" : true,
170175
"name" : "--test-failure-exit-code",
171-
"recursive" : false
176+
"recursive" : false,
177+
"swiftArgumentParserDefaultValue" : "false"
172178
},
173179
{
174180
"hidden" : true,
175181
"name" : "--test-validation-exit-code",
176-
"recursive" : false
182+
"recursive" : false,
183+
"swiftArgumentParserDefaultValue" : "false"
177184
},
178185
{
179186
"arguments" : [
@@ -280,7 +287,8 @@
280287
],
281288
"description" : "Use hexadecimal notation for the result.",
282289
"name" : "--hex-output",
283-
"recursive" : false
290+
"recursive" : false,
291+
"swiftArgumentParserDefaultValue" : "false"
284292
},
285293
{
286294
"description" : "Show the version.",

0 commit comments

Comments
 (0)