From fa9be84b182d503609420b2491351fe74a257e9d Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Sat, 12 Dec 2020 21:55:49 +0800 Subject: [PATCH] Propagate global arg in subcommand to subsubcommand --- src/build/app/mod.rs | 28 ++++++++++++++++------ tests/global_args.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/src/build/app/mod.rs b/src/build/app/mod.rs index 86c410b6..77ff9c0b 100644 --- a/src/build/app/mod.rs +++ b/src/build/app/mod.rs @@ -2261,6 +2261,26 @@ impl<'help> App<'help> { // Internally used only impl<'help> App<'help> { + fn get_used_global_args(&self, matcher: &ArgMatcher) -> Vec { + let global_args: Vec<_> = self + .args + .args + .iter() + .filter(|a| a.global) + .map(|ga| ga.id.clone()) + .collect(); + if let Some(used_subcommand) = matcher.0.subcommand.as_ref() { + if let Some(used_subcommand) = self + .subcommands + .iter() + .find(|subcommand| subcommand.id == used_subcommand.id) + { + return [global_args, used_subcommand.get_used_global_args(matcher)].concat(); + } + } + global_args + } + fn _do_parse(&mut self, it: &mut Input) -> ClapResult { debug!("App::_do_parse"); let mut matcher = ArgMatcher::default(); @@ -2275,13 +2295,7 @@ impl<'help> App<'help> { let mut parser = Parser::new(self); parser.get_matches_with(&mut matcher, it)?; - let global_arg_vec: Vec = self - .args - .args - .iter() - .filter(|a| a.global) - .map(|ga| ga.id.clone()) - .collect(); + let global_arg_vec: Vec = self.get_used_global_args(&matcher); matcher.propagate_globals(&global_arg_vec); diff --git a/tests/global_args.rs b/tests/global_args.rs index 3846cf70..a0efb836 100644 --- a/tests/global_args.rs +++ b/tests/global_args.rs @@ -29,3 +29,59 @@ fn issue_1076() { let _ = app.try_get_matches_from_mut(vec!["myprog"]); let _ = app.try_get_matches_from_mut(vec!["myprog"]); } + +#[test] +fn propagate_global_arg_in_subcommand_to_subsubcommand_1385() { + let m1 = App::new("foo") + .subcommand( + App::new("sub1") + .arg(Arg::new("arg1").long("arg1").takes_value(true).global(true)) + .subcommand(App::new("sub1a")), + ) + .get_matches_from(&["foo", "sub1", "--arg1", "v1", "sub1a"]); + assert_eq!( + "v1", + m1.subcommand_matches("sub1") + .unwrap() + .subcommand_matches("sub1a") + .unwrap() + .value_of("arg1") + .unwrap() + ); +} + +#[test] +fn propagate_global_arg_in_subcommand_to_subsubcommand_2053() { + let m = App::new("opts") + .arg(Arg::from("--global-flag").global(true)) + .arg( + Arg::from("--global-str ") + .required(false) + .global(true), + ) + .subcommand( + App::new("test") + .arg(Arg::from("--sub-flag").global(true)) + .arg( + Arg::from("--sub-str ") + .required(false) + .global(true), + ) + .subcommand(App::new("test")), + ) + .get_matches_from(&[ + "app", + "test", + "test", + "--global-flag", + "--global-str", + "hello", + "--sub-flag", + "--sub-str", + "world", + ]); + assert_eq!( + Some("world"), + m.subcommand_matches("test").unwrap().value_of("sub-str") + ); +}