clap
clap copied to clipboard
`.action(ArgAction::Help)` and `ArgAction::Version` bypass `exclusive(true)`
Please complete the following tasks
- [X] I have searched the discussions
- [X] I have searched the open and rejected issues
Rust Version
rustc 1.62.1 (e092d0b6b 2022-07-16)
Clap Version
master
Minimal reproducible code
use clap::{error::ErrorKind, Arg, ArgAction, Command};
fn main() {
let result = Command::new("flag_conflict")
.version("5.0.0")
.arg(
Arg::new("myhelp")
.action(ArgAction::Help)
.long("myhelp")
.exclusive(true),
)
.arg(
Arg::new("myversion")
.action(ArgAction::Version)
.long("myversion"),
)
.try_get_matches_from(vec!["test", "--myhelp", "--myversion"]);
assert_eq!(result.err().unwrap().kind(), ErrorKind::ArgumentConflict);
}
Steps to reproduce the bug with the above code
cargo run
Actual Behaviour
When using .action(ArgAction::Help)
or .action(ArgAction::Version)
and setting .exclusive(true)
on one of them and when input contains both flags the returned error is DisplayError
or DisplayVersion
.
Expected Behaviour
When using .action(ArgAction::Help)
or .action(ArgAction::Version)
and setting .exclusive(true)
on one of them and when input contains both flags it seems intuitive for the error to be ArgumentConflict
Additional Context
Would enable implementing false
and true
coreutils commands (https://github.com/uutils/coreutils/pull/3784) using ArgAction::Version
and ArgAction::Help
Debug Output
No response
It looks like you are taking manually implemented help and version flags and switching them to actions.
Could you expand on why those flags need to be exclusive?
Could you expand on why those flags need to be exclusive?
It's a weird behaviour of the GNU true and false utils. So a command like this
true --version
would show the version, but
true --version anotherarg
wouldn't. I believe the rationale is to maintain as much compatibility as possible with versions of the true
and false
commands that ignore all their arguments (like FreeBSD and built-ins of Bash).
We can work around this, but it was surprising to see the option being ignored when the ArgAction
changed.
We can work around this, but it was surprising to see the option being ignored when the ArgAction changed.
ArgActions are specified in the documentation for how to react when evaluating an argument, as in they are immediately processed. An important aspect of this is that we want to make actions pluggable and would like toe avoid special casing as that is something the user can't replicate.
It's a weird behaviour of the GNU true and false utils.
exclusive(true)
will cause an error which is the opposite of what you want here. To implement the GNU behavior, you would need to check if any other arg exists and ignore version/help if it does.
Considering the defined behavior of ArgAction, what seems like a relatively small use case (not even the described use case can rely on what is being requested, still small if it did), and the fact that its possible to workaround it, I'm going to go ahead and close this as part of our effort to limit the scope of clap to help keep binary sizes and compile times down
Alright, we will work around it by checking the number of arguments. ArgAction being processed immediately seems counterintuitive, but I can see how it makes sense for counting etc.. Thank you!
I think the linked PR can then also be closed. @jarkonik Thank you for putting in the effort to implement this!