fix(usage)!: Separate mutli-occ from multi-val syntax

In looking at multiple occurrences and values for issues like #2692, I
noticed that `...` can mean both multiple values and multiple
occurrences, like before we split them.

Pros
- No syntax change with clap3

Cons
- All the reasons we split `multiple` into two

Uncertain
- I originally started this as part of another branch but I lost track
  if something depended on this.  I'll have to do more digging

BREAKING CHANGE: If `--opt [val]...` was meant for
- only multiple occurrences, see `[opt]... --opt [val]`
- both multiple occurrences and values, see `[opt]... --opt [val]...`
This commit is contained in:
Ed Page 2021-10-30 12:56:49 -05:00
parent dfa4690c96
commit 53bd42a809
5 changed files with 43 additions and 26 deletions

View file

@ -1278,7 +1278,7 @@ impl<'help> Arg<'help> {
/// ```
/// # use clap::{App, Arg};
/// let m = App::new("posix")
/// .arg(Arg::from("--opt [val]... 'some option'")
/// .arg(Arg::from("[opt]... --opt [val]... 'some option'")
/// .overrides_with("opt"))
/// .get_matches_from(vec!["", "--opt", "first", "over", "--opt", "other", "val"]);
/// assert!(m.is_present("opt"));

View file

@ -180,9 +180,12 @@ impl<'help> UsageParser<'help> {
if dot_counter == 3 {
debug!("UsageParser::multiple: setting multiple");
if arg.is_set(ArgSettings::TakesValue) {
// This is after `--name=value`, so requesting multiple value
arg.settings.set(ArgSettings::MultipleValues);
} else {
// This is after `[name]` (or a flag), so requesting multiple occurrences
arg.settings.set(ArgSettings::MultipleOccurrences);
}
arg.settings.set(ArgSettings::MultipleOccurrences);
self.prev = UsageToken::Multiple;
self.pos += 1;
break;
@ -415,7 +418,7 @@ mod test {
assert_eq!(a.short.unwrap(), 'o');
assert!(a.long.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -443,7 +446,7 @@ mod test {
assert_eq!(a.short.unwrap(), 'o');
assert!(a.long.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -457,7 +460,7 @@ mod test {
assert_eq!(a.short.unwrap(), 'o');
assert!(a.long.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -485,13 +488,27 @@ mod test {
assert_eq!(a.short.unwrap(), 'o');
assert!(a.long.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
assert_eq!(a.val_names.iter().collect::<Vec<_>>(), [&"opt"]);
}
#[test]
fn create_option_usage10() {
let a = Arg::from("[option]... -o [opt]... 'some help info'");
assert_eq!(a.name, "option");
assert_eq!(a.short.unwrap(), 'o');
assert!(a.long.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
assert_eq!(a.val_names.iter().collect::<Vec<_>>(), [&"opt"]);
}
#[test]
fn create_option_usage_long1() {
let a = Arg::from("[option] --opt [opt] 'some help info'");
@ -555,7 +572,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -583,7 +600,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -597,7 +614,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -625,7 +642,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -695,7 +712,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -723,7 +740,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -737,7 +754,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -765,7 +782,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert!(a.short.is_none());
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -849,7 +866,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert_eq!(a.short.unwrap(), 'o');
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -877,7 +894,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert_eq!(a.short.unwrap(), 'o');
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -961,7 +978,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert_eq!(a.short.unwrap(), 'o');
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(!a.is_set(ArgSettings::Required));
@ -989,7 +1006,7 @@ mod test {
assert_eq!(a.long.unwrap(), "opt");
assert_eq!(a.short.unwrap(), 'o');
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -1017,7 +1034,7 @@ mod test {
assert!(a.long.is_none());
assert_eq!(a.short.unwrap(), 'o');
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));
@ -1031,7 +1048,7 @@ mod test {
assert!(a.short.is_none());
assert_eq!(a.long.unwrap(), "opt");
assert_eq!(a.about.unwrap(), "some help info");
assert!(a.is_set(ArgSettings::MultipleOccurrences));
assert!(!a.is_set(ArgSettings::MultipleOccurrences));
assert!(a.is_set(ArgSettings::MultipleValues));
assert!(a.is_set(ArgSettings::TakesValue));
assert!(a.is_set(ArgSettings::Required));

View file

@ -1038,7 +1038,7 @@ fn aaos_opts_mult() {
let res = App::new("posix")
.setting(AppSettings::AllArgsOverrideSelf)
.arg(
Arg::from("--opt [val]... 'some option'")
Arg::from("[opt]... --opt [val]... 'some option'")
.number_of_values(1)
.takes_value(true)
.use_delimiter(true)
@ -1060,7 +1060,7 @@ fn aaos_opts_mult_req_delims() {
// opts with multiple and require delims
let res = App::new("posix")
.setting(AppSettings::AllArgsOverrideSelf)
.arg(Arg::from("--opt [val]... 'some option'"))
.arg(Arg::from("[opt]... --opt [val]... 'some option'"))
.try_get_matches_from(vec![
"",
"--opt",

View file

@ -38,7 +38,7 @@ fn option_overrides_itself() {
fn mult_option_require_delim_overrides_itself() {
let res = App::new("posix")
.arg(
Arg::from("--opt [val]... 'some option'")
Arg::from("[opt]... --opt [val]... 'some option'")
.overrides_with("opt")
.number_of_values(1)
.takes_value(true)
@ -59,7 +59,7 @@ fn mult_option_require_delim_overrides_itself() {
#[test]
fn mult_option_overrides_itself() {
let res = App::new("posix")
.arg(Arg::from("--opt [val]... 'some option'").overrides_with("opt"))
.arg(Arg::from("[opt]... --opt [val]... 'some option'").overrides_with("opt"))
.try_get_matches_from(vec![
"",
"--opt",

View file

@ -59,7 +59,7 @@ pub fn complex_app() -> App<'static> {
.version("v1.4.8")
.about("tests clap library")
.author("Kevin K. <kbknapp@gmail.com>")
.arg("-o --option=[opt]... 'tests options'")
.arg("[option]... -o --option=[opt]... 'tests options'")
.arg("[positional] 'tests positionals'")
.arg(Arg::from("-f --flag... 'tests flags'").global(true))
.args(&[
@ -82,7 +82,7 @@ pub fn complex_app() -> App<'static> {
.about("tests subcommands")
.version("0.1")
.author("Kevin K. <kbknapp@gmail.com>")
.arg("-o --option [scoption]... 'tests options'")
.arg("[option]... -o --option [scoption]... 'tests options'")
.arg("-s --subcmdarg [subcmdarg] 'tests other args'")
.arg("[scpositional] 'tests positionals'"),
)