From ba15b5f43013cb96286072e5102c282da2a6cb7f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 3 Aug 2022 11:20:07 -0500 Subject: [PATCH 1/5] fix!: Rename Arg::number_of_values to Arg::num_args --- CHANGELOG.md | 16 +-- clap_bench/benches/03_complex.rs | 14 +-- clap_bench/benches/04_new_help.rs | 4 +- clap_bench/benches/05_ripgrep.rs | 2 +- clap_bench/benches/06_rustup.rs | 2 +- clap_complete/examples/completion.rs | 2 +- clap_complete/src/shells/zsh.rs | 2 +- clap_complete/tests/common.rs | 4 +- clap_complete_fig/tests/common.rs | 4 +- clap_derive/src/derives/args.rs | 6 +- clap_mangen/tests/common.rs | 2 +- examples/escaped-positional.rs | 2 +- examples/pacman.rs | 8 +- src/builder/arg.rs | 92 +++++++------- src/builder/command.rs | 8 +- src/builder/debug_asserts.rs | 13 +- src/builder/value_hint.rs | 4 +- src/error/kind.rs | 18 +-- src/macros.rs | 6 +- src/parser/arg_matcher.rs | 2 +- src/parser/matches/arg_matches.rs | 16 +-- src/parser/validator.rs | 2 +- tests/builder/app_settings.rs | 2 +- tests/builder/default_missing_vals.rs | 10 +- tests/builder/default_vals.rs | 6 +- tests/builder/delimiters.rs | 4 +- tests/builder/env.rs | 6 +- tests/builder/flag_subcommands.rs | 12 +- tests/builder/grouped_values.rs | 18 +-- tests/builder/groups.rs | 2 +- tests/builder/help.rs | 47 ++++--- tests/builder/indices.rs | 12 +- tests/builder/multiple_occurrences.rs | 6 +- tests/builder/multiple_values.rs | 170 ++++++++++---------------- tests/builder/opts.rs | 14 +-- tests/builder/positionals.rs | 6 +- tests/builder/possible_values.rs | 8 +- tests/builder/require.rs | 6 +- tests/builder/subcommands.rs | 2 +- tests/builder/utils.rs | 12 +- tests/derive/options.rs | 4 +- 41 files changed, 262 insertions(+), 314 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8789bafb08b..f9f61f2dab6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,12 +20,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `arg!` now sets `ArgAction::SetTrue`, `ArgAction::Count`, `ArgAction::Set`, or `ArgAction::Append` as appropriate (#3795) - Default actions are now `Set` and `SetTrue` - Removed `PartialEq` and `Eq` from `Command` -- `Arg::number_of_values` now applies per occurrence rather than the average across all occurrences -- `number_of_values(0)` no longer implies `takes_value(true).multiple_values(true)` -- `number_of_values(1)` no longer implies `multiple_values(true)` -- Remove `Arg::min_values` (across all occurrences) with `Arg::number_of_values(N..)` (per occurrence) -- Remove `Arg::max_values` (across all occurrences) with `Arg::number_of_values(1..=M)` (per occurrence) -- Remove `Arg::multiple_values(true)` with `Arg::number_of_values(1..)` and `Arg::multiple_values(false)` with `Arg::number_of_values(0)` +- Replace `Arg::number_of_values` (average across occurrences) with `Arg::num_args` (per occurrence) + - `num_args(0)` no longer implies `takes_value(true).multiple_values(true)` + - `num_args(1)` no longer implies `multiple_values(true)` +- Replace `Arg::min_values` (across all occurrences) with `Arg::num_args(N..)` (per occurrence) +- Replace `Arg::max_values` (across all occurrences) with `Arg::num_args(1..=M)` (per occurrence) +- Replace `Arg::multiple_values(true)` with `Arg::num_args(1..)` and `Arg::multiple_values(false)` with `Arg::num_args(0)` - Remove `Arg::use_value_delimiter` in favor of `Arg::value_delimiter` - `ArgAction::SetTrue` and `ArgAction::SetFalse` now prioritize `Arg::default_missing_value` over their standard behavior - *(help)* Make `DeriveDisplayOrder` the default and removed the setting. To sort help, set `next_display_order(None)` (#2808) @@ -36,14 +36,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Features -- `Arg::number_of_values` now accepts ranges, allowing setting both the minimum and maximum number of values per occurrence +- `Arg::num_args` now accepts ranges, allowing setting both the minimum and maximum number of values per occurrence - *(help)* Show `PossibleValue::help` in long help (`--help`) (#3312) ### Fixes - Leading dashes in `Arg::long` are no longer allowed (#3691) - Verify `required` is not used with conditional required settings (#3660) -- Disallow more `value_names` than `number_of_values` (#2695) +- Disallow more `value_names` than `num_args` (#2695) - Replaced `cmd.allow_invalid_for_utf8_external_subcommands` with `cmd.external_subcommand_value_parser` (#3733) - Changed the default type of `allow_external_subcommands` from `String` to `OsString` - `Arg::default_missing_value` now applies per occurrence rather than if a value is missing across all occurrences diff --git a/clap_bench/benches/03_complex.rs b/clap_bench/benches/03_complex.rs index bd9583f45a0..32b6dec634a 100644 --- a/clap_bench/benches/03_complex.rs +++ b/clap_bench/benches/03_complex.rs @@ -31,8 +31,8 @@ macro_rules! create_app { arg!( --multvalsmo "Tests multiple values, not mult occs" ).required(false).value_names(&["one", "two"]), - arg!(--minvals2 ... "Tests 2 min vals").number_of_values(2..).required(false), - arg!(--maxvals3 ... "Tests 3 max vals").number_of_values(1..=3).required(false), + arg!(--minvals2 ... "Tests 2 min vals").num_args(2..).required(false), + arg!(--maxvals3 ... "Tests 3 max vals").num_args(1..=3).required(false), ]) .subcommand( Command::new("subcmd") @@ -57,7 +57,7 @@ pub fn build_from_builder(c: &mut Criterion) { .help("tests options") .short('o') .long("option") - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .arg(Arg::new("positional").help("tests positionals").index(1)) @@ -99,7 +99,7 @@ pub fn build_from_builder(c: &mut Criterion) { ) .arg( Arg::new("positional3") - .number_of_values(1..) + .num_args(1..) .help("tests positionals with specific values") .index(4) .value_parser(POS3_VALS), @@ -122,14 +122,14 @@ pub fn build_from_builder(c: &mut Criterion) { .long("minvals2") .action(ArgAction::Append) .help("Tests 2 min vals") - .number_of_values(2..), + .num_args(2..), ) .arg( Arg::new("maxvals") .long("maxvals3") .action(ArgAction::Append) .help("Tests 3 max vals") - .number_of_values(1..=3), + .num_args(1..=3), ) .subcommand( Command::new("subcmd") @@ -140,7 +140,7 @@ pub fn build_from_builder(c: &mut Criterion) { Arg::new("scoption") .short('o') .long("option") - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append) .help("tests options"), ) diff --git a/clap_bench/benches/04_new_help.rs b/clap_bench/benches/04_new_help.rs index cbc5d36cf31..758260ffcc1 100644 --- a/clap_bench/benches/04_new_help.rs +++ b/clap_bench/benches/04_new_help.rs @@ -118,7 +118,7 @@ fn app_example7<'c>() -> Command<'c> { .arg( Arg::new("input") .help("the input file to use") - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append) .required(true) .short('i') @@ -135,7 +135,7 @@ fn app_example8<'c>() -> Command<'c> { .arg( Arg::new("input") .help("the input file to use") - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append) .required(true) .short('i') diff --git a/clap_bench/benches/05_ripgrep.rs b/clap_bench/benches/05_ripgrep.rs index 519471aa02a..30e2ba7812e 100644 --- a/clap_bench/benches/05_ripgrep.rs +++ b/clap_bench/benches/05_ripgrep.rs @@ -323,7 +323,7 @@ where "type-list", "version", ])) - .arg(arg("path").number_of_values(1..)) + .arg(arg("path").num_args(1..)) .arg( flag("regexp") .short('e') diff --git a/clap_bench/benches/06_rustup.rs b/clap_bench/benches/06_rustup.rs index 96196411bd3..f79cb6eed15 100644 --- a/clap_bench/benches/06_rustup.rs +++ b/clap_bench/benches/06_rustup.rs @@ -236,7 +236,7 @@ fn build_cli() -> Command<'static> { .after_help(RUN_HELP) .trailing_var_arg(true) .arg(Arg::new("toolchain").required(true)) - .arg(Arg::new("command").required(true).number_of_values(1..)), + .arg(Arg::new("command").required(true).num_args(1..)), ) .subcommand( Command::new("which") diff --git a/clap_complete/examples/completion.rs b/clap_complete/examples/completion.rs index e506222736e..27150a948d4 100644 --- a/clap_complete/examples/completion.rs +++ b/clap_complete/examples/completion.rs @@ -68,7 +68,7 @@ fn build_cli() -> Command<'static> { ) .arg( Arg::new("command_with_args") - .number_of_values(1..) + .num_args(1..) .value_hint(ValueHint::CommandWithArguments), ) .arg( diff --git a/clap_complete/src/shells/zsh.rs b/clap_complete/src/shells/zsh.rs index 16b47647a04..04fe1e4738e 100644 --- a/clap_complete/src/shells/zsh.rs +++ b/clap_complete/src/shells/zsh.rs @@ -462,7 +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_vals() { + let vc = match o.get_num_args() { Some(num_vals) => vc.repeat(num_vals.min_values()), None => vc, }; diff --git a/clap_complete/tests/common.rs b/clap_complete/tests/common.rs index f1d0323883a..f2512389a92 100644 --- a/clap_complete/tests/common.rs +++ b/clap_complete/tests/common.rs @@ -64,7 +64,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command<'static> { .require_equals(true) .help("the other case to test"), ) - .arg(clap::Arg::new("path").number_of_values(1..)), + .arg(clap::Arg::new("path").num_args(1..)), ) .subcommand(clap::Command::new("some-cmd-with-hyphens").alias("hyphen")) .subcommand(clap::Command::new("some-hidden-cmd").hide(true)) @@ -220,7 +220,7 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> { .arg( clap::Arg::new("command_with_args") .action(clap::ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .value_hint(clap::ValueHint::CommandWithArguments), ) .arg( diff --git a/clap_complete_fig/tests/common.rs b/clap_complete_fig/tests/common.rs index f1d0323883a..f2512389a92 100644 --- a/clap_complete_fig/tests/common.rs +++ b/clap_complete_fig/tests/common.rs @@ -64,7 +64,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command<'static> { .require_equals(true) .help("the other case to test"), ) - .arg(clap::Arg::new("path").number_of_values(1..)), + .arg(clap::Arg::new("path").num_args(1..)), ) .subcommand(clap::Command::new("some-cmd-with-hyphens").alias("hyphen")) .subcommand(clap::Command::new("some-hidden-cmd").hide(true)) @@ -220,7 +220,7 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> { .arg( clap::Arg::new("command_with_args") .action(clap::ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .value_hint(clap::ValueHint::CommandWithArguments), ) .arg( diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index 689a2418ee5..d5943e61c0d 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -258,7 +258,7 @@ pub fn gen_augment( Ty::OptionOption => quote_spanned! { ty.span()=> .value_name(#value_name) - .number_of_values(0..=1) + .num_args(0..=1) #value_parser #action }, @@ -267,7 +267,7 @@ pub fn gen_augment( if attrs.is_positional() { quote_spanned! { ty.span()=> .value_name(#value_name) - .number_of_values(1..) // action won't be sufficient for getting multiple + .num_args(1..) // action won't be sufficient for getting multiple #value_parser #action } @@ -284,7 +284,7 @@ pub fn gen_augment( if attrs.is_positional() { quote_spanned! { ty.span()=> .value_name(#value_name) - .number_of_values(1..) // action won't be sufficient for getting multiple + .num_args(1..) // action won't be sufficient for getting multiple #value_parser #action } diff --git a/clap_mangen/tests/common.rs b/clap_mangen/tests/common.rs index 025ffef923e..242e3eadf84 100644 --- a/clap_mangen/tests/common.rs +++ b/clap_mangen/tests/common.rs @@ -216,7 +216,7 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> { .arg( clap::Arg::new("command_with_args") .action(clap::ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .value_hint(clap::ValueHint::CommandWithArguments), ) .arg( diff --git a/examples/escaped-positional.rs b/examples/escaped-positional.rs index e0505b9d339..40135cab00c 100644 --- a/examples/escaped-positional.rs +++ b/examples/escaped-positional.rs @@ -11,7 +11,7 @@ fn main() { .arg( // Indicates that `slop` is only accessible after `--`. arg!(slop: [SLOP]) - .number_of_values(1..) + .num_args(1..) .last(true) .value_parser(value_parser!(String)), ) diff --git a/examples/pacman.rs b/examples/pacman.rs index f532bc68cce..6844282939c 100644 --- a/examples/pacman.rs +++ b/examples/pacman.rs @@ -22,7 +22,7 @@ fn main() { .help("search locally installed packages for matching strings") .conflicts_with("info") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .arg( Arg::new("info") @@ -31,7 +31,7 @@ fn main() { .conflicts_with("search") .help("view package information") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ), ) // Sync subcommand @@ -48,7 +48,7 @@ fn main() { .long("search") .conflicts_with("info") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .help("search remote repositories for matching strings"), ) .arg( @@ -64,7 +64,7 @@ fn main() { .help("packages") .required_unless_present("search") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ), ) .get_matches(); diff --git a/src/builder/arg.rs b/src/builder/arg.rs index 5ac7019d403..70557e3bd4d 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -411,7 +411,7 @@ impl<'help> Arg<'help> { /// **NOTE:** This is only meant to be used for positional arguments and shouldn't to be used /// with [`Arg::short`] or [`Arg::long`]. /// - /// **NOTE:** When utilized with [`Arg::number_of_values(1..)`], only the **last** positional argument + /// **NOTE:** When utilized with [`Arg::num_args(1..)`], only the **last** positional argument /// may be defined as having a variable number of arguments (i.e. with the highest index) /// /// # Panics @@ -447,7 +447,7 @@ impl<'help> Arg<'help> { /// ``` /// [`Arg::short`]: Arg::short() /// [`Arg::long`]: Arg::long() - /// [`Arg::number_of_values(true)`]: Arg::number_of_values() + /// [`Arg::num_args(true)`]: Arg::num_args() /// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html /// [`Command`]: crate::Command #[inline] @@ -801,7 +801,7 @@ impl<'help> Arg<'help> { /// assert!(m.contains_id("mode")); /// assert_eq!(m.get_one::("mode").unwrap(), "fast"); /// ``` - /// [multiple values]: Arg::number_of_values + /// [multiple values]: Arg::num_args #[inline] #[must_use] pub fn takes_value(self, yes: bool) -> Self { @@ -911,7 +911,7 @@ impl<'help> Arg<'help> { /// Specifies the number of values allowed per occurrence of this argument /// /// For example, if you had a `-f ` argument where you wanted exactly 3 'files' you would - /// set `.number_of_values(3)`, and this argument wouldn't be satisfied unless the user + /// set `.num_args(3)`, and this argument wouldn't be satisfied unless the user /// provided 3 and only 3 values. /// /// **NOTE:** Users may specify values for arguments in any of the following methods @@ -946,7 +946,7 @@ impl<'help> Arg<'help> { /// let m = Command::new("prog") /// .arg(Arg::new("mode") /// .long("mode") - /// .number_of_values(1)) + /// .num_args(1)) /// .get_matches_from(vec![ /// "prog", "--mode", "fast" /// ]); @@ -962,7 +962,7 @@ impl<'help> Arg<'help> { /// .long("mode") /// .default_missing_value("slow") /// .default_value("plaid") - /// .number_of_values(0..=1)); + /// .num_args(0..=1)); /// /// let m = cmd.clone() /// .get_matches_from(vec![ @@ -989,7 +989,7 @@ impl<'help> Arg<'help> { /// let cmd = Command::new("prog") /// .arg(Arg::new("file") /// .action(ArgAction::Set) - /// .number_of_values(2) + /// .num_args(2) /// .short('F')); /// /// let m = cmd.clone() @@ -1015,7 +1015,7 @@ impl<'help> Arg<'help> { /// let cmd = Command::new("prog") /// .arg(Arg::new("file") /// .action(ArgAction::Set) - /// .number_of_values(0..) + /// .num_args(0..) /// .short('F')) /// .arg(Arg::new("word")); /// @@ -1055,7 +1055,7 @@ impl<'help> Arg<'help> { /// ``` #[inline] #[must_use] - pub fn number_of_values(mut self, qty: impl Into) -> Self { + pub fn num_args(mut self, qty: impl Into) -> Self { let qty = qty.into(); self.num_vals = Some(qty); self.takes_value(qty.takes_values()) @@ -1128,7 +1128,7 @@ impl<'help> Arg<'help> { /// **Pro Tip:** It may help to use [`Arg::next_line_help(true)`] if there are long, or /// multiple value names in order to not throw off the help text alignment of all options. /// - /// **NOTE:** implicitly sets [`Arg::action(ArgAction::Set)`] and [`Arg::number_of_values(1..)`]. + /// **NOTE:** implicitly sets [`Arg::action(ArgAction::Set)`] and [`Arg::num_args(1..)`]. /// /// # Examples /// @@ -1164,9 +1164,9 @@ impl<'help> Arg<'help> { /// -V, --version Print version information /// ``` /// [`Arg::next_line_help(true)`]: Arg::next_line_help() - /// [`Arg::number_of_values`]: Arg::number_of_values() + /// [`Arg::num_args`]: Arg::num_args() /// [`Arg::action(ArgAction::Set)`]: Arg::takes_value() - /// [`Arg::number_of_values(1..)`]: Arg::number_of_values() + /// [`Arg::num_args(1..)`]: Arg::num_args() #[must_use] pub fn value_names(mut self, names: &[&'help str]) -> Self { self.val_names = names.to_vec(); @@ -1198,7 +1198,7 @@ impl<'help> Arg<'help> { /// .arg( /// Arg::new("command") /// .action(ArgAction::Set) - /// .number_of_values(1..) + /// .num_args(1..) /// .value_hint(ValueHint::CommandWithArguments) /// ); /// ``` @@ -1247,7 +1247,7 @@ impl<'help> Arg<'help> { /// .long("option") /// .action(ArgAction::Set) /// .ignore_case(true) - /// .number_of_values(1..) + /// .num_args(1..) /// .value_parser(["test123", "test321"])) /// .get_matches_from(vec![ /// "pv", "--option", "TeSt123", "teST123", "tESt321" @@ -1271,7 +1271,7 @@ impl<'help> Arg<'help> { /// **NOTE:** Setting this requires [`Arg::takes_value`] /// /// **WARNING**: Take caution when using this setting combined with - /// [`Arg::number_of_values`], as this becomes ambiguous `$ prog --arg -- -- val`. All + /// [`Arg::num_args`], as this becomes ambiguous `$ prog --arg -- -- val`. All /// three `--, --, val` will be values when the user may have thought the second `--` would /// constitute the normal, "Only positional args follow" idiom. /// @@ -1314,7 +1314,7 @@ impl<'help> Arg<'help> { /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument); /// ``` - /// [`Arg::number_of_values(1)`]: Arg::number_of_values() + /// [`Arg::num_args(1)`]: Arg::num_args() #[inline] #[must_use] pub fn allow_hyphen_values(self, yes: bool) -> Self { @@ -1431,7 +1431,7 @@ impl<'help> Arg<'help> { /// .action(ArgAction::Set) /// .value_delimiter(',') /// .require_value_delimiter(true) - /// .number_of_values(1..)) + /// .num_args(1..)) /// .get_matches_from(vec![ /// "prog", "-o", "val1,val2,val3", /// ]); @@ -1471,7 +1471,7 @@ impl<'help> Arg<'help> { /// .arg(Arg::new("opt") /// .short('o') /// .action(ArgAction::Set) - /// .number_of_values(1..)) + /// .num_args(1..)) /// .get_matches_from(vec![ /// "prog", "-o", "val1", "val2", "val3", /// ]); @@ -1494,9 +1494,9 @@ impl<'help> Arg<'help> { /// Sentinel to **stop** parsing multiple values of a given argument. /// /// By default when - /// one sets [`number_of_values(1..)`] on an argument, clap will continue parsing values for that + /// one sets [`num_args(1..)`] on an argument, clap will continue parsing values for that /// argument until it reaches another valid argument, or one of the other more specific settings - /// for multiple values is used (such as [`number_of_values`]). + /// for multiple values is used (such as [`num_args`]). /// /// **NOTE:** This setting only applies to [options] and [positional arguments] /// @@ -1509,7 +1509,7 @@ impl<'help> Arg<'help> { /// # use clap::{Command, Arg, ArgAction}; /// Arg::new("vals") /// .action(ArgAction::Set) - /// .number_of_values(1..) + /// .num_args(1..) /// .value_terminator(";") /// # ; /// ``` @@ -1522,7 +1522,7 @@ impl<'help> Arg<'help> { /// let m = Command::new("prog") /// .arg(Arg::new("cmds") /// .action(ArgAction::Set) - /// .number_of_values(1..) + /// .num_args(1..) /// .allow_hyphen_values(true) /// .value_terminator(";")) /// .arg(Arg::new("location")) @@ -1535,8 +1535,8 @@ impl<'help> Arg<'help> { /// ``` /// [options]: Arg::takes_value() /// [positional arguments]: Arg::index() - /// [`number_of_values(1..)`]: Arg::number_of_values() - /// [`number_of_values`]: Arg::number_of_values() + /// [`num_args(1..)`]: Arg::num_args() + /// [`num_args`]: Arg::num_args() #[inline] #[must_use] pub fn value_terminator(mut self, term: &'help str) -> Self { @@ -1559,11 +1559,11 @@ impl<'help> Arg<'help> { /// may not be exactly what you are expecting and using [`crate::Command::trailing_var_arg`] /// may be more appropriate. /// - /// **NOTE:** Implicitly sets [`Arg::action(ArgAction::Set)`] [`Arg::number_of_values(1..)`], + /// **NOTE:** Implicitly sets [`Arg::action(ArgAction::Set)`] [`Arg::num_args(1..)`], /// [`Arg::allow_hyphen_values(true)`], and [`Arg::last(true)`] when set to `true`. /// /// [`Arg::action(ArgAction::Set)`]: Arg::takes_value() - /// [`Arg::number_of_values(1..)`]: Arg::number_of_values() + /// [`Arg::num_args(1..)`]: Arg::num_args() /// [`Arg::allow_hyphen_values(true)`]: Arg::allow_hyphen_values() /// [`Arg::last(true)`]: Arg::last() #[inline] @@ -1680,7 +1680,7 @@ impl<'help> Arg<'help> { /// the user can quickly just add `--color` to the command line to produce the desired color output. /// /// **NOTE:** using this configuration option requires the use of the - /// [`.number_of_values(0..N)`][Arg::number_of_values] and the + /// [`.num_args(0..N)`][Arg::num_args] and the /// [`.require_equals(true)`][Arg::require_equals] configuration option. These are required in /// order to unambiguously determine what, if any, value was supplied for the argument. /// @@ -1695,7 +1695,7 @@ impl<'help> Arg<'help> { /// .value_name("WHEN") /// .value_parser(["always", "auto", "never"]) /// .default_value("auto") - /// .number_of_values(0..=1) + /// .num_args(0..=1) /// .require_equals(true) /// .default_missing_value("always") /// .help("Specify WHEN to colorize output.") @@ -1732,7 +1732,7 @@ impl<'help> Arg<'help> { /// .arg(Arg::new("create").long("create") /// .value_name("BOOL") /// .value_parser(value_parser!(bool)) - /// .number_of_values(0..=1) + /// .num_args(0..=1) /// .require_equals(true) /// .default_missing_value("true") /// ) @@ -1936,7 +1936,7 @@ impl<'help> Arg<'help> { /// .long("flag") /// .env("MY_FLAG_MULTI") /// .action(ArgAction::Set) - /// .number_of_values(1..) + /// .num_args(1..) /// .value_delimiter(',')) /// .get_matches_from(vec![ /// "prog" @@ -3811,13 +3811,13 @@ impl<'help> Arg<'help> { /// Get the number of values for this argument. #[inline] - pub fn get_num_vals(&self) -> Option { + pub fn get_num_args(&self) -> Option { self.num_vals } #[inline] pub(crate) fn get_min_vals(&self) -> Option { - self.get_num_vals().map(|r| r.min_values()) + self.get_num_args().map(|r| r.min_values()) } /// Get the delimiter between multiple values @@ -3897,7 +3897,7 @@ impl<'help> Arg<'help> { self.is_set(ArgSettings::Required) } - /// Report whether [`Arg::number_of_values`] allows multiple values + /// Report whether [`Arg::num_args`] allows multiple values pub fn is_multiple_values_set(&self) -> bool { self.is_set(ArgSettings::MultipleValues) } @@ -4286,7 +4286,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_vals().unwrap_or_else(|| { + let num_vals = arg.get_num_args().unwrap_or_else(|| { if arg.is_multiple_values_set() { (1..).into() } else { @@ -4302,7 +4302,7 @@ pub(crate) fn render_arg_val(arg: &Arg) -> String { } rendered.push_str(&arg_name); } - extra_values |= arg.get_num_vals().is_none() && arg.is_multiple_values_set(); + 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()); @@ -4414,7 +4414,7 @@ mod test { let mut o = Arg::new("opt") .long("option") .action(ArgAction::Set) - .number_of_values(1..); + .num_args(1..); o._build(); assert_eq!(o.to_string(), "--option ..."); @@ -4425,7 +4425,7 @@ mod test { let mut o = Arg::new("opt") .long("option") .action(ArgAction::Set) - .number_of_values(0..); + .num_args(0..); o._build(); assert_eq!(o.to_string(), "--option [...]"); @@ -4436,7 +4436,7 @@ mod test { let mut o = Arg::new("opt") .long("option") .action(ArgAction::Set) - .number_of_values(1..); + .num_args(1..); o._build(); assert_eq!(o.to_string(), "--option ..."); @@ -4447,7 +4447,7 @@ mod test { let mut o = Arg::new("opt") .short('o') .action(ArgAction::Set) - .number_of_values(0..) + .num_args(0..) .value_names(&["file"]); o._build(); @@ -4459,7 +4459,7 @@ mod test { let mut o = Arg::new("opt") .short('o') .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .value_names(&["file"]); o._build(); @@ -4471,7 +4471,7 @@ mod test { let mut o = Arg::new("opt") .long("option") .action(ArgAction::Set) - .number_of_values(0..=1); + .num_args(0..=1); o._build(); assert_eq!(o.to_string(), "--option []"); @@ -4492,7 +4492,7 @@ mod test { fn option_display3() { let mut o = Arg::new("opt") .short('o') - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Set) .value_names(&["file", "name"]); o._build(); @@ -4550,7 +4550,7 @@ mod test { #[test] fn positional_display_multiple_values() { - let mut p = Arg::new("pos").index(1).number_of_values(1..); + let mut p = Arg::new("pos").index(1).num_args(1..); p._build(); assert_eq!(p.to_string(), "..."); @@ -4558,7 +4558,7 @@ mod test { #[test] fn positional_display_zero_or_more_values() { - let mut p = Arg::new("pos").index(1).number_of_values(0..); + let mut p = Arg::new("pos").index(1).num_args(0..); p._build(); assert_eq!(p.to_string(), "[...]"); @@ -4566,7 +4566,7 @@ mod test { #[test] fn positional_display_one_or_more_values() { - let mut p = Arg::new("pos").index(1).number_of_values(1..); + let mut p = Arg::new("pos").index(1).num_args(1..); p._build(); assert_eq!(p.to_string(), "..."); @@ -4576,7 +4576,7 @@ mod test { fn positional_display_optional_value() { let mut p = Arg::new("pos") .index(1) - .number_of_values(0..=1) + .num_args(0..=1) .action(ArgAction::Set); p._build(); diff --git a/src/builder/command.rs b/src/builder/command.rs index 58c31a54d04..f202956a157 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -2116,7 +2116,7 @@ impl<'help> Command<'help> { /// .allow_missing_positional(true) /// .arg(Arg::new("foo")) /// .arg(Arg::new("bar")) - /// .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..)) + /// .arg(Arg::new("baz").action(ArgAction::Set).num_args(1..)) /// .get_matches_from(vec![ /// "prog", "foo", "bar", "baz1", "baz2", "baz3" /// ]); @@ -2135,7 +2135,7 @@ impl<'help> Command<'help> { /// .allow_missing_positional(true) /// .arg(Arg::new("foo")) /// .arg(Arg::new("bar")) - /// .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..)) + /// .arg(Arg::new("baz").action(ArgAction::Set).num_args(1..)) /// .get_matches_from(vec![ /// "prog", "--", "baz1", "baz2", "baz3" /// ]); @@ -2831,7 +2831,7 @@ impl<'help> Command<'help> { /// let cmd = Command::new("cmd").subcommand(Command::new("sub")).arg( /// Arg::new("arg") /// .long("arg") - /// .number_of_values(1..) + /// .num_args(1..) /// .action(ArgAction::Set), /// ); /// @@ -4254,7 +4254,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", Arg::new("subcommand") .index(1) .action(ArgAction::Append) - .number_of_values(..) + .num_args(..) .value_name("SUBCOMMAND") .help("The subcommand whose help message to display"), ); diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs index 38b744fbdb2..94aece65ba2 100644 --- a/src/builder/debug_asserts.rs +++ b/src/builder/debug_asserts.rs @@ -517,7 +517,7 @@ fn _verify_positionals(cmd: &Command) -> bool { || last.is_last_set(); assert!( ok, - "When using a positional argument with .number_of_values(1..) that is *not the \ + "When using a positional argument with .num_args(1..) that is *not the \ last* positional argument, the last positional argument (i.e. the one \ with the highest index) *must* have .required(true) or .last(true) set." ); @@ -527,14 +527,15 @@ fn _verify_positionals(cmd: &Command) -> bool { assert!( ok, "Only the last positional argument, or second to last positional \ - argument may be set to .number_of_values(1..)" + argument may be set to .num_args(1..)" ); // Next we check how many have both Multiple and not a specific number of values set let count = cmd .get_positionals() .filter(|p| { - p.is_multiple_values_set() && !p.num_vals.map(|r| r.is_fixed()).unwrap_or(false) + p.is_multiple_values_set() + && !p.get_num_args().map(|r| r.is_fixed()).unwrap_or(false) }) .count(); let ok = count <= 1 @@ -544,7 +545,7 @@ fn _verify_positionals(cmd: &Command) -> bool { && count == 2); assert!( ok, - "Only one positional argument with .number_of_values(1..) set is allowed per \ + "Only one positional argument with .num_args(1..) set is allowed per \ command, unless the second one also has .last(true) set" ); } @@ -689,7 +690,7 @@ fn assert_arg(arg: &Arg) { ); } - if let Some(num_vals) = arg.get_num_vals() { + if let Some(num_vals) = arg.get_num_args() { // This can be the cause of later asserts, so put this first let num_val_names = arg.get_value_names().unwrap_or(&[]).len(); if num_vals.max_values() < num_val_names { @@ -714,7 +715,7 @@ fn assert_arg(arg: &Arg) { num_vals, ); } - if arg.get_num_vals() == Some(1.into()) { + if arg.get_num_args() == Some(1.into()) { assert!( !arg.is_multiple_values_set(), "Argument {}: mismatch between `number_of_values` and `multiple_values`", diff --git a/src/builder/value_hint.rs b/src/builder/value_hint.rs index 5097f1aff1b..812d5d8668b 100644 --- a/src/builder/value_hint.rs +++ b/src/builder/value_hint.rs @@ -48,12 +48,12 @@ pub enum ValueHint { /// common when writing shell wrappers that execute anther command, for example `sudo` or `env`. /// /// This hint is special, the argument must be a positional argument and have - /// [`.number_of_values(1..)`] and Command must use [`Command::trailing_var_arg(true)`]. The result is that the + /// [`.num_args(1..)`] and Command must use [`Command::trailing_var_arg(true)`]. The result is that the /// command line `my_app ls -la /` will be parsed as `["ls", "-la", "/"]` and clap won't try to /// parse the `-la` argument itself. /// /// [`Command::trailing_var_arg(true)`]: crate::Command::trailing_var_arg - /// [`.number_of_values(1..)`]: crate::Arg::number_of_values() + /// [`.num_args(1..)`]: crate::Arg::num_args() CommandWithArguments, /// Name of a local operating system user. Username, diff --git a/src/error/kind.rs b/src/error/kind.rs index 77f74cead64..c9e42253f2c 100644 --- a/src/error/kind.rs +++ b/src/error/kind.rs @@ -96,7 +96,7 @@ pub enum ErrorKind { ValueValidation, /// Occurs when a user provides more values for an argument than were defined by setting - /// [`Arg::number_of_values`]. + /// [`Arg::num_args`]. /// /// # Examples /// @@ -104,17 +104,17 @@ pub enum ErrorKind { /// # use clap::{Command, Arg, error::ErrorKind}; /// let result = Command::new("prog") /// .arg(Arg::new("arg") - /// .number_of_values(1..=2) + /// .num_args(1..=2) /// .require_value_delimiter(true)) /// .try_get_matches_from(vec!["prog", "too,many,values"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues); /// ``` - /// [`Arg::number_of_values`]: crate::Arg::number_of_values() + /// [`Arg::num_args`]: crate::Arg::num_args() TooManyValues, /// Occurs when the user provides fewer values for an argument than were defined by setting - /// [`Arg::number_of_values`]. + /// [`Arg::num_args`]. /// /// # Examples /// @@ -123,16 +123,16 @@ pub enum ErrorKind { /// let result = Command::new("prog") /// .arg(Arg::new("some_opt") /// .long("opt") - /// .number_of_values(3..)) + /// .num_args(3..)) /// .try_get_matches_from(vec!["prog", "--opt", "too", "few"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues); /// ``` - /// [`Arg::number_of_values`]: crate::Arg::number_of_values() + /// [`Arg::num_args`]: crate::Arg::num_args() TooFewValues, /// Occurs when the user provides a different number of values for an argument than what's - /// been defined by setting [`Arg::number_of_values`] or than was implicitly set by + /// been defined by setting [`Arg::num_args`] or than was implicitly set by /// [`Arg::value_names`]. /// /// # Examples @@ -143,13 +143,13 @@ pub enum ErrorKind { /// .arg(Arg::new("some_opt") /// .long("opt") /// .action(ArgAction::Set) - /// .number_of_values(2)) + /// .num_args(2)) /// .try_get_matches_from(vec!["prog", "--opt", "wrong"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues); /// ``` /// - /// [`Arg::number_of_values`]: crate::Arg::number_of_values() + /// [`Arg::num_args`]: crate::Arg::num_args() /// [`Arg::value_names`]: crate::Arg::value_names() WrongNumberOfValues, diff --git a/src/macros.rs b/src/macros.rs index ca13ffa60d6..880ea74701f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -355,7 +355,7 @@ macro_rules! arg_impl { if arg.get_long().is_none() && arg.get_short().is_none() { arg = arg.required(false); } else { - arg = arg.number_of_values(0..=1); + arg = arg.num_args(0..=1); } let value_name = $crate::arg_impl! { @string $value_name }; @@ -387,7 +387,7 @@ macro_rules! arg_impl { if arg.get_long().is_none() && arg.get_short().is_none() { arg = arg.required(false); } else { - arg = arg.number_of_values(0..=1); + arg = arg.num_args(0..=1); } let value_name = $crate::arg_impl! { @string $value_name }; @@ -412,7 +412,7 @@ macro_rules! arg_impl { @arg ({ if $arg.get_long().is_none() && $arg.get_short().is_none() { - $arg.number_of_values(1..) + $arg.num_args(1..) // Allow collecting arguments interleaved with flags .action($crate::ArgAction::Append) } else if $arg.is_takes_value_set() { diff --git a/src/parser/arg_matcher.rs b/src/parser/arg_matcher.rs index 436e9914301..b463e117fb4 100644 --- a/src/parser/arg_matcher.rs +++ b/src/parser/arg_matcher.rs @@ -206,7 +206,7 @@ impl ArgMatcher { "ArgMatcher::needs_more_vals: o={}, pending={}", o.name, num_pending ); - if let Some(expected) = o.get_num_vals() { + if let Some(expected) = o.get_num_args() { debug!( "ArgMatcher::needs_more_vals: expected={}, actual={}", expected, num_pending diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index e146fab1d88..72eb49021b3 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -263,7 +263,7 @@ impl ArgMatches { /// let mut m = Command::new("myprog") /// .arg(Arg::new("file") /// .action(ArgAction::Append) - /// .number_of_values(1..) + /// .num_args(1..) /// .required(true)) /// .get_matches_from(vec![ /// "myprog", "file1.txt", "file2.txt", "file3.txt", "file4.txt", @@ -360,7 +360,7 @@ impl ArgMatches { /// let m = Command::new("myprog") /// .arg(Arg::new("exec") /// .short('x') - /// .number_of_values(1..) + /// .num_args(1..) /// .action(ArgAction::Append) /// .value_terminator(";")) /// .get_matches_from(vec![ @@ -544,7 +544,7 @@ impl ArgMatches { /// .arg(Arg::new("option") /// .short('o') /// .value_delimiter(',') - /// .number_of_values(1..)) + /// .num_args(1..)) /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// // ARGV indices: ^0 ^1 /// // clap indices: ^2 ^3 ^4 @@ -626,7 +626,7 @@ impl ArgMatches { /// .arg(Arg::new("option") /// .short('o') /// .action(ArgAction::Set) - /// .number_of_values(1..)) + /// .num_args(1..)) /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// // ARGV indices: ^0 ^1 /// // clap indices: ^2 @@ -1326,7 +1326,7 @@ impl<'a> Default for GroupedValues<'a> { /// let m = Command::new("myapp") /// .arg(Arg::new("output") /// .short('o') -/// .number_of_values(1..) +/// .num_args(1..) /// .action(ArgAction::Set)) /// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]); /// @@ -1422,7 +1422,7 @@ mod tests { .arg( crate::Arg::new("POTATO") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .required(true), ) .try_get_matches_from(["test", "one"]) @@ -1439,7 +1439,7 @@ mod tests { .arg( crate::Arg::new("POTATO") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .value_parser(crate::builder::ValueParser::os_string()) .required(true), ) @@ -1457,7 +1457,7 @@ mod tests { .arg( crate::Arg::new("POTATO") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .required(true), ) .try_get_matches_from(["test", "one"]) diff --git a/src/parser/validator.rs b/src/parser/validator.rs index 173c325e450..73a65ad9fd1 100644 --- a/src/parser/validator.rs +++ b/src/parser/validator.rs @@ -270,7 +270,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> { )); } - if let Some(expected) = a.get_num_vals() { + if let Some(expected) = a.get_num_args() { if let Some(expected) = expected.num_values() { if expected != actual { debug!( diff --git a/tests/builder/app_settings.rs b/tests/builder/app_settings.rs index 9720c29b347..bdb259c5444 100644 --- a/tests/builder/app_settings.rs +++ b/tests/builder/app_settings.rs @@ -1173,7 +1173,7 @@ fn aaos_opts_mult() { let res = Command::new("posix") .arg( arg!(--opt ... "some option") - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(vec![ diff --git a/tests/builder/default_missing_vals.rs b/tests/builder/default_missing_vals.rs index 6c441c5b8da..e0b8541cbf7 100644 --- a/tests/builder/default_missing_vals.rs +++ b/tests/builder/default_missing_vals.rs @@ -7,7 +7,7 @@ fn opt_missing() { Arg::new("color") .long("color") .default_value("auto") - .number_of_values(0..=1) + .num_args(0..=1) .require_equals(true) .default_missing_value("always"), ) @@ -33,7 +33,7 @@ fn opt_present_with_missing_value() { Arg::new("color") .long("color") .default_value("auto") - .number_of_values(0..=1) + .num_args(0..=1) .require_equals(true) .default_missing_value("always"), ) @@ -59,7 +59,7 @@ fn opt_present_with_value() { Arg::new("color") .long("color") .default_value("auto") - .number_of_values(0..=1) + .num_args(0..=1) .require_equals(true) .default_missing_value("always"), ) @@ -233,7 +233,7 @@ fn delimited_missing_value() { .long("flag") .default_value("one,two") .default_missing_value("three,four") - .number_of_values(0..) + .num_args(0..) .value_delimiter(',') .require_equals(true), ); @@ -294,7 +294,7 @@ fn valid_index() { Arg::new("color") .long("color") .default_value("auto") - .number_of_values(0..=1) + .num_args(0..=1) .require_equals(true) .default_missing_value("always"), ) diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index e49325cda04..faa8b4d9a7e 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -674,7 +674,7 @@ fn multiple_defaults() { .arg( Arg::new("files") .long("files") - .number_of_values(2) + .num_args(2) .default_values(&["old", "new"]), ) .try_get_matches_from(vec![""]); @@ -693,7 +693,7 @@ fn multiple_defaults_override() { .arg( Arg::new("files") .long("files") - .number_of_values(2) + .num_args(2) .default_values(&["old", "new"]), ) .try_get_matches_from(vec!["", "--files", "other", "mine"]); @@ -739,7 +739,7 @@ fn issue_1050_num_vals_and_defaults() { Arg::new("exit-code") .long("exit-code") .action(ArgAction::Set) - .number_of_values(1) + .num_args(1) .default_value("0"), ) .try_get_matches_from(vec!["hello", "--exit-code=1"]); diff --git a/tests/builder/delimiters.rs b/tests/builder/delimiters.rs index bc898604075..d59c190622b 100644 --- a/tests/builder/delimiters.rs +++ b/tests/builder/delimiters.rs @@ -87,7 +87,7 @@ fn opt_s_no_space_mult_no_delim() { Arg::new("option") .short('o') .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["", "-o", "val1,val2,val3"]); @@ -108,7 +108,7 @@ fn opt_eq_mult_def_delim() { Arg::new("option") .long("opt") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .value_delimiter(','), ) .try_get_matches_from(vec!["", "--opt=val1,val2,val3"]); diff --git a/tests/builder/env.rs b/tests/builder/env.rs index 94d8d61741f..99c2f6261ab 100644 --- a/tests/builder/env.rs +++ b/tests/builder/env.rs @@ -230,7 +230,7 @@ fn multiple_one() { .env("CLP_TEST_ENV_MO") .action(ArgAction::Set) .value_delimiter(',') - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec![""]); @@ -256,7 +256,7 @@ fn multiple_three() { .env("CLP_TEST_ENV_MULTI1") .action(ArgAction::Set) .value_delimiter(',') - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec![""]); @@ -281,7 +281,7 @@ fn multiple_no_delimiter() { arg!([arg] "some opt") .env("CLP_TEST_ENV_MULTI2") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec![""]); diff --git a/tests/builder/flag_subcommands.rs b/tests/builder/flag_subcommands.rs index 04fbe56e727..0abbabf5f11 100644 --- a/tests/builder/flag_subcommands.rs +++ b/tests/builder/flag_subcommands.rs @@ -526,7 +526,7 @@ fn flag_subcommand_long_short_normal_usage_string() { .help("search locally installed packages for matching strings") .conflicts_with("info") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .arg( Arg::new("info") @@ -535,7 +535,7 @@ fn flag_subcommand_long_short_normal_usage_string() { .conflicts_with("search") .help("view package information") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ), ); utils::assert_output(cmd, "pacman -Qh", FLAG_SUBCOMMAND_HELP, false); @@ -574,7 +574,7 @@ fn flag_subcommand_long_normal_usage_string() { .help("search locally installed packages for matching strings") .conflicts_with("info") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .arg( Arg::new("info") @@ -583,7 +583,7 @@ fn flag_subcommand_long_normal_usage_string() { .conflicts_with("search") .help("view package information") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ), ); utils::assert_output( @@ -627,7 +627,7 @@ fn flag_subcommand_short_normal_usage_string() { .help("search locally installed packages for matching strings") .conflicts_with("info") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .arg( Arg::new("info") @@ -636,7 +636,7 @@ fn flag_subcommand_short_normal_usage_string() { .conflicts_with("search") .help("view package information") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ), ); utils::assert_output( diff --git a/tests/builder/grouped_values.rs b/tests/builder/grouped_values.rs index d6e8a7c9736..a5336130be5 100644 --- a/tests/builder/grouped_values.rs +++ b/tests/builder/grouped_values.rs @@ -9,7 +9,7 @@ fn grouped_value_works() { Arg::new("option") .long("option") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(&[ @@ -41,7 +41,7 @@ fn issue_1026() { Arg::new("target") .long("target") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(&[ @@ -69,7 +69,7 @@ fn grouped_value_long_flag_delimiter() { .long("option") .action(ArgAction::Set) .value_delimiter(',') - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(vec![ @@ -99,7 +99,7 @@ fn grouped_value_short_flag_delimiter() { .short('o') .action(ArgAction::Set) .value_delimiter(',') - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(vec!["myapp", "-o=foo", "-o=val1,val2,val3", "-o=bar"]) @@ -118,7 +118,7 @@ fn grouped_value_positional_arg() { Arg::new("pos") .help("multiple positionals") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec![ "myprog", "val1", "val2", "val3", "val4", "val5", "val6", @@ -139,7 +139,7 @@ fn grouped_value_multiple_positional_arg() { Arg::new("pos2") .help("multiple positionals") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec![ "myprog", "val1", "val2", "val3", "val4", "val5", "val6", @@ -160,7 +160,7 @@ fn grouped_value_multiple_positional_arg_last_multiple() { Arg::new("pos2") .help("multiple positionals") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .last(true), ) .try_get_matches_from(vec![ @@ -177,7 +177,7 @@ fn grouped_value_multiple_positional_arg_last_multiple() { #[test] fn grouped_interleaved_positional_values() { let cmd = clap::Command::new("foo") - .arg(clap::Arg::new("pos").number_of_values(1..)) + .arg(clap::Arg::new("pos").num_args(1..)) .arg( clap::Arg::new("flag") .short('f') @@ -200,7 +200,7 @@ fn grouped_interleaved_positional_values() { #[test] fn grouped_interleaved_positional_occurrences() { let cmd = clap::Command::new("foo") - .arg(clap::Arg::new("pos").number_of_values(1..)) + .arg(clap::Arg::new("pos").num_args(1..)) .arg( clap::Arg::new("flag") .short('f') diff --git a/tests/builder/groups.rs b/tests/builder/groups.rs index 5b193c9c609..4fe603a1acd 100644 --- a/tests/builder/groups.rs +++ b/tests/builder/groups.rs @@ -133,7 +133,7 @@ fn group_required_flags_empty() { #[test] fn group_multi_value_single_arg() { let res = Command::new("group") - .arg(arg!(-c --color "some option").number_of_values(1..)) + .arg(arg!(-c --color "some option").num_args(1..)) .arg(arg!(-h --hostname "another option").required(false)) .group(ArgGroup::new("grp").args(&["hostname", "color"])) .try_get_matches_from(vec!["", "-c", "blue", "red", "green"]); diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 11fdc02f98d..3b95da2a887 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -67,7 +67,7 @@ fn help_multi_subcommand_error() { -o --option "tests options" ) .required(false) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ), ), @@ -104,16 +104,11 @@ OPTIONS: let cmd = Command::new("example") .version("1.0") - .arg( - Arg::new("FIRST") - .help("First") - .number_of_values(1..) - .required(true), - ) + .arg(Arg::new("FIRST").help("First").num_args(1..).required(true)) .arg( Arg::new("SECOND") .help("Second") - .number_of_values(1..) + .num_args(1..) .required(true) .last(true), ); @@ -172,7 +167,7 @@ OPTIONS: Arg::new("pass through args") .help("Any arguments you wish to pass to the being profiled.") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .last(true) .value_name("ARGS"), ); @@ -342,7 +337,7 @@ fn multi_level_sc_help() { -o --option "tests options" ) .required(false) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ), ), @@ -981,7 +976,7 @@ OPTIONS: .arg( Arg::new("arg2") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .help("some option"), ) .arg( @@ -1003,7 +998,7 @@ OPTIONS: .help("a label") .short('l') .long("label") - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Set), ); utils::assert_output(cmd, "myapp --help", ISSUE_702, false); @@ -1342,7 +1337,7 @@ OPTIONS: .arg( Arg::new("ARGS") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .last(true) .help("some"), ); @@ -1373,7 +1368,7 @@ OPTIONS: .arg( Arg::new("ARGS") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .last(true) .required(true) .help("some"), @@ -1411,7 +1406,7 @@ SUBCOMMANDS: .arg( Arg::new("ARGS") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .last(true) .required(true) .help("some"), @@ -1450,7 +1445,7 @@ SUBCOMMANDS: .arg( Arg::new("ARGS") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .last(true) .help("some"), ) @@ -1865,7 +1860,7 @@ OPTIONS: Arg::new("files") .value_name("FILES") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ); utils::assert_output(cmd, "demo -h", ISSUE_1364, false); @@ -2339,11 +2334,11 @@ fn only_custom_heading_pos_no_args() { #[test] fn issue_2508_number_of_values_with_single_value_name() { let cmd = Command::new("my_app") - .arg(Arg::new("some_arg").long("some_arg").number_of_values(2)) + .arg(Arg::new("some_arg").long("some_arg").num_args(2)) .arg( Arg::new("some_arg_issue") .long("some_arg_issue") - .number_of_values(2) + .num_args(2) .value_name("ARG"), ); utils::assert_output( @@ -2394,7 +2389,7 @@ fn missing_positional_final_multiple() { .allow_missing_positional(true) .arg(Arg::new("foo")) .arg(Arg::new("bar")) - .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..)); + .arg(Arg::new("baz").action(ArgAction::Set).num_args(1..)); utils::assert_output( cmd, "test --help", @@ -2421,7 +2416,7 @@ fn positional_multiple_values_is_dotted() { Arg::new("foo") .required(true) .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ); utils::assert_output( cmd, @@ -2445,7 +2440,7 @@ OPTIONS: .required(true) .action(ArgAction::Set) .value_name("BAR") - .number_of_values(1..), + .num_args(1..), ); utils::assert_output( cmd, @@ -2471,7 +2466,7 @@ fn positional_multiple_occurrences_is_dotted() { Arg::new("foo") .required(true) .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ); utils::assert_output( @@ -2496,7 +2491,7 @@ OPTIONS: .required(true) .action(ArgAction::Set) .value_name("BAR") - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ); utils::assert_output( @@ -2524,7 +2519,7 @@ fn too_few_value_names_is_dotted() { .long("foo") .required(true) .action(ArgAction::Set) - .number_of_values(3) + .num_args(3) .value_names(&["one", "two"]), ); utils::assert_output( @@ -2552,7 +2547,7 @@ fn too_many_value_names_panics() { .long("foo") .required(true) .action(ArgAction::Set) - .number_of_values(1) + .num_args(1) .value_names(&["one", "two"]), ) .debug_assert() diff --git a/tests/builder/indices.rs b/tests/builder/indices.rs index 0e6ad9bab52..5f6d40deb79 100644 --- a/tests/builder/indices.rs +++ b/tests/builder/indices.rs @@ -7,14 +7,14 @@ fn indices_mult_opts() { Arg::new("exclude") .short('e') .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .arg( Arg::new("include") .short('i') .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]) .unwrap(); @@ -36,14 +36,14 @@ fn index_mult_opts() { Arg::new("exclude") .short('e') .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .arg( Arg::new("include") .short('i') .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]) .unwrap(); @@ -136,7 +136,7 @@ fn indices_mult_opt_value_delim_eq() { .short('o') .action(ArgAction::Set) .value_delimiter(',') - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"]) .unwrap(); @@ -153,7 +153,7 @@ fn indices_mult_opt_value_no_delim_eq() { Arg::new("option") .short('o') .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"]) .unwrap(); diff --git a/tests/builder/multiple_occurrences.rs b/tests/builder/multiple_occurrences.rs index 9c3d939d801..0719b95ecdf 100644 --- a/tests/builder/multiple_occurrences.rs +++ b/tests/builder/multiple_occurrences.rs @@ -28,11 +28,7 @@ fn multiple_occurrences_of_flags_short() { #[test] fn multiple_occurrences_of_positional() { - let cmd = Command::new("test").arg( - Arg::new("multi") - .number_of_values(1..) - .action(ArgAction::Append), - ); + let cmd = Command::new("test").arg(Arg::new("multi").num_args(1..).action(ArgAction::Append)); let m = cmd .clone() diff --git a/tests/builder/multiple_values.rs b/tests/builder/multiple_values.rs index 74072b59433..a8333fd6aaa 100644 --- a/tests/builder/multiple_values.rs +++ b/tests/builder/multiple_values.rs @@ -8,7 +8,7 @@ fn option_long() { .long("option") .help("multiple options") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(vec![ @@ -36,7 +36,7 @@ fn option_short() { .short('o') .help("multiple options") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]); @@ -63,7 +63,7 @@ fn option_mixed() { .short('o') .help("multiple options") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .try_get_matches_from(vec![ @@ -90,7 +90,7 @@ fn option_exact_exact() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3) + .num_args(3) .action(ArgAction::Append), ) .try_get_matches_from(vec![ @@ -117,7 +117,7 @@ fn option_exact_exact_not_mult() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3), + .num_args(3), ) .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]); @@ -141,7 +141,7 @@ fn option_exact_exact_mult() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3) + .num_args(3) .action(ArgAction::Append), ) .try_get_matches_from(vec![ @@ -168,7 +168,7 @@ fn option_exact_less() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3) + .num_args(3) .action(ArgAction::Append), ) .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]); @@ -184,7 +184,7 @@ fn option_exact_more() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3) + .num_args(3) .action(ArgAction::Append), ) .try_get_matches_from(vec![ @@ -202,7 +202,7 @@ fn option_min_exact() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3..) + .num_args(3..) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]); @@ -227,7 +227,7 @@ fn option_min_less() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3..) + .num_args(3..) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "-o", "val1", "val2"]); @@ -244,7 +244,7 @@ fn option_short_min_more_mult_occurs() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3..) + .num_args(3..) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "pos", "-o", "val1", "val2", "val3", "val4"]); @@ -272,7 +272,7 @@ fn option_short_min_more_single_occur() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(3..), + .num_args(3..), ) .try_get_matches_from(vec!["", "pos", "-o", "val1", "val2", "val3", "val4"]); @@ -298,7 +298,7 @@ fn option_max_exact() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(1..=3) + .num_args(1..=3) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]); @@ -323,7 +323,7 @@ fn option_max_less() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(1..=3) + .num_args(1..=3) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "-o", "val1", "val2"]); @@ -348,7 +348,7 @@ fn option_max_zero() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(1..=3) + .num_args(1..=3) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "-o"]); @@ -364,7 +364,7 @@ fn option_max_zero_eq() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(1..=3) + .num_args(1..=3) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "-o="]); @@ -389,7 +389,7 @@ fn option_max_more() { Arg::new("option") .short('o') .help("multiple options") - .number_of_values(1..=3) + .num_args(1..=3) .action(ArgAction::Set), ) .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3", "val4"]); @@ -405,7 +405,7 @@ fn optional_value() { Arg::new("port") .short('p') .value_name("NUM") - .number_of_values(0..=1), + .num_args(0..=1), ); let r = cmd.try_get_matches_from_mut(["test", "-p42"]); @@ -448,7 +448,7 @@ fn positional() { Arg::new("pos") .help("multiple positionals") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]); @@ -468,11 +468,7 @@ fn positional() { #[test] fn positional_exact_exact() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(3), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(3)) .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]); assert!(m.is_ok(), "{}", m.unwrap_err()); @@ -491,11 +487,7 @@ fn positional_exact_exact() { #[test] fn positional_exact_less() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(3), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(3)) .try_get_matches_from(vec!["myprog", "val1", "val2"]); assert!(m.is_err()); @@ -505,11 +497,7 @@ fn positional_exact_less() { #[test] fn positional_exact_more() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(3), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(3)) .try_get_matches_from(vec!["myprog", "val1", "val2", "val3", "val4"]); assert!(m.is_err()); @@ -519,11 +507,7 @@ fn positional_exact_more() { #[test] fn positional_min_exact() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(3..), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(3..)) .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]); assert!(m.is_ok(), "{}", m.unwrap_err()); @@ -542,11 +526,7 @@ fn positional_min_exact() { #[test] fn positional_min_less() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(3..), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(3..)) .try_get_matches_from(vec!["myprog", "val1", "val2"]); assert!(m.is_err()); @@ -556,11 +536,7 @@ fn positional_min_less() { #[test] fn positional_min_more() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(3..), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(3..)) .try_get_matches_from(vec!["myprog", "val1", "val2", "val3", "val4"]); assert!(m.is_ok(), "{}", m.unwrap_err()); @@ -579,11 +555,7 @@ fn positional_min_more() { #[test] fn positional_max_exact() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(1..=3), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(1..=3)) .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]); assert!(m.is_ok(), "{}", m.unwrap_err()); @@ -602,11 +574,7 @@ fn positional_max_exact() { #[test] fn positional_max_less() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(1..=3), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(1..=3)) .try_get_matches_from(vec!["myprog", "val1", "val2"]); assert!(m.is_ok(), "{}", m.unwrap_err()); @@ -625,11 +593,7 @@ fn positional_max_less() { #[test] fn positional_max_more() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(1..=3), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(1..=3)) .try_get_matches_from(vec!["myprog", "val1", "val2", "val3", "val4"]); assert!(m.is_err()); @@ -873,14 +837,14 @@ fn req_delimiter_long() { .arg( Arg::new("option") .long("option") - .number_of_values(1..) + .num_args(1..) .value_delimiter(',') .require_value_delimiter(true), ) .arg( Arg::new("args") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .index(1), ) .try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]); @@ -911,14 +875,14 @@ fn req_delimiter_long_with_equal() { .arg( Arg::new("option") .long("option") - .number_of_values(1..) + .num_args(1..) .value_delimiter(',') .require_value_delimiter(true), ) .arg( Arg::new("args") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .index(1), ) .try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]); @@ -949,14 +913,14 @@ fn req_delimiter_short_with_space() { .arg( Arg::new("option") .short('o') - .number_of_values(1..) + .num_args(1..) .value_delimiter(',') .require_value_delimiter(true), ) .arg( Arg::new("args") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .index(1), ) .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]); @@ -987,14 +951,14 @@ fn req_delimiter_short_with_no_space() { .arg( Arg::new("option") .short('o') - .number_of_values(1..) + .num_args(1..) .value_delimiter(',') .require_value_delimiter(true), ) .arg( Arg::new("args") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .index(1), ) .try_get_matches_from(vec!["", "-oval1", "val2", "val3"]); @@ -1025,14 +989,14 @@ fn req_delimiter_short_with_equal() { .arg( Arg::new("option") .short('o') - .number_of_values(1..) + .num_args(1..) .value_delimiter(',') .require_value_delimiter(true), ) .arg( Arg::new("args") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .index(1), ) .try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]); @@ -1064,12 +1028,12 @@ fn req_delimiter_complex() { Arg::new("option") .long("option") .short('o') - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append) .value_delimiter(',') .require_value_delimiter(true), ) - .arg(Arg::new("args").number_of_values(1..).index(1)) + .arg(Arg::new("args").num_args(1..).index(1)) .try_get_matches_from(vec![ "", "val1", @@ -1129,7 +1093,7 @@ fn req_delimiter_complex() { #[cfg(debug_assertions)] #[test] #[should_panic = "When using a positional argument with \ -.number_of_values(1..) that is *not the last* positional argument, the last \ +.num_args(1..) that is *not the last* positional argument, the last \ positional argument (i.e. the one with the highest index) *must* have \ .required(true) or .last(true) set."] fn low_index_positional_not_required() { @@ -1139,7 +1103,7 @@ fn low_index_positional_not_required() { .index(1) .action(ArgAction::Set) .required(true) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("target").index(2)) .try_get_matches_from(vec![""]); @@ -1148,7 +1112,7 @@ fn low_index_positional_not_required() { // This tests a programmer error and will only succeed with debug_assertions #[cfg(debug_assertions)] #[test] -#[should_panic = "Only one positional argument with .number_of_values(1..) \ +#[should_panic = "Only one positional argument with .num_args(1..) \ set is allowed per command, unless the second one also has .last(true) set"] fn low_index_positional_last_multiple_too() { let _ = Command::new("lip") @@ -1157,14 +1121,14 @@ fn low_index_positional_last_multiple_too() { .index(1) .action(ArgAction::Set) .required(true) - .number_of_values(1..), + .num_args(1..), ) .arg( Arg::new("target") .index(2) .action(ArgAction::Set) .required(true) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec![""]); } @@ -1173,7 +1137,7 @@ fn low_index_positional_last_multiple_too() { #[cfg(debug_assertions)] #[test] #[should_panic = "Only the last positional argument, or second to \ -last positional argument may be set to .number_of_values(1..)"] +last positional argument may be set to .num_args(1..)"] fn low_index_positional_too_far_back() { let _ = Command::new("lip") .arg( @@ -1181,7 +1145,7 @@ fn low_index_positional_too_far_back() { .index(1) .action(ArgAction::Set) .required(true) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("target").required(true).index(2)) .arg(Arg::new("target2").required(true).index(3)) @@ -1196,7 +1160,7 @@ fn low_index_positional() { .index(1) .action(ArgAction::Set) .required(true) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("target").index(2).required(true)) .try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target"]); @@ -1229,7 +1193,7 @@ fn low_index_positional_in_subcmd() { .index(1) .action(ArgAction::Set) .required(true) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("target").index(2).required(true)), ) @@ -1262,7 +1226,7 @@ fn low_index_positional_with_option() { .required(true) .index(1) .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("target").index(2).required(true)) .arg(Arg::new("opt").long("option").action(ArgAction::Set)) @@ -1300,7 +1264,7 @@ fn low_index_positional_with_flag() { .index(1) .action(ArgAction::Set) .required(true) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("target").index(2).required(true)) .arg(Arg::new("flg").long("flag").action(ArgAction::SetTrue)) @@ -1331,7 +1295,7 @@ fn low_index_positional_with_extra_flags() { .arg(Arg::new("yes").long("yes").action(ArgAction::SetTrue)) .arg(Arg::new("one").long("one").action(ArgAction::Set)) .arg(Arg::new("two").long("two").action(ArgAction::Set)) - .arg(Arg::new("input").number_of_values(1..).required(true)) + .arg(Arg::new("input").num_args(1..).required(true)) .arg(Arg::new("output").required(true)); let m = cmd.try_get_matches_from([ "test", "--one", "1", "--two", "2", "3", "4", "5", "6", "7", "8", @@ -1368,7 +1332,7 @@ fn multiple_value_terminator_option() { .short('f') .value_terminator(";") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("other")) .try_get_matches_from(vec!["lip", "-f", "val1", "val2", ";", "otherval"]); @@ -1399,7 +1363,7 @@ fn multiple_value_terminator_option_other_arg() { .short('f') .value_terminator(";") .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ) .arg(Arg::new("other")) .arg(Arg::new("flag").short('F').action(ArgAction::SetTrue)) @@ -1430,7 +1394,7 @@ fn multiple_vals_with_hyphen() { .arg( Arg::new("cmds") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .allow_hyphen_values(true) .value_terminator(";"), ) @@ -1463,7 +1427,7 @@ fn multiple_vals_with_hyphen() { #[test] fn issue_1480_max_values_consumes_extra_arg_1() { let res = Command::new("prog") - .arg(Arg::new("field").number_of_values(..=1).long("field")) + .arg(Arg::new("field").num_args(..=1).long("field")) .arg(Arg::new("positional").required(true).index(1)) .try_get_matches_from(vec!["prog", "--field", "1", "file"]); @@ -1473,7 +1437,7 @@ fn issue_1480_max_values_consumes_extra_arg_1() { #[test] fn issue_1480_max_values_consumes_extra_arg_2() { let res = Command::new("prog") - .arg(Arg::new("field").number_of_values(..=1).long("field")) + .arg(Arg::new("field").num_args(..=1).long("field")) .try_get_matches_from(vec!["prog", "--field", "1", "2"]); assert!(res.is_err()); @@ -1483,7 +1447,7 @@ fn issue_1480_max_values_consumes_extra_arg_2() { #[test] fn issue_1480_max_values_consumes_extra_arg_3() { let res = Command::new("prog") - .arg(Arg::new("field").number_of_values(..=1).long("field")) + .arg(Arg::new("field").num_args(..=1).long("field")) .try_get_matches_from(vec!["prog", "--field", "1", "2", "3"]); assert!(res.is_err()); @@ -1531,12 +1495,12 @@ fn value_names_building_num_vals_for_positional() { } #[test] -fn number_of_values_preferred_over_value_names() { +fn num_args_preferred_over_value_names() { let m = Command::new("test") .arg( Arg::new("pos") .long("pos") - .number_of_values(4) + .num_args(4) .value_names(&["who", "what", "why"]), ) .try_get_matches_from(vec!["myprog", "--pos", "val1", "val2", "val3", "val4"]); @@ -1558,7 +1522,7 @@ fn values_per_occurrence_named() { let mut a = Command::new("test").arg( Arg::new("pos") .long("pos") - .number_of_values(2) + .num_args(2) .action(ArgAction::Append), ); @@ -1591,11 +1555,7 @@ fn values_per_occurrence_named() { #[test] fn values_per_occurrence_positional() { - let mut a = Command::new("test").arg( - Arg::new("pos") - .number_of_values(2) - .action(ArgAction::Append), - ); + let mut a = Command::new("test").arg(Arg::new("pos").num_args(2).action(ArgAction::Append)); let m = a.try_get_matches_from_mut(vec!["myprog", "val1", "val2"]); assert!(m.is_ok(), "{}", m.unwrap_err()); @@ -1612,11 +1572,7 @@ fn values_per_occurrence_positional() { #[test] fn issue_2229() { let m = Command::new("multiple_values") - .arg( - Arg::new("pos") - .help("multiple positionals") - .number_of_values(3), - ) + .arg(Arg::new("pos").help("multiple positionals").num_args(3)) .try_get_matches_from(vec![ "myprog", "val1", "val2", "val3", "val4", "val5", "val6", ]); diff --git a/tests/builder/opts.rs b/tests/builder/opts.rs index 4d93d7e67dc..72cd3ebea97 100644 --- a/tests/builder/opts.rs +++ b/tests/builder/opts.rs @@ -71,7 +71,7 @@ fn require_equals_min_values_zero() { Arg::new("cfg") .action(ArgAction::Set) .require_equals(true) - .number_of_values(0..) + .num_args(0..) .long("config"), ) .arg(Arg::new("cmd")) @@ -177,7 +177,7 @@ fn opts_using_short() { #[test] fn lots_o_vals() { let r = Command::new("opts") - .arg(arg!(o: -o "some opt").number_of_values(1..)) + .arg(arg!(o: -o "some opt").num_args(1..)) .try_get_matches_from(vec![ "", "-o", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", @@ -338,7 +338,7 @@ fn multiple_vals_pos_arg_delim() { let r = Command::new("mvae") .arg( arg!(o: -o "some opt") - .number_of_values(1..) + .num_args(1..) .value_delimiter(','), ) .arg(arg!([file] "some file")) @@ -380,7 +380,7 @@ fn require_delims() { let r = Command::new("mvae") .arg( arg!(o: -o "some opt") - .number_of_values(1..) + .num_args(1..) .value_delimiter(',') .require_value_delimiter(true), ) @@ -408,7 +408,7 @@ fn leading_hyphen_pass() { let r = Command::new("mvae") .arg( arg!(o: -o "some opt") - .number_of_values(1..) + .num_args(1..) .allow_hyphen_values(true), ) .try_get_matches_from(vec!["", "-o", "-2", "3"]); @@ -439,7 +439,7 @@ fn leading_hyphen_with_flag_after() { let r = Command::new("mvae") .arg( arg!(o: -o "some opt") - .number_of_values(1..) + .num_args(1..) .allow_hyphen_values(true), ) .arg(arg!(f: -f "some flag").action(ArgAction::SetTrue)) @@ -514,7 +514,7 @@ fn issue_1047_min_zero_vals_default_val() { .long("del") .action(ArgAction::Set) .require_equals(true) - .number_of_values(0..) + .num_args(0..) .default_missing_value("default"), ) .try_get_matches_from(vec!["foo", "-d"]) diff --git a/tests/builder/positionals.rs b/tests/builder/positionals.rs index 41e24d15ed7..253e39d2190 100644 --- a/tests/builder/positionals.rs +++ b/tests/builder/positionals.rs @@ -121,7 +121,7 @@ fn positional_multiple() { Arg::new("positional") .index(1) .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ]) .try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]); assert!(r.is_ok(), "{:#?}", r); @@ -145,7 +145,7 @@ fn positional_multiple_3() { Arg::new("positional") .index(1) .action(ArgAction::Set) - .number_of_values(1..), + .num_args(1..), ]) .try_get_matches_from(vec!["", "test1", "test2", "test3", "--flag"]); assert!(r.is_ok(), "{:#?}", r); @@ -330,7 +330,7 @@ fn ignore_hyphen_values_on_last() { let cmd = clap::Command::new("foo") .arg( clap::Arg::new("cmd") - .number_of_values(1..) + .num_args(1..) .last(true) .allow_hyphen_values(true), ) diff --git a/tests/builder/possible_values.rs b/tests/builder/possible_values.rs index a0e17a7ce0d..29aeb1bb1b0 100644 --- a/tests/builder/possible_values.rs +++ b/tests/builder/possible_values.rs @@ -90,7 +90,7 @@ fn possible_values_of_positional_multiple() { .index(1) .action(ArgAction::Set) .value_parser(["test123", "test321"]) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["myprog", "test123", "test321"]); @@ -115,7 +115,7 @@ fn possible_values_of_positional_multiple_fail() { .index(1) .action(ArgAction::Set) .value_parser(["test123", "test321"]) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["myprog", "test123", "notest"]); @@ -394,7 +394,7 @@ fn ignore_case_multiple() { .long("option") .action(ArgAction::Set) .value_parser(["test123", "test321"]) - .number_of_values(1..) + .num_args(1..) .ignore_case(true), ) .try_get_matches_from(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]); @@ -419,7 +419,7 @@ fn ignore_case_multiple_fail() { .long("option") .action(ArgAction::Set) .value_parser(["test123", "test321"]) - .number_of_values(1..), + .num_args(1..), ) .try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]); diff --git a/tests/builder/require.rs b/tests/builder/require.rs index f103650e39e..db182b455bb 100644 --- a/tests/builder/require.rs +++ b/tests/builder/require.rs @@ -344,7 +344,7 @@ fn required_unless_present_err() { #[test] fn required_unless_present_with_optional_value() { let res = Command::new("unlesstest") - .arg(Arg::new("opt").long("opt").number_of_values(0..=1)) + .arg(Arg::new("opt").long("opt").num_args(0..=1)) .arg( Arg::new("cfg") .required_unless_present("dbg") @@ -1144,7 +1144,7 @@ fn short_flag_require_equals_with_minvals_zero() { .arg( Arg::new("check") .short('c') - .number_of_values(0..) + .num_args(0..) .require_equals(true), ) .arg(Arg::new("unique").short('u').action(ArgAction::SetTrue)) @@ -1162,7 +1162,7 @@ fn issue_2624() { .short('c') .long("check") .require_equals(true) - .number_of_values(0..) + .num_args(0..) .value_parser(["silent", "quiet", "diagnose-first"]), ) .arg( diff --git a/tests/builder/subcommands.rs b/tests/builder/subcommands.rs index cb7d7bb873f..57f133147f4 100644 --- a/tests/builder/subcommands.rs +++ b/tests/builder/subcommands.rs @@ -304,7 +304,7 @@ fn issue_1161_multiple_hyphen_hyphen() { .arg( Arg::new("slop") .action(ArgAction::Set) - .number_of_values(1..) + .num_args(1..) .last(true), ) .try_get_matches_from(vec![ diff --git a/tests/builder/utils.rs b/tests/builder/utils.rs index 9cf31c1a304..8b6383fe95f 100644 --- a/tests/builder/utils.rs +++ b/tests/builder/utils.rs @@ -49,7 +49,7 @@ pub fn complex_app() -> Command<'static> { -o --option "tests options" ) .required(false) - .number_of_values(1..) + .num_args(1..) .action(ArgAction::Append), ) .arg(arg!([positional] "tests positionals")) @@ -80,17 +80,17 @@ pub fn complex_app() -> Command<'static> { .required(false), arg!(--minvals2 "Tests 2 min vals") .required(false) - .number_of_values(2..), + .num_args(2..), arg!(--maxvals3 "Tests 3 max vals") .required(false) - .number_of_values(1..=3), + .num_args(1..=3), arg!(--optvaleq "Tests optional value, require = sign") .required(false) - .number_of_values(0..=1) + .num_args(0..=1) .require_equals(true), arg!(--optvalnoeq "Tests optional value") .required(false) - .number_of_values(0..=1), + .num_args(0..=1), ]) .subcommand( Command::new("subcmd") @@ -100,7 +100,7 @@ pub fn complex_app() -> Command<'static> { .arg( arg!(-o --option "tests options") .required(false) - .number_of_values(1..), + .num_args(1..), ) .arg(arg!(-s --subcmdarg "tests other args").required(false)) .arg(arg!([scpositional] "tests positionals")), diff --git a/tests/derive/options.rs b/tests/derive/options.rs index d41dab2dc33..82e8a934470 100644 --- a/tests/derive/options.rs +++ b/tests/derive/options.rs @@ -369,7 +369,7 @@ fn vec_type_with_required() { fn vec_type_with_multiple_values_only() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, long, number_of_values(1..))] + #[clap(short, long, num_args(1..))] arg: Vec, } assert_eq!( @@ -429,7 +429,7 @@ fn option_vec_type() { fn option_vec_type_structopt_behavior() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, long, number_of_values(0..))] + #[clap(short, long, num_args(0..))] arg: Option>, } assert_eq!( From 6dddf119ceef74c868d2530b983cd558361eb913 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 3 Aug 2022 14:42:12 -0500 Subject: [PATCH 2/5] fix!: `num_args` controls user args rather than parsed values This mostly impacts use of delimiters. --- CHANGELOG.md | 2 +- src/builder/arg.rs | 6 +- src/parser/arg_matcher.rs | 4 -- src/parser/matches/matched_arg.rs | 1 + src/parser/mod.rs | 1 + src/parser/parser.rs | 74 ++++++++++++++++++++++-- src/parser/validator.rs | 95 ++----------------------------- 7 files changed, 78 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f61f2dab6..1dc207f0f69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `arg!` now sets `ArgAction::SetTrue`, `ArgAction::Count`, `ArgAction::Set`, or `ArgAction::Append` as appropriate (#3795) - Default actions are now `Set` and `SetTrue` - Removed `PartialEq` and `Eq` from `Command` -- Replace `Arg::number_of_values` (average across occurrences) with `Arg::num_args` (per occurrence) +- Replace `Arg::number_of_values` (average across occurrences) with `Arg::num_args` (per occurrence, raw CLI args, not parsed values) - `num_args(0)` no longer implies `takes_value(true).multiple_values(true)` - `num_args(1)` no longer implies `multiple_values(true)` - Replace `Arg::min_values` (across all occurrences) with `Arg::num_args(N..)` (per occurrence) diff --git a/src/builder/arg.rs b/src/builder/arg.rs index 70557e3bd4d..5de6d097fa0 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -908,13 +908,13 @@ impl<'help> Arg<'help> { } } - /// Specifies the number of values allowed per occurrence of this argument + /// Specifies the number of arguments parsed per occurrence /// /// For example, if you had a `-f ` argument where you wanted exactly 3 'files' you would /// set `.num_args(3)`, and this argument wouldn't be satisfied unless the user /// provided 3 and only 3 values. /// - /// **NOTE:** Users may specify values for arguments in any of the following methods + /// Users may specify values for arguments in any of the following methods /// /// - Using a space such as `-o value` or `--option value` /// - Using an equals and no space such as `-o=value` or `--option=value` @@ -934,7 +934,7 @@ impl<'help> Arg<'help> { /// - It reaches the [`Arg::value_terminator`] if set /// /// Alternatively, - /// - Require a delimiter between values with [Arg::require_value_delimiter] + /// - Use a delimiter between values with [Arg::value_delimiter] /// - Require a flag occurrence per value with [`ArgAction::Append`] /// - Require positional arguments to appear after `--` with [`Arg::last`] /// diff --git a/src/parser/arg_matcher.rs b/src/parser/arg_matcher.rs index b463e117fb4..373e455f4cd 100644 --- a/src/parser/arg_matcher.rs +++ b/src/parser/arg_matcher.rs @@ -122,10 +122,6 @@ impl ArgMatcher { self.matches.subcommand_name() } - pub(crate) fn iter(&self) -> indexmap::map::Iter { - self.matches.args.iter() - } - pub(crate) fn check_explicit<'a>(&self, arg: &Id, predicate: ArgPredicate<'a>) -> bool { self.get(arg).map_or(false, |a| a.check_explicit(predicate)) } diff --git a/src/parser/matches/matched_arg.rs b/src/parser/matches/matched_arg.rs index c8fb80a565f..74bac9907bd 100644 --- a/src/parser/matches/matched_arg.rs +++ b/src/parser/matches/matched_arg.rs @@ -75,6 +75,7 @@ impl MatchedArg { self.indices.push(index) } + #[cfg(feature = "unstable-grouped")] pub(crate) fn vals(&self) -> Iter> { self.vals.iter() } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 883b1ada835..4e8a256c682 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -16,6 +16,7 @@ pub(crate) use self::matches::{MatchedArg, SubCommand}; pub(crate) use self::parser::Identifier; pub(crate) use self::parser::PendingArg; pub(crate) use self::parser::{ParseState, Parser}; +pub(crate) use self::validator::get_possible_values_cli; pub(crate) use self::validator::Validator; pub use self::matches::RawValues; diff --git a/src/parser/parser.rs b/src/parser/parser.rs index d23e91a6ec1..e8fd3328f1f 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -8,6 +8,7 @@ use std::{ use clap_lex::RawOsStr; // Internal +use crate::builder::PossibleValue; use crate::builder::{Arg, Command}; use crate::error::Error as ClapError; use crate::error::Result as ClapResult; @@ -1120,6 +1121,12 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { ) -> ClapResult { self.resolve_pending(matcher)?; + debug!( + "Parser::react action={:?}, identifier={:?}, source={:?}", + arg.get_action(), + ident, + source + ); if raw_vals.is_empty() { // We assume this case is valid: require equals, but min_vals == 0. if !arg.default_missing_vals.is_empty() { @@ -1141,12 +1148,8 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { }; } - debug!( - "Parser::react action={:?}, identifier={:?}, source={:?}", - arg.get_action(), - ident, - source - ); + self.verify_num_args(arg, &raw_vals)?; + match arg.get_action() { ArgAction::Set => { if source == ValueSource::CommandLine @@ -1248,6 +1251,65 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { } } + fn verify_num_args(&self, arg: &Arg<'help>, raw_vals: &[OsString]) -> ClapResult<()> { + if self.cmd.is_ignore_errors_set() { + return Ok(()); + } + + let actual = raw_vals.len(); + + let min_vals = arg.get_min_vals().unwrap_or(1); + if arg.is_takes_value_set() && 0 < min_vals && 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( + self.cmd, + &super::get_possible_values_cli(arg) + .iter() + .filter(|pv| !pv.is_hide_set()) + .map(PossibleValue::get_name) + .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( + 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(()) + } + fn remove_overrides(&self, arg: &Arg<'help>, matcher: &mut ArgMatcher) { debug!("Parser::remove_overrides: id={:?}", arg.id); for override_id in &arg.overrides { diff --git a/src/parser/validator.rs b/src/parser/validator.rs index 73a65ad9fd1..ae91f9729de 100644 --- a/src/parser/validator.rs +++ b/src/parser/validator.rs @@ -3,10 +3,10 @@ use crate::builder::{Arg, ArgPredicate, Command, PossibleValue}; use crate::error::{Error, Result as ClapResult}; use crate::output::fmt::Stream; use crate::output::Usage; -use crate::parser::{ArgMatcher, MatchedArg, ParseState}; +use crate::parser::{ArgMatcher, ParseState}; use crate::util::ChildGraph; use crate::util::Id; -use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8}; +use crate::INTERNAL_ERROR_MSG; pub(crate) struct Validator<'help, 'cmd> { cmd: &'cmd Command<'help>, @@ -40,7 +40,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> { if should_err { return Err(Error::empty_value( self.cmd, - &get_possible_values(o) + &get_possible_values_cli(o) .iter() .filter(|pv| !pv.is_hide_set()) .map(PossibleValue::get_name) @@ -78,7 +78,6 @@ impl<'help, 'cmd> Validator<'help, 'cmd> { if !(self.cmd.is_subcommand_negates_reqs_set() && has_subcmd) { self.validate_required(matcher, &mut conflicts)?; } - self.validate_matched_args(matcher)?; Ok(()) } @@ -231,92 +230,6 @@ impl<'help, 'cmd> Validator<'help, 'cmd> { } } - fn validate_matched_args(&self, matcher: &ArgMatcher) -> ClapResult<()> { - debug!("Validator::validate_matched_args"); - matcher.iter().try_for_each(|(name, ma)| { - debug!( - "Validator::validate_matched_args:iter:{:?}: vals={:#?}", - name, - ma.vals_flatten() - ); - if let Some(arg) = self.cmd.find(name) { - self.validate_arg_num_vals(arg, ma)?; - } - Ok(()) - }) - } - - fn validate_arg_num_vals(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> { - debug!("Validator::validate_arg_num_vals"); - for (_i, group) in ma.vals().enumerate() { - let actual = group.len(); - debug!( - "Validator::validate_arg_num_vals: group={}, actual={}", - _i, actual - ); - - let min_vals = a.get_min_vals().unwrap_or(1); - if a.is_takes_value_set() && 0 < min_vals && actual == 0 { - // Issue 665 (https://github.com/clap-rs/clap/issues/665) - // Issue 1105 (https://github.com/clap-rs/clap/issues/1105) - return Err(Error::empty_value( - self.cmd, - &get_possible_values(a) - .iter() - .filter(|pv| !pv.is_hide_set()) - .map(PossibleValue::get_name) - .collect::>(), - a.to_string(), - )); - } - - if let Some(expected) = a.get_num_args() { - if let Some(expected) = expected.num_values() { - if expected != actual { - debug!( - "Validator::validate_arg_num_vals: Sending error WrongNumberOfValues" - ); - return Err(Error::wrong_number_of_values( - self.cmd, - a.to_string(), - expected, - actual, - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - } else if actual < expected.min_values() { - return Err(Error::too_few_values( - self.cmd, - a.to_string(), - expected.min_values(), - actual, - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } else if expected.max_values() < actual { - debug!("Validator::validate_arg_num_vals: Sending error TooManyValues"); - return Err(Error::too_many_values( - self.cmd, - ma.raw_vals_flatten() - .last() - .expect(INTERNAL_ERROR_MSG) - .to_str() - .expect(INVALID_UTF8) - .to_string(), - a.to_string(), - Usage::new(self.cmd) - .required(&self.required) - .create_usage_with_title(&[]), - )); - } - } - } - Ok(()) - } - fn validate_required( &mut self, matcher: &ArgMatcher, @@ -540,7 +453,7 @@ impl Conflicts { } } -fn get_possible_values<'help>(a: &Arg<'help>) -> Vec> { +pub(crate) fn get_possible_values_cli<'help>(a: &Arg<'help>) -> Vec> { if !a.is_takes_value_set() { vec![] } else { From 03f747ba8be1ff572767d468fcb0b0f434a0f24d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 3 Aug 2022 14:51:38 -0500 Subject: [PATCH 3/5] fix(parser)!: Only apply num_args to user values --- CHANGELOG.md | 2 ++ src/parser/parser.rs | 6 ++++-- tests/builder/default_missing_vals.rs | 1 + tests/builder/default_vals.rs | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dc207f0f69..c67687d9071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Replace `Arg::number_of_values` (average across occurrences) with `Arg::num_args` (per occurrence, raw CLI args, not parsed values) - `num_args(0)` no longer implies `takes_value(true).multiple_values(true)` - `num_args(1)` no longer implies `multiple_values(true)` + - Does not check default values, only what the user explicitly passes in +- Sometimes `Arg::default_missing_value` didn't require `num_args(0..=1)`, now it does - Replace `Arg::min_values` (across all occurrences) with `Arg::num_args(N..)` (per occurrence) - Replace `Arg::max_values` (across all occurrences) with `Arg::num_args(1..=M)` (per occurrence) - Replace `Arg::multiple_values(true)` with `Arg::num_args(1..)` and `Arg::multiple_values(false)` with `Arg::num_args(0)` diff --git a/src/parser/parser.rs b/src/parser/parser.rs index e8fd3328f1f..13db57e8920 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1127,6 +1127,10 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { ident, source ); + + // `default_missing_values` does not count (ie to avoid problems with flags) + self.verify_num_args(arg, &raw_vals)?; + if raw_vals.is_empty() { // We assume this case is valid: require equals, but min_vals == 0. if !arg.default_missing_vals.is_empty() { @@ -1148,8 +1152,6 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { }; } - self.verify_num_args(arg, &raw_vals)?; - match arg.get_action() { ArgAction::Set => { if source == ValueSource::CommandLine diff --git a/tests/builder/default_missing_vals.rs b/tests/builder/default_missing_vals.rs index e0b8541cbf7..b325af27939 100644 --- a/tests/builder/default_missing_vals.rs +++ b/tests/builder/default_missing_vals.rs @@ -171,6 +171,7 @@ fn default_missing_value_flag_value() { Arg::new("flag") .long("flag") .action(ArgAction::Set) + .num_args(0..=1) .default_value("false") .default_missing_value("true"), ); diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index faa8b4d9a7e..fdf157ed186 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -874,6 +874,7 @@ fn missing_with_value_delimiter() { Arg::new("option") .long("option") .value_delimiter(';') + .num_args(0..=1) .default_missing_values(&["value1;value2;value3", "value4;value5"]), ); From 1352be3d8878984572bdc5738de766e5c7059b84 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 3 Aug 2022 17:41:13 -0500 Subject: [PATCH 4/5] fix(parser): Further limit num_args to user values --- src/parser/parser.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 13db57e8920..6ea06d9f88f 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1128,8 +1128,11 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { source ); - // `default_missing_values` does not count (ie to avoid problems with flags) - self.verify_num_args(arg, &raw_vals)?; + // Process before `default_missing_values` to avoid it counting as values from the command + // line + if source == ValueSource::CommandLine { + self.verify_num_args(arg, &raw_vals)?; + } if raw_vals.is_empty() { // We assume this case is valid: require equals, but min_vals == 0. From e6577b284e38afb7c60551d4e91c88366150292b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 3 Aug 2022 14:56:23 -0500 Subject: [PATCH 5/5] fix(assert)!: Prevent require equal when it won't work --- src/builder/debug_asserts.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs index 94aece65ba2..377a2957ee1 100644 --- a/src/builder/debug_asserts.rs +++ b/src/builder/debug_asserts.rs @@ -714,6 +714,15 @@ fn assert_arg(arg: &Arg) { 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 + ); + } } if arg.get_num_args() == Some(1.into()) { assert!(