fix(parser): Don't make Args exclusive with their ArgGroup

This is most obvious with the derive API as it creates `ArgGroup`s all
over the place now.

Fixes #4396
This commit is contained in:
Ed Page 2022-10-17 19:02:39 -05:00
parent a40c7b491e
commit 45dcf0ed22
2 changed files with 23 additions and 3 deletions

View file

@ -112,6 +112,9 @@ impl<'cmd> Validator<'cmd> {
.arg_ids()
.filter(|arg_id| {
matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
// Avoid including our own groups by checking none of them. If a group is present, the
// args for the group will be.
&& self.cmd.find(arg_id).is_some()
})
.count();
if args_count <= 1 {

View file

@ -38,10 +38,13 @@ fn flag_conflict_with_all() {
#[test]
fn exclusive_flag() {
let result = Command::new("flag_conflict")
let cmd = Command::new("flag_conflict")
.arg(arg!(-f --flag "some flag").exclusive(true))
.arg(arg!(-o --other "some flag"))
.try_get_matches_from(vec!["myprog", "-o", "-f"]);
.arg(arg!(-o --other "some flag"));
let result = cmd.clone().try_get_matches_from(vec!["myprog", "-f"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
let result = cmd.clone().try_get_matches_from(vec!["myprog", "-o", "-f"]);
assert!(result.is_err());
let err = result.err().unwrap();
assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
@ -71,6 +74,20 @@ fn not_exclusive_with_defaults() {
assert!(result.is_ok(), "{}", result.unwrap_err());
}
#[test]
fn not_exclusive_with_group() {
let cmd = Command::new("test")
.group(clap::ArgGroup::new("test").arg("foo"))
.arg(
clap::Arg::new("foo")
.long("foo")
.exclusive(true)
.action(clap::ArgAction::SetTrue),
);
let result = cmd.try_get_matches_from(vec!["test", "--foo"]);
assert!(result.is_ok(), "{}", result.unwrap_err());
}
#[test]
fn default_doesnt_activate_exclusive() {
let result = Command::new("flag_conflict")