Skip to content

Commit

Permalink
fix(parser): Allow delimiting default_missing_values
Browse files Browse the repository at this point in the history
Fixes #3761
  • Loading branch information
epage committed May 27, 2022
1 parent 9805fda commit ccc809a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 44 deletions.
56 changes: 12 additions & 44 deletions src/parser/parser.rs
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand All @@ -1016,19 +1016,6 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
}

fn add_multiple_vals_to_arg(
&self,
arg: &Arg<'help>,
raw_vals: impl Iterator<Item = OsString>,
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>,
Expand Down Expand Up @@ -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<OsString> {
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",
Expand All @@ -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!(
Expand All @@ -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);
Expand Down
33 changes: 33 additions & 0 deletions tests/builder/default_missing_vals.rs
Expand Up @@ -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::<String>("flag")
.unwrap()
.map(|s| s.as_str())
.collect::<Vec<_>>(),
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::<String>("flag")
.unwrap()
.map(|s| s.as_str())
.collect::<Vec<_>>(),
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 '<arg>'"]
Expand Down

0 comments on commit ccc809a

Please sign in to comment.