Augment Option to support default as flag option#830
Conversation
d08351c to
61a6602
Compare
|
Would it make more sense instead to provide this functionality via @Option(parsing: .scanningForValue(default: "text"))
var showBinPath: String?You'd add/modify the following (I haven't checked the code for proper generics/types/compilation/keywords/etc.; it's just pseudo-code to illustrate the concept. I also haven't checked to see what problems adding the new public struct SingleValueParsingStrategy: Hashable {
…
// This is an addition
public static func scanningForValue<Value>(default: Value) -> SingleValueParsingStrategy {
self.init(base: .scanningForValue(default: default))
}
…
}
struct ArgumentDefinition {
…
enum ParsingStrategy {
…
// This is a modification
case scanningForValue(default: Any? = nil)
…
}
…
}One possible issue: must ensure that the option terminator cmd --show-bin-path -- json |
|
Thanks for the feedback @rgoldberg . What you proposed makes more sense than what I implemented. |
61a6602 to
b319a92
Compare
b319a92 to
2316d12
Compare
|
After discussing with @rauhul and @natecook1000 , we came up with the following API New initializers API usage looks as follows And the help dump looks like: |
2316d12 to
d3593e3
Compare
7f148ea to
b84708e
Compare
The changes requested have been taken into account in the most up to date change.
Tests/ArgumentParserGenerateManualTests/DefaultAsFlagManualTests.swift
Outdated
Show resolved
Hide resolved
bd602d4 to
f8eb0cc
Compare
b92f9cc to
755c1e6
Compare
natecook1000
left a comment
There was a problem hiding this comment.
Thanks for this implementation, @bkhouri! Notes below, mostly about docs. I'd particularly like to avoid duplicating the fiddly logic of the parseValue function – let's look at whether we can just provide new fallback behavior when that function fails to find a value.
Sources/ArgumentParser/Documentation.docc/Articles/DeclaringArguments.md
Show resolved
Hide resolved
| 2. **No value available**: Use the `defaultAsFlag` value | ||
| 3. **Explicit value provided**: Parse and use that value | ||
|
|
||
| This works with all parsing strategies (`.next`, `.scanningForValue`, `.unconditional`), though `.unconditional` defeats the purpose by always requiring a value. |
There was a problem hiding this comment.
Is this .unconditional/.defaultAsFlag mismatch worthy of a validation step, to prevent using them together?
There was a problem hiding this comment.
we can add a validation step to prevent this combination. do you have an suggested error message that should be reported?
There was a problem hiding this comment.
a compilation error will occur if defaultAsFlag is used with .unconditional parsing strategy. The documentation has been updated to reflect the supported parsing strategies.
755c1e6 to
8bf9dd9
Compare
2962ba2 to
a72b520
Compare
Sources/ArgumentParser/Documentation.docc/Articles/DeclaringArguments.md
Outdated
Show resolved
Hide resolved
a72b520 to
deffc73
Compare
| } catch let error as ParserError { | ||
| switch error { | ||
| case .missingValueForOption, .missingValueOrUnknownCompositeOption: | ||
| // Fall back to flag behavior when no value is available | ||
| let origin = InputOrigin(elements: [originElement]) |
1ded0e6 to
91fb75a
Compare
3d88047 to
8ae7861
Compare
In some use cases, there is a need to have an option argument behave
like a flag.
This change introduced 4 new intialiazers to `Option` that accept a
`defaultAsFlag` value.
With the following usage:
```swift
struct Example: ParsableCommand {
@option(defaultAsFlag: "default", help: "Set output format.")
var format: String?
func run() {
print("Format: \(format ?? "none")")
}
}
```
The `defaultAsFlag` parameter creates a hybrid that supports both patterns:
- **Flag behavior**: `--format` (sets format to "default")
- **Option behavior**: `--format json` (sets format to "json")
- **No usage**: format remains `nil`
As a user of the command line tool, the `--help` output clearly distinguishes
between the the hybrid and regular usages.
```
OPTIONS:
--format [<format>] Set output format. (default as flag: default)
````
Note the `(default as flag: ...)` text instead of regular `(default: ...)`,
and the optional value syntax `[<value>]` instead of required `<value>`.
Fixes: #829
8ae7861 to
55cbeed
Compare
In some use cases, there is a need to have an option argument behave like a flag.
This change introduced 4 new intialiazers to
Optionthat accept adefaultAsFlagvalue.With the following usage:
The
defaultAsFlagparameter creates a hybrid that supports both patterns:--format(sets format to "default")--format json(sets format to "json")nilAs a user of the command line tool, the
--helpoutput clearly distinguishes between the the hybrid and regular usages.Note the
(default as flag: ...)text instead of regular(default: ...), and the optional value syntax[<value>]instead of required<value>.Fixes: #829
Checklist