You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The top-level command has an argument that is passed before the subcommand name (to provide a uniform context). Doing this with @OptionGroup on the parent CLI type.
Some subcommands want to collect free-form arguments so they can do more precise parsing (collecting related, order-sensitive flags) using @Argument(parsing: .allUnrecognized).
When set up this way, Swift argument parser starts producing bogus errors when the command line is used correctly.
And further, when used incorrectly, the error messages don't reflect what's actually wrong.
ArgumentParser version:1.5.0 and main Swift version: Swift 5.11, multiple Swift 6 betas and pre-release toolchains.
Checklist
If possible, I've reproduced the issue using the main branch of this package
import ArgumentParser
@mainstructCLI:ParsableCommand{@Argumentvarcontext:String?staticletconfiguration=CommandConfiguration(subcommands:[Command.self])structCommand:ParsableCommand{@OptionGroupvarouter:CLI@Optionvarinner:Int?@Argument(parsing:.allUnrecognized)varquery:[String]mutatingfunc run()throws{
if let context = outer.context {print("Context: \(context)")}else{print("No context set")}
if let inner {print("Inner: \(inner)")}print("Query: \(query)")}}}
Behavior
Running:
$ swift run -- cli context-here command --include hello --inner 123 --exclude hi
Error: Missing expected argument '<query> ...'
Help: <query>
Usage: cli command [<context>] [--inner <inner>] <query> ...
See 'cli command --help' for more information.
In both cases, the query fails to parse in different ways.
Variations
The "Missing expected argument ' ...'" is caused by query being required.
If you make it var query: [String] = [] then it doesn't produce that kind of error, it's always "Unknown option".
If you comment out the @OptionGroup var outer: CLI, then you can use the command line properly.
However, if you forget to pass the context argument on the outer CLI, like:
$ swift run -- cli command --inner 123 --exclude hi
Then you get the unhelpful error message:
Error: Unknown option '--inner'
Usage: cli [<context>] <subcommand>
See 'cli --help' for more information.
indicating that it just treated command as the context argument. It should probably give an error about the missing subcommand? But also, context is optional here, so it should maybe be treating the command as the subcommand? That might be more context-sensitive than the parsing is intended to provide though.
If you use @Argument(parsing: .postTerminator), things work correctly, but you're forced to move all the flexible arguments to the end past the -- terminator, which is dramatically worse UX.
The text was updated successfully, but these errors were encountered:
porglezomp
added a commit
to porglezomp-misc/swift-argument-parser
that referenced
this issue
Aug 5, 2024
I put up a commit here with tests for the behavior I expect—they're messy tests and should be re-written but should give an easier reproducer for what I'm running into here. porglezomp-misc@5e37672
I have a CLI with two specific constraints:
@OptionGroup
on the parent CLI type.@Argument(parsing: .allUnrecognized)
.When set up this way, Swift argument parser starts producing bogus errors when the command line is used correctly.
And further, when used incorrectly, the error messages don't reflect what's actually wrong.
ArgumentParser version:
1.5.0
andmain
Swift version: Swift 5.11, multiple Swift 6 betas and pre-release toolchains.
Checklist
main
branch of this packageSteps to Reproduce
It reproduces with this sample tool:
Behavior
Running:
$ swift run -- cli context-here command --include hello --inner 123 --exclude hi
Should output:
But instead fails with:
And running:
$ swift run -- cli context-here command --include hello --inner 123 --exclude hi
Should output:
But instead fails with:
In both cases, the query fails to parse in different ways.
Variations
The "Missing expected argument ' ...'" is caused by
query
being required.If you make it
var query: [String] = []
then it doesn't produce that kind of error, it's always "Unknown option".If you comment out the
@OptionGroup var outer: CLI
, then you can use the command line properly.However, if you forget to pass the context argument on the outer CLI, like:
$ swift run -- cli command --inner 123 --exclude hi
Then you get the unhelpful error message:
indicating that it just treated
command
as the context argument. It should probably give an error about the missing subcommand? But also, context is optional here, so it should maybe be treating thecommand
as the subcommand? That might be more context-sensitive than the parsing is intended to provide though.If you use
@Argument(parsing: .postTerminator)
, things work correctly, but you're forced to move all the flexible arguments to the end past the--
terminator, which is dramatically worse UX.The text was updated successfully, but these errors were encountered: