Skip to content

Commit 2d256de

Browse files
authored
Add @Flag initializer for Optional<Bool> (#54)
* Add @Flag initializer for Optional<Bool> Per [discussion][], add an initializer for `Flag<Optional<Bool>>` that allows the default value to be `nil`, enabling capacity to distinguish the lack of a supplied flag vs the default value from user. [discussion]: https://forums.swift.org/t/flag-default-value-where-did-it-come-from/34204/10 * fixup! Add @Flag initializer for Optional<Bool>
1 parent 58660b0 commit 2d256de

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

Sources/ArgumentParser/Parsable Properties/Flag.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,35 @@ public enum FlagExclusivity {
112112
case chooseLast
113113
}
114114

115+
extension Flag where Value == Optional<Bool> {
116+
/// Creates a Boolean property that reads its value from the presence of
117+
/// one or more inverted flags.
118+
///
119+
/// Use this initializer to create an optional Boolean flag with an on/off
120+
/// pair. With the following declaration, for example, the user can specify
121+
/// either `--use-https` or `--no-use-https` to set the `useHTTPS` flag to
122+
/// `true` or `false`, respectively. If neither is specified, the resulting
123+
/// flag value would be `nil`.
124+
///
125+
/// @Flag(inversion: .prefixedNo)
126+
/// var useHTTPS: Bool?
127+
///
128+
/// - Parameters:
129+
/// - name: A specification for what names are allowed for this flag.
130+
/// - inversion: The method for converting this flags name into an on/off
131+
/// pair.
132+
/// - help: Information about how to use this flag.
133+
public init(
134+
name: NameSpecification = .long,
135+
inversion: FlagInversion,
136+
help: ArgumentHelp? = nil
137+
) {
138+
self.init(_parsedValue: .init { key in
139+
.flag(key: key, name: name, default: nil, inversion: inversion, help: help)
140+
})
141+
}
142+
}
143+
115144
extension Flag where Value == Bool {
116145
/// Creates a Boolean property that reads its value from the presence of a
117146
/// flag.

Tests/EndToEndTests/FlagsEndToEndTests.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,37 @@ fileprivate struct Bar: ParsableArguments {
2424

2525
@Flag(inversion: .prefixedNo)
2626
var extattr: Bool
27+
28+
@Flag(inversion: .prefixedNo)
29+
var extattr2: Bool?
2730
}
2831

2932
extension FlagsEndToEndTests {
3033
func testParsing_defaultValue() throws {
3134
AssertParse(Bar.self, []) { options in
3235
XCTAssertEqual(options.verbose, false)
3336
XCTAssertEqual(options.extattr, false)
37+
XCTAssertEqual(options.extattr2, nil)
3438
}
3539
}
3640

3741
func testParsing_settingValue() throws {
3842
AssertParse(Bar.self, ["--verbose"]) { options in
3943
XCTAssertEqual(options.verbose, true)
4044
XCTAssertEqual(options.extattr, false)
45+
XCTAssertEqual(options.extattr2, nil)
4146
}
4247

4348
AssertParse(Bar.self, ["--extattr"]) { options in
4449
XCTAssertEqual(options.verbose, false)
4550
XCTAssertEqual(options.extattr, true)
51+
XCTAssertEqual(options.extattr2, nil)
52+
}
53+
54+
AssertParse(Bar.self, ["--extattr2"]) { options in
55+
XCTAssertEqual(options.verbose, false)
56+
XCTAssertEqual(options.extattr, false)
57+
XCTAssertEqual(options.extattr2, .some(true))
4658
}
4759
}
4860

0 commit comments

Comments
 (0)