From 52ec1f92e9c2f37074123b13efd287d6eedfa9ea Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 4 Aug 2022 11:20:18 -0500 Subject: [PATCH 1/3] fix: Clarify that `get_num_args` is safe to call The only time it won't be initialized is before `_build`. This is possible because of #4027 I wish I could just put the `expect` inside the call but I'm worried about allowing people to build stuff on top of clap. --- clap_complete/src/shells/zsh.rs | 5 +-- src/builder/arg.rs | 15 ++----- src/builder/debug_asserts.rs | 69 +++++++++++++++++---------------- src/output/help.rs | 2 +- src/parser/arg_matcher.rs | 15 +++---- src/parser/parser.rs | 61 ++++++++++++++--------------- src/parser/validator.rs | 2 +- 7 files changed, 77 insertions(+), 92 deletions(-) diff --git a/clap_complete/src/shells/zsh.rs b/clap_complete/src/shells/zsh.rs index 04fe1e4738e..f7c7b410fd6 100644 --- a/clap_complete/src/shells/zsh.rs +++ b/clap_complete/src/shells/zsh.rs @@ -462,10 +462,7 @@ fn write_opts_of(p: &Command, p_global: Option<&Command>) -> String { Some(val) => format!(":{}:{}", vn, val), None => format!(":{}: ", vn), }; - let vc = match o.get_num_args() { - Some(num_vals) => vc.repeat(num_vals.min_values()), - None => vc, - }; + let vc = vc.repeat(o.get_num_args().expect("built").min_values()); if let Some(shorts) = o.get_short_and_visible_aliases() { for short in shorts { diff --git a/src/builder/arg.rs b/src/builder/arg.rs index 72a113f9581..bfb68da1b61 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -3709,8 +3709,8 @@ impl<'help> Arg<'help> { } #[inline] - pub(crate) fn get_min_vals(&self) -> Option { - self.get_num_args().map(|r| r.min_values()) + pub(crate) fn get_min_vals(&self) -> usize { + self.get_num_args().expect(INTERNAL_ERROR_MSG).min_values() } /// Get the delimiter between multiple values @@ -4060,7 +4060,7 @@ impl<'help> Display for Arg<'help> { write!(f, "-{}", s)?; } let mut need_closing_bracket = false; - let is_optional_val = self.get_min_vals() == Some(0); + let is_optional_val = self.get_min_vals() == 0; if self.is_positional() { if is_optional_val { let sep = "["; @@ -4171,13 +4171,7 @@ pub(crate) fn render_arg_val(arg: &Arg) -> String { let mut extra_values = false; debug_assert!(arg.is_takes_value_set()); - let num_vals = arg.get_num_args().unwrap_or_else(|| { - if arg.is_multiple_values_set() { - (1..).into() - } else { - 1.into() - } - }); + let num_vals = arg.get_num_args().expect(INTERNAL_ERROR_MSG); if val_names.len() == 1 { let arg_name = format!("<{}>", val_names[0]); let min = num_vals.min_values().max(1); @@ -4187,7 +4181,6 @@ pub(crate) fn render_arg_val(arg: &Arg) -> String { } rendered.push_str(&arg_name); } - extra_values |= arg.get_num_args().is_none() && arg.is_multiple_values_set(); extra_values |= min < num_vals.max_values(); } else { debug_assert!(1 < val_names.len()); diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs index dc378084193..0e29e8024ef 100644 --- a/src/builder/debug_asserts.rs +++ b/src/builder/debug_asserts.rs @@ -5,6 +5,7 @@ use clap_lex::RawOsStr; use crate::builder::arg::ArgProvider; use crate::mkeymap::KeyType; use crate::ArgAction; +use crate::INTERNAL_ERROR_MSG; use crate::{Arg, Command, ValueHint}; pub(crate) fn assert_app(cmd: &Command) { @@ -535,7 +536,7 @@ fn _verify_positionals(cmd: &Command) -> bool { .get_positionals() .filter(|p| { p.is_multiple_values_set() - && !p.get_num_args().map(|r| r.is_fixed()).unwrap_or(false) + && !p.get_num_args().expect(INTERNAL_ERROR_MSG).is_fixed() }) .count(); let ok = count <= 1 @@ -690,44 +691,44 @@ fn assert_arg(arg: &Arg) { ); } - if let Some(num_vals) = arg.get_num_args() { - // This can be the cause of later asserts, so put this first - if num_vals != 0.into() { - // HACK: Don't check for flags to make the derive easier - let num_val_names = arg.get_value_names().unwrap_or(&[]).len(); - if num_vals.max_values() < num_val_names { - panic!( - "Argument {}: Too many value names ({}) compared to `num_args` ({})", - arg.name, num_val_names, num_vals - ); - } + let num_vals = arg.get_num_args().expect(INTERNAL_ERROR_MSG); + // This can be the cause of later asserts, so put this first + if num_vals != 0.into() { + // HACK: Don't check for flags to make the derive easier + let num_val_names = arg.get_value_names().unwrap_or(&[]).len(); + if num_vals.max_values() < num_val_names { + panic!( + "Argument {}: Too many value names ({}) compared to `num_args` ({})", + arg.name, num_val_names, num_vals + ); } + } - assert_eq!( - num_vals.takes_values(), - arg.is_takes_value_set(), - "Argument {}: mismatch between `num_args` ({}) and `takes_value`", - arg.name, - num_vals, - ); - assert_eq!( - num_vals.is_multiple(), - arg.is_multiple_values_set(), - "Argument {}: mismatch between `num_args` ({}) and `multiple_values`", + assert_eq!( + num_vals.takes_values(), + arg.is_takes_value_set(), + "Argument {}: mismatch between `num_args` ({}) and `takes_value`", + arg.name, + num_vals, + ); + assert_eq!( + num_vals.is_multiple(), + arg.is_multiple_values_set(), + "Argument {}: mismatch between `num_args` ({}) and `multiple_values`", + arg.name, + num_vals, + ); + + if 1 < num_vals.min_values() { + assert!( + !arg.is_require_equals_set(), + "Argument {}: cannot accept more than 1 arg (num_args={}) with require_equals", arg.name, - num_vals, + num_vals ); - - if 1 < num_vals.min_values() { - assert!( - !arg.is_require_equals_set(), - "Argument {}: cannot accept more than 1 arg (num_args={}) with require_equals", - arg.name, - num_vals - ); - } } - if arg.get_num_args() == Some(1.into()) { + + if num_vals == 1.into() { assert!( !arg.is_multiple_values_set(), "Argument {}: mismatch between `num_args` and `multiple_values`", diff --git a/src/output/help.rs b/src/output/help.rs index 394256b2523..1a2385a6283 100644 --- a/src/output/help.rs +++ b/src/output/help.rs @@ -297,7 +297,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> { debug!("Help::val: arg={}", arg.name); let mut need_closing_bracket = false; if arg.is_takes_value_set() && !arg.is_positional() { - let is_optional_val = arg.get_min_vals() == Some(0); + let is_optional_val = arg.get_min_vals() == 0; let sep = if arg.is_require_equals_set() { if is_optional_val { need_closing_bracket = true; diff --git a/src/parser/arg_matcher.rs b/src/parser/arg_matcher.rs index e220bdfe6d9..e4d5d7a3352 100644 --- a/src/parser/arg_matcher.rs +++ b/src/parser/arg_matcher.rs @@ -202,15 +202,12 @@ impl ArgMatcher { "ArgMatcher::needs_more_vals: o={}, pending={}", o.name, num_pending ); - if let Some(expected) = o.get_num_args() { - debug!( - "ArgMatcher::needs_more_vals: expected={}, actual={}", - expected, num_pending - ); - expected.accepts_more(num_pending) - } else { - o.is_multiple_values_set() - } + let expected = o.get_num_args().expect(INTERNAL_ERROR_MSG); + debug!( + "ArgMatcher::needs_more_vals: expected={}, actual={}", + expected, num_pending + ); + expected.accepts_more(num_pending) } pub(crate) fn pending_arg_id(&self) -> Option<&Id> { diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 786a7d76a81..b421dcebddf 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -978,7 +978,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { debug!("Parser::parse_opt_value; Checking for val..."); // require_equals is set, but no '=' is provided, try throwing error. if arg.is_require_equals_set() && !has_eq { - if arg.get_min_vals() == Some(0) { + if arg.get_min_vals() == 0 { debug!("Requires equals, but min_vals == 0"); let arg_values = Vec::new(); let trailing_idx = None; @@ -1252,9 +1252,9 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { } let actual = raw_vals.len(); + let expected = arg.get_num_args().expect(INTERNAL_ERROR_MSG); - let min_vals = arg.get_min_vals().unwrap_or(1); - if arg.is_takes_value_set() && 0 < min_vals && actual == 0 { + if 0 < expected.min_values() && actual == 0 { // Issue 665 (https://github.com/clap-rs/clap/issues/665) // Issue 1105 (https://github.com/clap-rs/clap/issues/1105) return Err(ClapError::empty_value( @@ -1266,42 +1266,39 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { .collect::>(), arg.to_string(), )); - } - - if let Some(expected) = arg.get_num_args() { - if let Some(expected) = expected.num_values() { - if expected != actual { - debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues"); - return Err(ClapError::wrong_number_of_values( - self.cmd, - arg.to_string(), - expected, - actual, - Usage::new(self.cmd).create_usage_with_title(&[]), - )); - } - } else if actual < expected.min_values() { - return Err(ClapError::too_few_values( + } else if let Some(expected) = expected.num_values() { + if expected != actual { + debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues"); + return Err(ClapError::wrong_number_of_values( self.cmd, arg.to_string(), - expected.min_values(), + expected, actual, Usage::new(self.cmd).create_usage_with_title(&[]), )); - } else if expected.max_values() < actual { - debug!("Validator::validate_arg_num_vals: Sending error TooManyValues"); - return Err(ClapError::too_many_values( - self.cmd, - raw_vals - .last() - .expect(INTERNAL_ERROR_MSG) - .to_string_lossy() - .into_owned(), - arg.to_string(), - Usage::new(self.cmd).create_usage_with_title(&[]), - )); } + } else if actual < expected.min_values() { + return Err(ClapError::too_few_values( + self.cmd, + arg.to_string(), + expected.min_values(), + actual, + Usage::new(self.cmd).create_usage_with_title(&[]), + )); + } else if expected.max_values() < actual { + debug!("Validator::validate_arg_num_vals: Sending error TooManyValues"); + return Err(ClapError::too_many_values( + self.cmd, + raw_vals + .last() + .expect(INTERNAL_ERROR_MSG) + .to_string_lossy() + .into_owned(), + arg.to_string(), + Usage::new(self.cmd).create_usage_with_title(&[]), + )); } + Ok(()) } diff --git a/src/parser/validator.rs b/src/parser/validator.rs index ae91f9729de..1470189d68a 100644 --- a/src/parser/validator.rs +++ b/src/parser/validator.rs @@ -33,7 +33,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> { let o = &self.cmd[&a]; let should_err = if let Some(v) = matcher.args.get(&o.id) { - v.all_val_groups_empty() && o.get_min_vals() != Some(0) + v.all_val_groups_empty() && o.get_min_vals() != 0 } else { true }; From 6e1ca59ec10c2d337766ef663a55f3e040dfa226 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 4 Aug 2022 14:44:11 -0500 Subject: [PATCH 2/3] fix!: Make is_takes_value_set private At this point, it is an implementation detail to help with book keeping within the builder. --- clap_complete/src/generator/utils.rs | 4 ++-- clap_complete/src/shells/fish.rs | 2 +- clap_complete_fig/src/fig.rs | 2 +- src/builder/arg.rs | 3 +-- src/macros.rs | 24 ++++++++++++++++-------- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/clap_complete/src/generator/utils.rs b/clap_complete/src/generator/utils.rs index 51a68c6eb15..27bf807808f 100644 --- a/clap_complete/src/generator/utils.rs +++ b/clap_complete/src/generator/utils.rs @@ -121,14 +121,14 @@ pub fn longs_and_visible_aliases(p: &Command) -> Vec { pub fn flags<'help>(p: &Command<'help>) -> Vec> { debug!("flags: name={}", p.get_name()); p.get_arguments() - .filter(|a| !a.is_takes_value_set() && !a.is_positional()) + .filter(|a| !a.get_num_args().expect("built").takes_values() && !a.is_positional()) .cloned() .collect() } /// Get the possible values for completion pub fn possible_values<'help>(a: &Arg<'help>) -> Option>> { - if !a.is_takes_value_set() { + if !a.get_num_args().expect("built").takes_values() { None } else { a.get_value_parser() diff --git a/clap_complete/src/shells/fish.rs b/clap_complete/src/shells/fish.rs index eb1e44b52c5..2550a22989b 100644 --- a/clap_complete/src/shells/fish.rs +++ b/clap_complete/src/shells/fish.rs @@ -148,7 +148,7 @@ fn gen_fish_inner( } fn value_completion(option: &Arg) -> String { - if !option.is_takes_value_set() { + if !option.get_num_args().expect("built").takes_values() { return "".to_string(); } diff --git a/clap_complete_fig/src/fig.rs b/clap_complete_fig/src/fig.rs index 32e426aa5ec..f7648df707a 100644 --- a/clap_complete_fig/src/fig.rs +++ b/clap_complete_fig/src/fig.rs @@ -321,7 +321,7 @@ fn gen_options(cmd: &Command, indent: usize) -> String { } fn gen_args(arg: &Arg, indent: usize) -> String { - if !arg.is_takes_value_set() { + if !arg.get_num_args().expect("built").takes_values() { return "".to_string(); } diff --git a/src/builder/arg.rs b/src/builder/arg.rs index bfb68da1b61..dcce85ffd8f 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -3795,8 +3795,7 @@ impl<'help> Arg<'help> { self.is_set(ArgSettings::MultipleValues) } - /// Report whether [`Arg::is_takes_value_set`] is set - pub fn is_takes_value_set(&self) -> bool { + pub(crate) fn is_takes_value_set(&self) -> bool { self.is_set(ArgSettings::TakesValue) } diff --git a/src/macros.rs b/src/macros.rs index 30463cae247..423288cafb0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -403,14 +403,22 @@ macro_rules! arg_impl { $crate::arg_impl! { @arg ({ - if $arg.get_long().is_none() && $arg.get_short().is_none() { - $arg.num_args(1..) - // Allow collecting arguments interleaved with flags - .action($crate::ArgAction::Append) - } else if $arg.is_takes_value_set() { - $arg.action($crate::ArgAction::Append) - } else { - $arg.action($crate::ArgAction::Count) + match $arg.get_action() { + $crate::ArgAction::Set => { + if $arg.get_long().is_none() && $arg.get_short().is_none() { + $arg.num_args(1..) + // Allow collecting arguments interleaved with flags + .action($crate::ArgAction::Append) + } else { + $arg.action($crate::ArgAction::Append) + } + }, + $crate::ArgAction::SetTrue => { + $arg.action($crate::ArgAction::Count) + } + action => { + panic!("Unexpected action {:?}", action) + } } }) $($tail)* From 32f308d4ef2f507c5fef584a6d765db62b8b60c9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 4 Aug 2022 14:53:42 -0500 Subject: [PATCH 3/3] fix!: Make is_multiple_values private multiple_values is now just book keeping for the builder, instead people should look to actions and `num_args`. The meaning for it was a little weird anyways. --- clap_complete/src/shells/zsh.rs | 3 ++- clap_complete_fig/src/fig.rs | 3 ++- src/builder/arg.rs | 3 +-- tests/macros.rs | 36 ++++++++++++++++----------------- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/clap_complete/src/shells/zsh.rs b/clap_complete/src/shells/zsh.rs index f7c7b410fd6..1dae45aa05e 100644 --- a/clap_complete/src/shells/zsh.rs +++ b/clap_complete/src/shells/zsh.rs @@ -622,7 +622,8 @@ fn write_positionals_of(p: &Command) -> String { for arg in p.get_positionals() { debug!("write_positionals_of:iter: arg={}", arg.get_id()); - let cardinality = if arg.is_multiple_values_set() { + let num_args = arg.get_num_args().expect("built"); + let cardinality = if num_args != 1.into() && num_args != 0.into() { "*:" } else if !arg.is_required_set() { ":" diff --git a/clap_complete_fig/src/fig.rs b/clap_complete_fig/src/fig.rs index f7648df707a..d0cc0b2c7f6 100644 --- a/clap_complete_fig/src/fig.rs +++ b/clap_complete_fig/src/fig.rs @@ -334,7 +334,8 @@ fn gen_args(arg: &Arg, indent: usize) -> String { indent = indent )); - if arg.is_multiple_values_set() { + let num_args = arg.get_num_args().expect("built"); + if num_args != 0.into() && num_args != 1.into() { buffer.push_str(&format!( "{:indent$}isVariadic: true,\n", "", diff --git a/src/builder/arg.rs b/src/builder/arg.rs index dcce85ffd8f..b74c9a1d6cd 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -3790,8 +3790,7 @@ impl<'help> Arg<'help> { self.is_set(ArgSettings::Required) } - /// Report whether [`Arg::num_args`] allows multiple values - pub fn is_multiple_values_set(&self) -> bool { + pub(crate) fn is_multiple_values_set(&self) -> bool { self.is_set(ArgSettings::MultipleValues) } diff --git a/tests/macros.rs b/tests/macros.rs index eeabbbde4cf..f22c1baa308 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -44,7 +44,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -52,7 +52,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -60,7 +60,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::Count)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -68,7 +68,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), Some("How to use it")); } @@ -80,7 +80,7 @@ mod arg { assert_eq!(arg.get_long(), Some("hello")); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -89,7 +89,7 @@ mod arg { assert_eq!(arg.get_long(), Some("hello")); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -98,7 +98,7 @@ mod arg { assert_eq!(arg.get_long(), Some("hello")); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::Count)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -107,7 +107,7 @@ mod arg { assert_eq!(arg.get_long(), Some("hello")); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), Some("How to use it")); } @@ -118,7 +118,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -126,7 +126,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -134,7 +134,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::Append)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -142,7 +142,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_short(), Some('b')); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), Some("How to use it")); } @@ -153,7 +153,7 @@ mod arg { assert_eq!(arg.get_id(), "NUM"); assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice())); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -161,7 +161,7 @@ mod arg { assert_eq!(arg.get_id(), "NUM"); assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice())); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(!arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -169,7 +169,7 @@ mod arg { assert_eq!(arg.get_id(), "NUM"); assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice())); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -177,7 +177,7 @@ mod arg { assert_eq!(arg.get_id(), "foo"); assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice())); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -185,7 +185,7 @@ mod arg { assert_eq!(arg.get_id(), "NUM"); assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice())); assert!(matches!(arg.get_action(), clap::ArgAction::Append)); - assert!(arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), Some((1..).into())); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), None); @@ -193,7 +193,7 @@ mod arg { assert_eq!(arg.get_id(), "NUM"); assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice())); assert!(matches!(arg.get_action(), clap::ArgAction::Set)); - assert!(!arg.is_multiple_values_set()); + assert_eq!(arg.get_num_args(), None); assert!(arg.is_required_set()); assert_eq!(arg.get_help(), Some("How to use it")); }