diff --git a/src/build/app/mod.rs b/src/build/app/mod.rs index 9ab1e0a2..9df2dbc2 100644 --- a/src/build/app/mod.rs +++ b/src/build/app/mod.rs @@ -27,7 +27,7 @@ use crate::{ build::{arg::ArgProvider, Arg, ArgGroup, ArgSettings}, mkeymap::MKeyMap, output::{fmt::Colorizer, Help, HelpWriter, Usage}, - parse::{ArgMatcher, ArgMatches, Input, Parser}, + parse::{ArgMatcher, ArgMatches, Input, Parser, ValueType}, util::{color::ColorChoice, safe_exit, Id, Key, USAGE_CODE}, Error, ErrorKind, Result as ClapResult, INTERNAL_ERROR_MSG, }; @@ -2936,6 +2936,7 @@ impl<'help> App<'help> { if let Some(v) = val { if matcher .get(arg) + .filter(|ma| !matches!(ma.ty, ValueType::DefaultValue)) .map(|ma| ma.contains_val(v)) .unwrap_or(false) { @@ -2943,8 +2944,10 @@ impl<'help> App<'help> { } else { None } - } else { + } else if !matcher.is_default_value(arg) { Some(req_arg.clone()) + } else { + None } }; diff --git a/src/parse/validator.rs b/src/parse/validator.rs index c8886b6f..acc9c351 100644 --- a/src/parse/validator.rs +++ b/src/parse/validator.rs @@ -401,8 +401,10 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> { } } else if let Some(g) = self.p.app.groups.iter().find(|grp| grp.id == *name) { debug!("Validator::gather_conflicts:iter:{:?}:group", name); - for r in &g.requires { - self.p.required.insert(r.clone()); + if !matcher.is_default_value(&g.id) { + for r in &g.requires { + self.p.required.insert(r.clone()); + } } } } diff --git a/tests/require.rs b/tests/require.rs index 69b15059..9f43b6a6 100644 --- a/tests/require.rs +++ b/tests/require.rs @@ -238,7 +238,7 @@ fn required_unless_present() { } #[test] -fn required_unless_err() { +fn required_unless_present_err() { let res = App::new("unlesstest") .arg( Arg::new("cfg") @@ -1107,3 +1107,56 @@ fn required_unless_invalid_arg() { ) .try_get_matches_from(vec![""]); } + +#[test] +fn requires_with_default_value() { + let result = App::new("prog") + .arg( + Arg::new("opt") + .long("opt") + .default_value("default") + .requires("flag"), + ) + .arg(Arg::new("flag").long("flag")) + .try_get_matches_from(vec!["myprog"]); + + assert!(result.is_ok(), "{:?}", result.unwrap()); + let m = result.unwrap(); + + assert_eq!(m.value_of("opt"), Some("default")); + assert!(!m.is_present("flag")); +} + +#[test] +fn requires_if_with_default_value() { + let result = App::new("prog") + .arg( + Arg::new("opt") + .long("opt") + .default_value("default") + .requires_if("default", "flag"), + ) + .arg(Arg::new("flag").long("flag")) + .try_get_matches_from(vec!["myprog"]); + + assert!(result.is_ok(), "{:?}", result.unwrap()); + let m = result.unwrap(); + + assert_eq!(m.value_of("opt"), Some("default")); + assert!(!m.is_present("flag")); +} + +#[test] +fn group_requires_with_default_value() { + let result = App::new("prog") + .arg(Arg::new("opt").long("opt").default_value("default")) + .arg(Arg::new("flag").long("flag")) + .group(ArgGroup::new("one").arg("opt").requires("flag")) + .try_get_matches_from(vec!["myprog"]); + + assert!(result.is_ok(), "{:?}", result.unwrap()); + let m = result.unwrap(); + + assert_eq!(m.value_of("opt"), Some("default")); + assert!(!m.is_present("flag")); +}