Repository: clap-rs/clap
Pull request #4023 (2022-08-03 19:47:23)

fix!: num_args controls user args rather than parsed values 
This will help us clean up our interactions with delimiters and eventually, flags.

Part of #2688


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8789bafb..c67687d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,12 +20,14 @@ 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, 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)`
 - 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 +38,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 bd9583f4..32b6dec6 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 <minvals> ... "Tests 2 min vals").number_of_values(2..).required(false),
-                arg!(--maxvals3 <maxvals> ... "Tests 3 max vals").number_of_values(1..=3).required(false),
+                arg!(--minvals2 <minvals> ... "Tests 2 min vals").num_args(2..).required(false),
+                arg!(--maxvals3 <maxvals> ... "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 cbc5d36c..758260ff 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 519471aa..30e2ba78 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 96196411..f79cb6ee 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 e5062227..27150a94 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 16b47647..04fe1e47 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_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs
index 689a2418..d5943e61 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/examples/escaped-positional.rs b/examples/escaped-positional.rs
index e0505b9d..40135cab 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 f532bc68..68442829 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 5ac7019d..5de6d097 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::<String>("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 {
@@ -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 <file>` 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
+    /// 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`]
     ///
@@ -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<ValuesRange>) -> Self {
+    pub fn num_args(mut self, qty: impl Into<ValuesRange>) -> 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<ValuesRange> {
+    pub fn get_num_args(&self) -> Option<ValuesRange> {
         self.num_vals
     }
 
     #[inline]
     pub(crate) fn get_min_vals(&self) -> Option<usize> {
-        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 <opt>...");
@@ -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 [<opt>...]");
@@ -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 <opt>...");
@@ -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 [<opt>]");
@@ -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(), "<pos>...");
@@ -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(), "[<pos>...]");
@@ -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(), "<pos>...");
@@ -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 58c31a54..f202956a 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 38b744fb..377a2957 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 {
@@ -713,8 +714,17 @@ 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_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 5097f1af..812d5d86 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 77f74cea..c9e42253 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 ca13ffa6..880ea747 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 436e9914..373e455f 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<Id, MatchedArg> {
-        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))
     }
@@ -206,7 +202,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 e146fab1..72eb4902 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/matches/matched_arg.rs b/src/parser/matches/matched_arg.rs
index c8fb80a5..74bac990 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<Vec<AnyValue>> {
         self.vals.iter()
     }
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 883b1ada..4e8a256c 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 d23e91a6..6ea06d9f 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,19 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
     ) -> ClapResult<ParseResult> {
         self.resolve_pending(matcher)?;
 
+        debug!(
+            "Parser::react action={:?}, identifier={:?}, source={:?}",
+            arg.get_action(),
+            ident,
+            source
+        );
+
+        // 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.
             if !arg.default_missing_vals.is_empty() {
@@ -1141,12 +1155,6 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
             };
         }
 
-        debug!(
-            "Parser::react action={:?}, identifier={:?}, source={:?}",
-            arg.get_action(),
-            ident,
-            source
-        );
         match arg.get_action() {
             ArgAction::Set => {
                 if source == ValueSource::CommandLine
@@ -1248,6 +1256,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::<Vec<_>>(),
+                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 173c325e..ae91f972 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::<Vec<_>>(),
-                    a.to_string(),
-                ));
-            }
-
-            if let Some(expected) = a.get_num_vals() {
-                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<PossibleValue<'help>> {
+pub(crate) fn get_possible_values_cli<'help>(a: &Arg<'help>) -> Vec<PossibleValue<'help>> {
     if !a.is_takes_value_set() {
         vec![]
     } else {


Test patch:
diff --git a/clap_complete/tests/common.rs b/clap_complete/tests/common.rs
index f1d03238..f2512389 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 f1d03238..f2512389 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_mangen/tests/common.rs b/clap_mangen/tests/common.rs
index 025ffef9..242e3ead 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/tests/builder/app_settings.rs b/tests/builder/app_settings.rs
index 9720c29b..bdb259c5 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 <val> ... "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 6c441c5b..b325af27 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"),
         )
@@ -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"),
     );
@@ -233,7 +234,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 +295,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 e49325cd..fdf157ed 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"]);
@@ -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"]),
     );
 
diff --git a/tests/builder/delimiters.rs b/tests/builder/delimiters.rs
index bc898604..d59c1906 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 94d8d617..99c2f626 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 04fbe56e..0abbabf5 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 d6e8a7c9..a5336130 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 5b193c9c..4fe603a1 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 <color> "some option").number_of_values(1..))
+        .arg(arg!(-c --color <color> "some option").num_args(1..))
         .arg(arg!(-h --hostname <name> "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 11fdc02f..3b95da2a 100644
--- a/tests/builder/help.rs
+++ b/tests/builder/help.rs
@@ -67,7 +67,7 @@ fn help_multi_subcommand_error() {
                         -o --option <scoption>    "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 <scoption>    "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 0e6ad9ba..5f6d40de 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 9c3d939d..0719b95e 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 74072b59..a8333fd6 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 4d93d7e6..72cd3ebe 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 <opt> "some opt").number_of_values(1..))
+        .arg(arg!(o: -o <opt> "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 <opt> "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 <opt> "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 <opt> "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 <opt> "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 41e24d15..253e39d2 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 a0e17a7c..29aeb1bb 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 f103650e..db182b45 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 cb7d7bb8..57f13314 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 9cf31c1a..8b6383fe 100644
--- a/tests/builder/utils.rs
+++ b/tests/builder/utils.rs
@@ -49,7 +49,7 @@ pub fn complex_app() -> Command<'static> {
                 -o --option <opt> "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 <minvals> "Tests 2 min vals")
                 .required(false)
-                .number_of_values(2..),
+                .num_args(2..),
             arg!(--maxvals3 <maxvals> "Tests 3 max vals")
                 .required(false)
-                .number_of_values(1..=3),
+                .num_args(1..=3),
             arg!(--optvaleq <optval> "Tests optional value, require = sign")
                 .required(false)
-                .number_of_values(0..=1)
+                .num_args(0..=1)
                 .require_equals(true),
             arg!(--optvalnoeq <optval> "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 <scoption> "tests options")
                         .required(false)
-                        .number_of_values(1..),
+                        .num_args(1..),
                 )
                 .arg(arg!(-s --subcmdarg <subcmdarg> "tests other args").required(false))
                 .arg(arg!([scpositional] "tests positionals")),
diff --git a/tests/derive/options.rs b/tests/derive/options.rs
index d41dab2d..82e8a934 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<i32>,
     }
     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<Vec<i32>>,
     }
     assert_eq!(