From ccc809a9df18541297a3be758200ddb277e5cd19 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 26 May 2022 20:36:49 -0500 Subject: [PATCH] fix(parser): Allow delimiting default_missing_values Fixes #3761 --- src/parser/parser.rs | 56 ++++++--------------------- tests/builder/default_missing_vals.rs | 33 ++++++++++++++++ 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index dc4dac3e19e..5a7151c65c3 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -941,11 +941,9 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { // We assume this case is valid: require equals, but min_vals == 0. if !opt.default_missing_vals.is_empty() { debug!("Parser::parse_opt: has default_missing_vals"); - self.add_multiple_vals_to_arg( - opt, - opt.default_missing_vals.iter().map(OsString::from), - matcher, - )?; + for v in opt.default_missing_vals.iter() { + self.add_val_to_arg(opt, &RawOsStr::new(v), matcher, trailing_values)?; + } }; if attached_value.is_some() { Ok(ParseResult::AttachedValueNotConsumed) @@ -989,7 +987,9 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { .split(delim) .map(|x| x.to_os_str().into_owned()) .take_while(|val| Some(val.as_os_str()) != terminator); - self.add_multiple_vals_to_arg(arg, vals, matcher)?; + for raw_val in vals { + self.add_single_val_to_arg(arg, raw_val, matcher)?; + } // If there was a delimiter used or we must use the delimiter to // separate the values or no more vals is needed, we're not // looking for more values. @@ -1016,19 +1016,6 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { } } - fn add_multiple_vals_to_arg( - &self, - arg: &Arg<'help>, - raw_vals: impl Iterator, - matcher: &mut ArgMatcher, - ) -> ClapResult<()> { - for raw_val in raw_vals { - self.add_single_val_to_arg(arg, raw_val, matcher)?; - } - - Ok(()) - } - fn add_single_val_to_arg( &self, arg: &Arg<'help>, @@ -1222,21 +1209,6 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { debug!("Parser::add_default_value: doesn't have conditional defaults"); } - fn process_default_vals(arg: &Arg<'_>, default_vals: &[&OsStr]) -> Vec { - if let Some(delim) = arg.val_delim { - let mut vals = vec![]; - for val in default_vals { - let val = RawOsStr::new(val); - for val in val.split(delim) { - vals.push(val.to_os_str().into_owned()); - } - } - vals - } else { - default_vals.iter().map(OsString::from).collect() - } - } - if !arg.default_vals.is_empty() { debug!( "Parser::add_default_value:iter:{}: has default vals", @@ -1249,11 +1221,9 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { debug!("Parser::add_default_value:iter:{}: wasn't used", arg.name); self.start_custom_arg(matcher, arg, ValueSource::DefaultValue); - self.add_multiple_vals_to_arg( - arg, - process_default_vals(arg, &arg.default_vals).into_iter(), - matcher, - )?; + for v in arg.default_vals.iter() { + self.add_val_to_arg(arg, &RawOsStr::new(v), matcher, trailing_values)?; + } } } else { debug!( @@ -1276,11 +1246,9 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { arg.name ); self.start_custom_arg(matcher, arg, ValueSource::DefaultValue); - self.add_multiple_vals_to_arg( - arg, - process_default_vals(arg, &arg.default_missing_vals).into_iter(), - matcher, - )?; + for v in arg.default_missing_vals.iter() { + self.add_val_to_arg(arg, &RawOsStr::new(v), matcher, trailing_values)?; + } } None => { debug!("Parser::add_default_value:iter:{}: wasn't used", arg.name); diff --git a/tests/builder/default_missing_vals.rs b/tests/builder/default_missing_vals.rs index 0700df6712f..11879f56d1c 100644 --- a/tests/builder/default_missing_vals.rs +++ b/tests/builder/default_missing_vals.rs @@ -174,6 +174,39 @@ fn default_missing_value_flag_value() { ); } +#[test] +fn delimited_missing_value() { + let cmd = Command::new("test").arg( + Arg::new("flag") + .long("flag") + .default_value("one,two") + .default_missing_value("three,four") + .min_values(0) + .value_delimiter(',') + .require_equals(true), + ); + + let m = cmd.clone().try_get_matches_from(["test"]).unwrap(); + assert_eq!( + m.get_many::("flag") + .unwrap() + .map(|s| s.as_str()) + .collect::>(), + vec!["one", "two"] + ); + assert_eq!(m.occurrences_of("flag"), 0); + + let m = cmd.try_get_matches_from(["test", "--flag"]).unwrap(); + assert_eq!( + m.get_many::("flag") + .unwrap() + .map(|s| s.as_str()) + .collect::>(), + vec!["three", "four"] + ); + assert_eq!(m.occurrences_of("flag"), 1); +} + #[cfg(debug_assertions)] #[test] #[should_panic = "Argument `arg`'s default_missing_value=\"value\" failed validation: error: \"value\" isn't a valid value for ''"]