From 0ef80bb9bcc41d7cfc430b77a6fe614984dfe26c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 11 Feb 2025 13:26:26 -0600 Subject: [PATCH] fix(parser): Dont report missing flags as present When we switched flags to `ArgAction::SetTrue`, we overlooked updating `args_present`. Because of the default value for `ArgAction::SetTrue`, `args_present` will always report true when a flag is defined. I went with the trivial implementation for now. We could proactively track this but was unsure about correctness vs overhead and so I thought I'd have those using it pay for it. Looking over uses on github, this will fix a couple bugs but should otherwise be unnoticeable. Fixes #5860 --- clap_builder/src/parser/matches/arg_matches.rs | 4 +++- clap_builder/src/util/flat_map.rs | 4 ++++ tests/builder/arg_matches.rs | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/clap_builder/src/parser/matches/arg_matches.rs b/clap_builder/src/parser/matches/arg_matches.rs index 5e4d9dcd48e..67929a1b22d 100644 --- a/clap_builder/src/parser/matches/arg_matches.rs +++ b/clap_builder/src/parser/matches/arg_matches.rs @@ -575,7 +575,9 @@ impl ArgMatches { /// .unwrap(); /// assert!(! m.args_present()); pub fn args_present(&self) -> bool { - !self.args.is_empty() + self.args + .values() + .any(|v| v.source().map(|s| s.is_explicit()).unwrap_or(false)) } /// Report where argument value came from diff --git a/clap_builder/src/util/flat_map.rs b/clap_builder/src/util/flat_map.rs index d739b922211..3dce096ef26 100644 --- a/clap_builder/src/util/flat_map.rs +++ b/clap_builder/src/util/flat_map.rs @@ -118,6 +118,10 @@ impl FlatMap { self.keys.iter() } + pub(crate) fn values(&self) -> std::slice::Iter<'_, V> { + self.values.iter() + } + pub(crate) fn iter(&self) -> Iter<'_, K, V> { Iter { keys: self.keys.iter(), diff --git a/tests/builder/arg_matches.rs b/tests/builder/arg_matches.rs index 36f4a2ac26b..cfbb0731453 100644 --- a/tests/builder/arg_matches.rs +++ b/tests/builder/arg_matches.rs @@ -99,7 +99,7 @@ fn args_present_flag() { let c = Command::new("test").arg(Arg::new("flag").long("flag").action(ArgAction::SetTrue)); let m = c.clone().try_get_matches_from(["test"]).unwrap(); - assert!(m.args_present()); + assert!(!m.args_present()); let m = c.clone().try_get_matches_from(["test", "--flag"]).unwrap(); assert!(m.args_present());