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
{{ message }}
Repository navigation
Should option tokens be greedy with regard to subsequent bundled option or subcommand tokens? #1380
Currently, the token following a known option token is not treated as an argument. This means that if the subsequent token matches a subcommand, it will be treated as a subcommand
Should this behavior be changed so that the subsequent token would be considered an argument to the option, producing the following results, respectively, for the above examples?
changed the title [-]Should option tokens be greedy?[/-][+]Should option tokens be greedy with regard to subsequent bundled option or subcommand tokens?[/+]on Aug 18, 2021
In my opion the "greedy" behavior should be default.
Otherwise, this has to be documented, including in the help text as generated by System.CommandLine. Imagine having to document/explain that the argument following an option has to be different from any other option/subcommand name, otherwise you, the user, has to invoke the commandline of the program in this or that other way. This not only can become akward and confusing. but it also makes the user responsible for checking whether the argument value they provided matches by chance a subcommand or another option. It might perhaps even make otherwise valid commandline invocations impossible.
What if the user actually wants to assign the value "-b" to the option -a? What if the CLI in question should allow program invocation without invoking a subcommand (in other words, the root command has a handler) and the user wants to provide -a with a "subcommand" value? How could they do this if options are non-greedy?
The greedy approach avoids all this. Documentation and help text remain relatively simple and there are no special cases involved where an argument value by chance collides with other option or subcommand names.
For those who prefer the "special case"-ness of the non-greedy behavior, perhaps there could be a setting offered by System.CommandLine to enable non-greedy behavior if desired. (Perhaps as an extension method applicable to RootCommand instances which effects this setting on the root command, all its descendent sub commands and options.)
Data point from a real migration, plus an update on where this landed.
Current behaviour is mixed
Re-running both examples from the original post against 3.0.0-rc.3.26522.148 on .NET 10:
[-a -bc] -a='' errors=0
[-a subcommand] -a='subcommand' cmd=<root> errors=[Required command was not provided.]
So the second example did change to the greedy behaviour proposed here, while the first did not — bundled short options are still not consumed. Worth noting since this issue is still open and reads as though neither had changed.
Greediness also extends to registered options of the same command, including --help:
[--search=--foo] OK Search='--foo'
[--search --foo] ERR CommandLine.UnknownOptionError
Under the current greedy behaviour, darc get-subscriptions --target-repo --help silently binds "--help" as a repository name and queries for it, rather than printing help. A user who forgets an argument gets a confusing empty result set instead of an error.
I agree with @elgonzo that greedy is the right default — it is the only way to pass a value that happens to look like an option. But the all-or-nothing nature of it is the issue. There is currently no way to opt into stricter handling, so a CLI migrating from a stricter parser has to accept the regression.
Request
An opt-in strict mode, ideally settable per-option as well as inherited from the root command, that reports an error when a scalar option's value starts with a prefix character and was not explicitly assigned with =.
That second half is the key qualifier, and it is currently impossible to express: the = is erased during tokenization, so --search=--foo and --search --foo are byte-identical in ArgumentResult.Tokens, OptionResult.IdentifierToken, and ParseResult.Tokens. I filed #2868 for that specific gap, since preserving the distinction is a prerequisite for any strict mode that is not also a usability regression.
Activity
[-]Make option tokens greedy[/-][+]Should option tokens be greedy?[/+][-]Should option tokens be greedy?[/-][+]Should option tokens be greedy with regard to subsequent bundled option or subcommand tokens?[/+]elgonzo commentedon Aug 18, 2021
In my opion the "greedy" behavior should be default.
Otherwise, this has to be documented, including in the help text as generated by System.CommandLine. Imagine having to document/explain that the argument following an option has to be different from any other option/subcommand name, otherwise you, the user, has to invoke the commandline of the program in this or that other way. This not only can become akward and confusing. but it also makes the user responsible for checking whether the argument value they provided matches by chance a subcommand or another option. It might perhaps even make otherwise valid commandline invocations impossible.
What if the user actually wants to assign the value "-b" to the option
-a? What if the CLI in question should allow program invocation without invoking a subcommand (in other words, the root command has a handler) and the user wants to provide-awith a "subcommand" value? How could they do this if options are non-greedy?The greedy approach avoids all this. Documentation and help text remain relatively simple and there are no special cases involved where an argument value by chance collides with other option or subcommand names.
For those who prefer the "special case"-ness of the non-greedy behavior, perhaps there could be a setting offered by System.CommandLine to enable non-greedy behavior if desired. (Perhaps as an extension method applicable to RootCommand instances which effects this setting on the root command, all its descendent sub commands and options.)
ViktorHofer commentedon Oct 29, 2026
Data point from a real migration, plus an update on where this landed.
Current behaviour is mixed
Re-running both examples from the original post against
3.0.0-rc.3.26522.148on .NET 10:So the second example did change to the greedy behaviour proposed here, while the first did not — bundled short options are still not consumed. Worth noting since this issue is still open and reads as though neither had changed.
Greediness also extends to registered options of the same command, including
--help:Why this is a problem in practice
We are migrating the
darcCLI off CommandLineParser as a prerequisite for Native AOT (dotnet/arcade-services#6825). CommandLineParser rejected option-like values unless they were explicitly assigned with=:Under the current greedy behaviour,
darc get-subscriptions --target-repo --helpsilently binds"--help"as a repository name and queries for it, rather than printing help. A user who forgets an argument gets a confusing empty result set instead of an error.I agree with @elgonzo that greedy is the right default — it is the only way to pass a value that happens to look like an option. But the all-or-nothing nature of it is the issue. There is currently no way to opt into stricter handling, so a CLI migrating from a stricter parser has to accept the regression.
Request
An opt-in strict mode, ideally settable per-option as well as inherited from the root command, that reports an error when a scalar option's value starts with a prefix character and was not explicitly assigned with
=.That second half is the key qualifier, and it is currently impossible to express: the
=is erased during tokenization, so--search=--fooand--search --fooare byte-identical inArgumentResult.Tokens,OptionResult.IdentifierToken, andParseResult.Tokens. I filed #2868 for that specific gap, since preserving the distinction is a prerequisite for any strict mode that is not also a usability regression.