fix!: Replace multiple_values with number_of_values

This reduces ambiguity in how the different "multiple" parts of the API
interact and lowrs the amount of API surface area users have to dig
through to use clap.

For now, this is only a matter of cleaning up the public API.  Cleaning
up the implementation is the next step.
This commit is contained in:
Ed Page 2022-07-29 07:23:42 -05:00
parent e2a6bbfa95
commit 470531b515
39 changed files with 170 additions and 354 deletions

View file

@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `number_of_values(1)` no longer implies `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::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::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)`
- `ArgAction::SetTrue` and `ArgAction::SetFalse` now prioritize `Arg::default_missing_value` over their standard behavior - `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) - *(help)* Make `DeriveDisplayOrder` the default and removed the setting. To sort help, set `next_display_order(None)` (#2808)
- *(help)* Subcommand display order respects `Command::next_display_order` instead of `DeriveDisplayOrder` and using its own initial display order value (#2808) - *(help)* Subcommand display order respects `Command::next_display_order` instead of `DeriveDisplayOrder` and using its own initial display order value (#2808)

View file

@ -30,9 +30,9 @@ macro_rules! create_app {
arg!(--multvals <s> "Tests multiple values not mult occs").required(false).value_names(&["one", "two"]), arg!(--multvals <s> "Tests multiple values not mult occs").required(false).value_names(&["one", "two"]),
arg!( arg!(
--multvalsmo <s> "Tests multiple values, not mult occs" --multvalsmo <s> "Tests multiple values, not mult occs"
).multiple_values(true).required(false).value_names(&["one", "two"]), ).required(false).value_names(&["one", "two"]),
arg!(--minvals2 <minvals> ... "Tests 2 min vals").number_of_values(2..).multiple_values(true).required(false), 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).multiple_values(true).required(false), arg!(--maxvals3 <maxvals> ... "Tests 3 max vals").number_of_values(1..=3).required(false),
]) ])
.subcommand( .subcommand(
Command::new("subcmd") Command::new("subcmd")
@ -57,7 +57,7 @@ pub fn build_from_builder(c: &mut Criterion) {
.help("tests options") .help("tests options")
.short('o') .short('o')
.long("option") .long("option")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.arg(Arg::new("positional").help("tests positionals").index(1)) .arg(Arg::new("positional").help("tests positionals").index(1))
@ -99,7 +99,7 @@ pub fn build_from_builder(c: &mut Criterion) {
) )
.arg( .arg(
Arg::new("positional3") Arg::new("positional3")
.multiple_values(true) .number_of_values(1..)
.help("tests positionals with specific values") .help("tests positionals with specific values")
.index(4) .index(4)
.value_parser(POS3_VALS), .value_parser(POS3_VALS),
@ -113,7 +113,6 @@ pub fn build_from_builder(c: &mut Criterion) {
.arg( .arg(
Arg::new("multvalsmo") Arg::new("multvalsmo")
.long("multvalsmo") .long("multvalsmo")
.multiple_values(true)
.action(ArgAction::Append) .action(ArgAction::Append)
.help("Tests multiple values, not mult occs") .help("Tests multiple values, not mult occs")
.value_names(&["one", "two"]), .value_names(&["one", "two"]),
@ -121,7 +120,6 @@ pub fn build_from_builder(c: &mut Criterion) {
.arg( .arg(
Arg::new("minvals") Arg::new("minvals")
.long("minvals2") .long("minvals2")
.multiple_values(true)
.action(ArgAction::Append) .action(ArgAction::Append)
.help("Tests 2 min vals") .help("Tests 2 min vals")
.number_of_values(2..), .number_of_values(2..),
@ -129,7 +127,6 @@ pub fn build_from_builder(c: &mut Criterion) {
.arg( .arg(
Arg::new("maxvals") Arg::new("maxvals")
.long("maxvals3") .long("maxvals3")
.multiple_values(true)
.action(ArgAction::Append) .action(ArgAction::Append)
.help("Tests 3 max vals") .help("Tests 3 max vals")
.number_of_values(1..=3), .number_of_values(1..=3),
@ -143,7 +140,7 @@ pub fn build_from_builder(c: &mut Criterion) {
Arg::new("scoption") Arg::new("scoption")
.short('o') .short('o')
.long("option") .long("option")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append) .action(ArgAction::Append)
.help("tests options"), .help("tests options"),
) )

View file

@ -118,7 +118,7 @@ fn app_example7<'c>() -> Command<'c> {
.arg( .arg(
Arg::new("input") Arg::new("input")
.help("the input file to use") .help("the input file to use")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append) .action(ArgAction::Append)
.required(true) .required(true)
.short('i') .short('i')
@ -135,7 +135,7 @@ fn app_example8<'c>() -> Command<'c> {
.arg( .arg(
Arg::new("input") Arg::new("input")
.help("the input file to use") .help("the input file to use")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append) .action(ArgAction::Append)
.required(true) .required(true)
.short('i') .short('i')

View file

@ -323,7 +323,7 @@ where
"type-list", "type-list",
"version", "version",
])) ]))
.arg(arg("path").multiple_values(true)) .arg(arg("path").number_of_values(1..))
.arg( .arg(
flag("regexp") flag("regexp")
.short('e') .short('e')

View file

@ -236,7 +236,7 @@ fn build_cli() -> Command<'static> {
.after_help(RUN_HELP) .after_help(RUN_HELP)
.trailing_var_arg(true) .trailing_var_arg(true)
.arg(Arg::new("toolchain").required(true)) .arg(Arg::new("toolchain").required(true))
.arg(Arg::new("command").required(true).multiple_values(true)), .arg(Arg::new("command").required(true).number_of_values(1..)),
) )
.subcommand( .subcommand(
Command::new("which") Command::new("which")

View file

@ -68,7 +68,7 @@ fn build_cli() -> Command<'static> {
) )
.arg( .arg(
Arg::new("command_with_args") Arg::new("command_with_args")
.multiple_values(true) .number_of_values(1..)
.value_hint(ValueHint::CommandWithArguments), .value_hint(ValueHint::CommandWithArguments),
) )
.arg( .arg(

View file

@ -64,7 +64,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
.require_equals(true) .require_equals(true)
.help("the other case to test"), .help("the other case to test"),
) )
.arg(clap::Arg::new("path").multiple_values(true)), .arg(clap::Arg::new("path").number_of_values(1..)),
) )
.subcommand(clap::Command::new("some-cmd-with-hyphens").alias("hyphen")) .subcommand(clap::Command::new("some-cmd-with-hyphens").alias("hyphen"))
.subcommand(clap::Command::new("some-hidden-cmd").hide(true)) .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( .arg(
clap::Arg::new("command_with_args") clap::Arg::new("command_with_args")
.action(clap::ArgAction::Set) .action(clap::ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.value_hint(clap::ValueHint::CommandWithArguments), .value_hint(clap::ValueHint::CommandWithArguments),
) )
.arg( .arg(

View file

@ -39,7 +39,7 @@ _my-app() {
return 0 return 0
;; ;;
my__app__help) my__app__help)
opts="-c <SUBCOMMAND>..." opts="-c [<SUBCOMMAND>...]"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0

View file

@ -39,7 +39,7 @@ _my-app() {
return 0 return 0
;; ;;
my__app__help) my__app__help)
opts="<SUBCOMMAND>..." opts="[<SUBCOMMAND>...]"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0

View file

@ -138,7 +138,7 @@ _my-app() {
return 0 return 0
;; ;;
my__app__help) my__app__help)
opts="<SUBCOMMAND>..." opts="[<SUBCOMMAND>...]"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0

View file

@ -48,7 +48,7 @@ _my-app() {
return 0 return 0
;; ;;
my__app__help) my__app__help)
opts="<SUBCOMMAND>..." opts="[<SUBCOMMAND>...]"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0

View file

@ -45,7 +45,7 @@ _my-app() {
return 0 return 0
;; ;;
my__app__help) my__app__help)
opts="<SUBCOMMAND>..." opts="[<SUBCOMMAND>...]"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0
@ -73,7 +73,7 @@ _my-app() {
return 0 return 0
;; ;;
my__app__some_cmd__help) my__app__some_cmd__help)
opts="<SUBCOMMAND>..." opts="[<SUBCOMMAND>...]"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0 return 0

View file

@ -64,7 +64,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
.require_equals(true) .require_equals(true)
.help("the other case to test"), .help("the other case to test"),
) )
.arg(clap::Arg::new("path").multiple_values(true)), .arg(clap::Arg::new("path").number_of_values(1..)),
) )
.subcommand(clap::Command::new("some-cmd-with-hyphens").alias("hyphen")) .subcommand(clap::Command::new("some-cmd-with-hyphens").alias("hyphen"))
.subcommand(clap::Command::new("some-hidden-cmd").hide(true)) .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( .arg(
clap::Arg::new("command_with_args") clap::Arg::new("command_with_args")
.action(clap::ArgAction::Set) .action(clap::ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.value_hint(clap::ValueHint::CommandWithArguments), .value_hint(clap::ValueHint::CommandWithArguments),
) )
.arg( .arg(

View file

@ -267,7 +267,7 @@ pub fn gen_augment(
if attrs.is_positional() { if attrs.is_positional() {
quote_spanned! { ty.span()=> quote_spanned! { ty.span()=>
.value_name(#value_name) .value_name(#value_name)
.multiple_values(true) // action won't be sufficient for getting multiple .number_of_values(1..) // action won't be sufficient for getting multiple
#value_parser #value_parser
#action #action
} }
@ -284,7 +284,7 @@ pub fn gen_augment(
if attrs.is_positional() { if attrs.is_positional() {
quote_spanned! { ty.span()=> quote_spanned! { ty.span()=>
.value_name(#value_name) .value_name(#value_name)
.multiple_values(true) // action won't be sufficient for getting multiple .number_of_values(1..) // action won't be sufficient for getting multiple
#value_parser #value_parser
#action #action
} }

View file

@ -216,7 +216,7 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> {
.arg( .arg(
clap::Arg::new("command_with_args") clap::Arg::new("command_with_args")
.action(clap::ArgAction::Set) .action(clap::ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.value_hint(clap::ValueHint::CommandWithArguments), .value_hint(clap::ValueHint::CommandWithArguments),
) )
.arg( .arg(

View file

@ -11,7 +11,7 @@ fn main() {
.arg( .arg(
// Indicates that `slop` is only accessible after `--`. // Indicates that `slop` is only accessible after `--`.
arg!(slop: [SLOP]) arg!(slop: [SLOP])
.multiple_values(true) .number_of_values(1..)
.last(true) .last(true)
.value_parser(value_parser!(String)), .value_parser(value_parser!(String)),
) )

View file

@ -22,7 +22,7 @@ fn main() {
.help("search locally installed packages for matching strings") .help("search locally installed packages for matching strings")
.conflicts_with("info") .conflicts_with("info")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.arg( .arg(
Arg::new("info") Arg::new("info")
@ -31,7 +31,7 @@ fn main() {
.conflicts_with("search") .conflicts_with("search")
.help("view package information") .help("view package information")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
), ),
) )
// Sync subcommand // Sync subcommand
@ -48,7 +48,7 @@ fn main() {
.long("search") .long("search")
.conflicts_with("info") .conflicts_with("info")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.help("search remote repositories for matching strings"), .help("search remote repositories for matching strings"),
) )
.arg( .arg(
@ -64,7 +64,7 @@ fn main() {
.help("packages") .help("packages")
.required_unless_present("search") .required_unless_present("search")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
), ),
) )
.get_matches(); .get_matches();

View file

@ -411,8 +411,8 @@ impl<'help> Arg<'help> {
/// **NOTE:** This is only meant to be used for positional arguments and shouldn't to be used /// **NOTE:** This is only meant to be used for positional arguments and shouldn't to be used
/// with [`Arg::short`] or [`Arg::long`]. /// with [`Arg::short`] or [`Arg::long`].
/// ///
/// **NOTE:** When utilized with [`Arg::multiple_values(true)`], only the **last** positional argument /// **NOTE:** When utilized with [`Arg::number_of_values(1..)`], only the **last** positional argument
/// may be defined as multiple (i.e. with the highest index) /// may be defined as having a variable number of arguments (i.e. with the highest index)
/// ///
/// # Panics /// # Panics
/// ///
@ -447,7 +447,7 @@ impl<'help> Arg<'help> {
/// ``` /// ```
/// [`Arg::short`]: Arg::short() /// [`Arg::short`]: Arg::short()
/// [`Arg::long`]: Arg::long() /// [`Arg::long`]: Arg::long()
/// [`Arg::multiple_values(true)`]: Arg::multiple_values() /// [`Arg::number_of_values(true)`]: Arg::number_of_values()
/// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html /// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html
/// [`Command`]: crate::Command /// [`Command`]: crate::Command
#[inline] #[inline]
@ -808,7 +808,7 @@ impl<'help> Arg<'help> {
/// assert_eq!(m.get_one::<String>("mode").unwrap(), "fast"); /// assert_eq!(m.get_one::<String>("mode").unwrap(), "fast");
/// ``` /// ```
/// [`Arg::value_delimiter(char)`]: Arg::value_delimiter() /// [`Arg::value_delimiter(char)`]: Arg::value_delimiter()
/// [multiple values]: Arg::multiple_values /// [multiple values]: Arg::number_of_values
#[inline] #[inline]
#[must_use] #[must_use]
pub fn takes_value(self, yes: bool) -> Self { pub fn takes_value(self, yes: bool) -> Self {
@ -905,170 +905,9 @@ impl<'help> Arg<'help> {
self self
} }
/// Specifies that the argument may have an unknown number of values
///
/// Without any other settings, this argument may appear only *once*.
///
/// For example, `--opt val1 val2` is allowed, but `--opt val1 val2 --opt val3` is not.
///
/// **NOTE:** Setting this requires [`Arg::takes_value`].
///
/// **WARNING:**
///
/// Setting `multiple_values` for an argument that takes a value, but with no other details can
/// be dangerous in some circumstances. Because multiple values are allowed,
/// `--option val1 val2 val3` is perfectly valid. Be careful when designing a CLI where
/// positional arguments are *also* expected as `clap` will continue parsing *values* until one
/// of the following happens:
///
/// - It reaches the [maximum number of values]
/// - It reaches a [specific number of values]
/// - It finds another flag or option (i.e. something that starts with a `-`)
/// - It reaches a [value terminator][Arg::value_terminator]
///
/// Alternatively, [require a delimiter between values][Arg::require_value_delimiter].
///
/// **WARNING:**
///
/// When using args with `multiple_values` and [`subcommands`], one needs to consider the
/// possibility of an argument value being the same as a valid subcommand. By default `clap` will
/// parse the argument in question as a value *only if* a value is possible at that moment.
/// Otherwise it will be parsed as a subcommand. In effect, this means using `multiple_values` with no
/// additional parameters and a value that coincides with a subcommand name, the subcommand
/// cannot be called unless another argument is passed between them.
///
/// As an example, consider a CLI with an option `--ui-paths=<paths>...` and subcommand `signer`
///
/// The following would be parsed as values to `--ui-paths`.
///
/// ```text
/// $ program --ui-paths path1 path2 signer
/// ```
///
/// This is because `--ui-paths` accepts multiple values. `clap` will continue parsing values
/// until another argument is reached and it knows `--ui-paths` is done parsing.
///
/// By adding additional parameters to `--ui-paths` we can solve this issue. Consider adding
/// [`Arg::number_of_values(1)`] or using *only* [`ArgAction::Append`]. The following are all
/// valid, and `signer` is parsed as a subcommand in the first case, but a value in the second
/// case.
///
/// ```text
/// $ program --ui-paths path1 signer
/// $ program --ui-paths path1 --ui-paths signer signer
/// ```
///
/// # Examples
///
/// An example with options
///
/// ```rust
/// # use clap::{Command, Arg, ArgAction};
/// let m = Command::new("prog")
/// .arg(Arg::new("file")
/// .action(ArgAction::Set)
/// .multiple_values(true)
/// .short('F'))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3"
/// ]);
///
/// assert!(m.contains_id("file"));
/// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3"]);
/// ```
///
/// Although `multiple_values` has been specified, the last argument still wins
///
/// ```rust
/// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
/// let m = Command::new("prog")
/// .arg(Arg::new("file")
/// .action(ArgAction::Set)
/// .multiple_values(true)
/// .short('F'))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "-F", "file2", "-F", "file3"
/// ]);
///
/// assert!(m.contains_id("file"));
/// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
/// assert_eq!(files, ["file3"]);
/// ```
///
/// A common mistake is to define an option which allows multiple values, and a positional
/// argument.
///
/// ```rust
/// # use clap::{Command, Arg, ArgAction};
/// let m = Command::new("prog")
/// .arg(Arg::new("file")
/// .action(ArgAction::Set)
/// .multiple_values(true)
/// .short('F'))
/// .arg(Arg::new("word"))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3", "word"
/// ]);
///
/// assert!(m.contains_id("file"));
/// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3", "word"]); // wait...what?!
/// assert!(!m.contains_id("word")); // but we clearly used word!
/// ```
///
/// The problem is `clap` doesn't know when to stop parsing values for "files". This is further
/// compounded by if we'd said `word -F file1 file2` it would have worked fine, so it would
/// appear to only fail sometimes...not good!
///
/// A solution for the example above is to limit how many values with a [maximum], or [specific]
/// number, or to say [`ArgAction::Append`] is ok, but multiple values is not.
///
/// ```rust
/// # use clap::{Command, Arg, ArgAction};
/// let m = Command::new("prog")
/// .arg(Arg::new("file")
/// .action(ArgAction::Set)
/// .action(ArgAction::Append)
/// .short('F'))
/// .arg(Arg::new("word"))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "-F", "file2", "-F", "file3", "word"
/// ]);
///
/// assert!(m.contains_id("file"));
/// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3"]);
/// assert_eq!(m.get_one::<String>("word").unwrap(), "word");
/// ```
///
/// As a final example, let's fix the above error and get a pretty message to the user :)
///
/// ```rust
/// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
/// let res = Command::new("prog")
/// .arg(Arg::new("file")
/// .action(ArgAction::Set)
/// .action(ArgAction::Append)
/// .short('F'))
/// .arg(Arg::new("word"))
/// .try_get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3", "word"
/// ]);
///
/// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
/// ```
///
/// [`subcommands`]: crate::Command::subcommand()
/// [`Arg::number_of_values(1)`]: Arg::number_of_values()
/// [maximum number of values]: Arg::number_of_values()
/// [specific number of values]: Arg::number_of_values()
/// [maximum]: Arg::number_of_values()
/// [specific]: Arg::number_of_values()
#[inline] #[inline]
#[must_use] #[must_use]
pub fn multiple_values(self, yes: bool) -> Self { fn multiple_values(self, yes: bool) -> Self {
if yes { if yes {
self.setting(ArgSettings::MultipleValues) self.setting(ArgSettings::MultipleValues)
} else { } else {
@ -1222,7 +1061,6 @@ impl<'help> Arg<'help> {
/// assert_eq!(m.get_one::<String>("word").unwrap(), "word"); /// assert_eq!(m.get_one::<String>("word").unwrap(), "word");
/// ``` /// ```
/// [`Arg::value_delimiter(char)`]: Arg::value_delimiter() /// [`Arg::value_delimiter(char)`]: Arg::value_delimiter()
/// [multiple values]: Arg::multiple_values
#[inline] #[inline]
#[must_use] #[must_use]
pub fn number_of_values(mut self, qty: impl Into<ValuesRange>) -> Self { pub fn number_of_values(mut self, qty: impl Into<ValuesRange>) -> Self {
@ -1298,7 +1136,7 @@ impl<'help> Arg<'help> {
/// **Pro Tip:** It may help to use [`Arg::next_line_help(true)`] if there are long, or /// **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. /// 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::multiple_values(true)`]. /// **NOTE:** implicitly sets [`Arg::action(ArgAction::Set)`] and [`Arg::number_of_values(1..)`].
/// ///
/// # Examples /// # Examples
/// ///
@ -1336,7 +1174,7 @@ impl<'help> Arg<'help> {
/// [`Arg::next_line_help(true)`]: Arg::next_line_help() /// [`Arg::next_line_help(true)`]: Arg::next_line_help()
/// [`Arg::number_of_values`]: Arg::number_of_values() /// [`Arg::number_of_values`]: Arg::number_of_values()
/// [`Arg::action(ArgAction::Set)`]: Arg::takes_value() /// [`Arg::action(ArgAction::Set)`]: Arg::takes_value()
/// [`Arg::multiple_values(true)`]: Arg::multiple_values() /// [`Arg::number_of_values(1..)`]: Arg::number_of_values()
#[must_use] #[must_use]
pub fn value_names(mut self, names: &[&'help str]) -> Self { pub fn value_names(mut self, names: &[&'help str]) -> Self {
self.val_names = names.to_vec(); self.val_names = names.to_vec();
@ -1368,7 +1206,7 @@ impl<'help> Arg<'help> {
/// .arg( /// .arg(
/// Arg::new("command") /// Arg::new("command")
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .multiple_values(true) /// .number_of_values(1..)
/// .value_hint(ValueHint::CommandWithArguments) /// .value_hint(ValueHint::CommandWithArguments)
/// ); /// );
/// ``` /// ```
@ -1417,7 +1255,7 @@ impl<'help> Arg<'help> {
/// .long("option") /// .long("option")
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .ignore_case(true) /// .ignore_case(true)
/// .multiple_values(true) /// .number_of_values(1..)
/// .value_parser(["test123", "test321"])) /// .value_parser(["test123", "test321"]))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "pv", "--option", "TeSt123", "teST123", "tESt321" /// "pv", "--option", "TeSt123", "teST123", "tESt321"
@ -1441,7 +1279,7 @@ impl<'help> Arg<'help> {
/// **NOTE:** Setting this requires [`Arg::takes_value`] /// **NOTE:** Setting this requires [`Arg::takes_value`]
/// ///
/// **WARNING**: Take caution when using this setting combined with /// **WARNING**: Take caution when using this setting combined with
/// [`Arg::multiple_values`], as this becomes ambiguous `$ prog --arg -- -- val`. All /// [`Arg::number_of_values`], as this becomes ambiguous `$ prog --arg -- -- val`. All
/// three `--, --, val` will be values when the user may have thought the second `--` would /// three `--, --, val` will be values when the user may have thought the second `--` would
/// constitute the normal, "Only positional args follow" idiom. /// constitute the normal, "Only positional args follow" idiom.
/// ///
@ -1666,7 +1504,7 @@ impl<'help> Arg<'help> {
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .use_value_delimiter(true) /// .use_value_delimiter(true)
/// .require_value_delimiter(true) /// .require_value_delimiter(true)
/// .multiple_values(true)) /// .number_of_values(1..))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog", "-o", "val1,val2,val3", /// "prog", "-o", "val1,val2,val3",
/// ]); /// ]);
@ -1707,7 +1545,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("opt") /// .arg(Arg::new("opt")
/// .short('o') /// .short('o')
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .multiple_values(true)) /// .number_of_values(1..))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog", "-o", "val1", "val2", "val3", /// "prog", "-o", "val1", "val2", "val3",
/// ]); /// ]);
@ -1728,7 +1566,7 @@ impl<'help> Arg<'help> {
/// Sentinel to **stop** parsing multiple values of a given argument. /// Sentinel to **stop** parsing multiple values of a given argument.
/// ///
/// By default when /// By default when
/// one sets [`multiple_values(true)`] on an argument, clap will continue parsing values for that /// one sets [`number_of_values(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 /// 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 [`number_of_values`]).
/// ///
@ -1743,7 +1581,7 @@ impl<'help> Arg<'help> {
/// # use clap::{Command, Arg, ArgAction}; /// # use clap::{Command, Arg, ArgAction};
/// Arg::new("vals") /// Arg::new("vals")
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .multiple_values(true) /// .number_of_values(1..)
/// .value_terminator(";") /// .value_terminator(";")
/// # ; /// # ;
/// ``` /// ```
@ -1756,7 +1594,7 @@ impl<'help> Arg<'help> {
/// let m = Command::new("prog") /// let m = Command::new("prog")
/// .arg(Arg::new("cmds") /// .arg(Arg::new("cmds")
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .multiple_values(true) /// .number_of_values(1..)
/// .allow_hyphen_values(true) /// .allow_hyphen_values(true)
/// .value_terminator(";")) /// .value_terminator(";"))
/// .arg(Arg::new("location")) /// .arg(Arg::new("location"))
@ -1769,7 +1607,7 @@ impl<'help> Arg<'help> {
/// ``` /// ```
/// [options]: Arg::takes_value() /// [options]: Arg::takes_value()
/// [positional arguments]: Arg::index() /// [positional arguments]: Arg::index()
/// [`multiple_values(true)`]: Arg::multiple_values() /// [`number_of_values(1..)`]: Arg::number_of_values()
/// [`number_of_values`]: Arg::number_of_values() /// [`number_of_values`]: Arg::number_of_values()
#[inline] #[inline]
#[must_use] #[must_use]
@ -1793,11 +1631,11 @@ impl<'help> Arg<'help> {
/// may not be exactly what you are expecting and using [`crate::Command::trailing_var_arg`] /// may not be exactly what you are expecting and using [`crate::Command::trailing_var_arg`]
/// may be more appropriate. /// may be more appropriate.
/// ///
/// **NOTE:** Implicitly sets [`Arg::action(ArgAction::Set)`] [`Arg::multiple_values(true)`], /// **NOTE:** Implicitly sets [`Arg::action(ArgAction::Set)`] [`Arg::number_of_values(1..)`],
/// [`Arg::allow_hyphen_values(true)`], and [`Arg::last(true)`] when set to `true`. /// [`Arg::allow_hyphen_values(true)`], and [`Arg::last(true)`] when set to `true`.
/// ///
/// [`Arg::action(ArgAction::Set)`]: Arg::takes_value() /// [`Arg::action(ArgAction::Set)`]: Arg::takes_value()
/// [`Arg::multiple_values(true)`]: Arg::multiple_values() /// [`Arg::number_of_values(1..)`]: Arg::number_of_values()
/// [`Arg::allow_hyphen_values(true)`]: Arg::allow_hyphen_values() /// [`Arg::allow_hyphen_values(true)`]: Arg::allow_hyphen_values()
/// [`Arg::last(true)`]: Arg::last() /// [`Arg::last(true)`]: Arg::last()
#[inline] #[inline]
@ -2170,7 +2008,7 @@ impl<'help> Arg<'help> {
/// .long("flag") /// .long("flag")
/// .env("MY_FLAG_MULTI") /// .env("MY_FLAG_MULTI")
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .multiple_values(true) /// .number_of_values(1..)
/// .use_value_delimiter(true)) /// .use_value_delimiter(true))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog" /// "prog"
@ -4131,7 +3969,7 @@ impl<'help> Arg<'help> {
self.is_set(ArgSettings::Required) self.is_set(ArgSettings::Required)
} }
/// Report whether [`Arg::multiple_values`] is set /// Report whether [`Arg::number_of_values`] allows multiple values
pub fn is_multiple_values_set(&self) -> bool { pub fn is_multiple_values_set(&self) -> bool {
self.is_set(ArgSettings::MultipleValues) self.is_set(ArgSettings::MultipleValues)
} }
@ -4659,7 +4497,7 @@ mod test {
let mut o = Arg::new("opt") let mut o = Arg::new("opt")
.long("option") .long("option")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true); .number_of_values(1..);
o._build(); o._build();
assert_eq!(o.to_string(), "--option <opt>..."); assert_eq!(o.to_string(), "--option <opt>...");
@ -4737,12 +4575,12 @@ mod test {
fn option_display3() { fn option_display3() {
let mut o = Arg::new("opt") let mut o = Arg::new("opt")
.short('o') .short('o')
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Set) .action(ArgAction::Set)
.value_names(&["file", "name"]); .value_names(&["file", "name"]);
o._build(); o._build();
assert_eq!(o.to_string(), "-o <file> <name>"); assert_eq!(o.to_string(), "-o <file> <name>...");
} }
#[test] #[test]
@ -4795,7 +4633,7 @@ mod test {
#[test] #[test]
fn positional_display_multiple_values() { fn positional_display_multiple_values() {
let mut p = Arg::new("pos").index(1).multiple_values(true); let mut p = Arg::new("pos").index(1).number_of_values(1..);
p._build(); p._build();
assert_eq!(p.to_string(), "<pos>..."); assert_eq!(p.to_string(), "<pos>...");

View file

@ -2016,8 +2016,7 @@ impl<'help> Command<'help> {
/// ///
/// The values of the trailing positional argument will contain all args from itself on. /// The values of the trailing positional argument will contain all args from itself on.
/// ///
/// **NOTE:** The final positional argument **must** have [`Arg::multiple_values(true)`] or the usage /// **NOTE:** The final positional argument **must** have [`Arg::number_of_values(..)`].
/// string equivalent.
/// ///
/// # Examples /// # Examples
/// ///
@ -2031,7 +2030,7 @@ impl<'help> Command<'help> {
/// let trail: Vec<_> = m.get_many::<String>("cmd").unwrap().collect(); /// let trail: Vec<_> = m.get_many::<String>("cmd").unwrap().collect();
/// assert_eq!(trail, ["arg1", "-r", "val1"]); /// assert_eq!(trail, ["arg1", "-r", "val1"]);
/// ``` /// ```
/// [`Arg::multiple_values(true)`]: crate::Arg::multiple_values() /// [`Arg::number_of_values(true)`]: crate::Arg::number_of_values()
pub fn trailing_var_arg(self, yes: bool) -> Self { pub fn trailing_var_arg(self, yes: bool) -> Self {
if yes { if yes {
self.setting(AppSettings::TrailingVarArg) self.setting(AppSettings::TrailingVarArg)
@ -2117,7 +2116,7 @@ impl<'help> Command<'help> {
/// .allow_missing_positional(true) /// .allow_missing_positional(true)
/// .arg(Arg::new("foo")) /// .arg(Arg::new("foo"))
/// .arg(Arg::new("bar")) /// .arg(Arg::new("bar"))
/// .arg(Arg::new("baz").action(ArgAction::Set).multiple_values(true)) /// .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog", "foo", "bar", "baz1", "baz2", "baz3" /// "prog", "foo", "bar", "baz1", "baz2", "baz3"
/// ]); /// ]);
@ -2136,7 +2135,7 @@ impl<'help> Command<'help> {
/// .allow_missing_positional(true) /// .allow_missing_positional(true)
/// .arg(Arg::new("foo")) /// .arg(Arg::new("foo"))
/// .arg(Arg::new("bar")) /// .arg(Arg::new("bar"))
/// .arg(Arg::new("baz").action(ArgAction::Set).multiple_values(true)) /// .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog", "--", "baz1", "baz2", "baz3" /// "prog", "--", "baz1", "baz2", "baz3"
/// ]); /// ]);
@ -2832,7 +2831,7 @@ impl<'help> Command<'help> {
/// let cmd = Command::new("cmd").subcommand(Command::new("sub")).arg( /// let cmd = Command::new("cmd").subcommand(Command::new("sub")).arg(
/// Arg::new("arg") /// Arg::new("arg")
/// .long("arg") /// .long("arg")
/// .multiple_values(true) /// .number_of_values(1..)
/// .action(ArgAction::Set), /// .action(ArgAction::Set),
/// ); /// );
/// ///
@ -4255,7 +4254,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.",
Arg::new("subcommand") Arg::new("subcommand")
.index(1) .index(1)
.action(ArgAction::Append) .action(ArgAction::Append)
.multiple_values(true) .number_of_values(..)
.value_name("SUBCOMMAND") .value_name("SUBCOMMAND")
.help("The subcommand whose help message to display"), .help("The subcommand whose help message to display"),
); );

View file

@ -131,7 +131,7 @@ pub(crate) fn assert_app(cmd: &Command) {
panic!( panic!(
"Command {}: Argument '{}' has the same index as '{}' \ "Command {}: Argument '{}' has the same index as '{}' \
and they are both positional arguments\n\n\t \ and they are both positional arguments\n\n\t \
Use Arg::multiple_values(true) to allow one \ Use Arg::number_of_values(1..) to allow one \
positional argument to take multiple values", positional argument to take multiple values",
cmd.get_name(), cmd.get_name(),
first.name, first.name,
@ -517,7 +517,7 @@ fn _verify_positionals(cmd: &Command) -> bool {
|| last.is_last_set(); || last.is_last_set();
assert!( assert!(
ok, ok,
"When using a positional argument with .multiple_values(true) that is *not the \ "When using a positional argument with .number_of_values(1..) that is *not the \
last* positional argument, the last positional argument (i.e. the one \ last* positional argument, the last positional argument (i.e. the one \
with the highest index) *must* have .required(true) or .last(true) set." with the highest index) *must* have .required(true) or .last(true) set."
); );
@ -527,7 +527,7 @@ fn _verify_positionals(cmd: &Command) -> bool {
assert!( assert!(
ok, ok,
"Only the last positional argument, or second to last positional \ "Only the last positional argument, or second to last positional \
argument may be set to .multiple_values(true)" argument may be set to .number_of_values(1..)"
); );
// Next we check how many have both Multiple and not a specific number of values set // Next we check how many have both Multiple and not a specific number of values set
@ -544,7 +544,7 @@ fn _verify_positionals(cmd: &Command) -> bool {
&& count == 2); && count == 2);
assert!( assert!(
ok, ok,
"Only one positional argument with .multiple_values(true) set is allowed per \ "Only one positional argument with .number_of_values(1..) set is allowed per \
command, unless the second one also has .last(true) set" command, unless the second one also has .last(true) set"
); );
} }

View file

@ -48,12 +48,12 @@ pub enum ValueHint {
/// common when writing shell wrappers that execute anther command, for example `sudo` or `env`. /// 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 /// This hint is special, the argument must be a positional argument and have
/// [`.multiple_values(true)`] and Command must use [`Command::trailing_var_arg(true)`]. The result is that the /// [`.number_of_values(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 /// command line `my_app ls -la /` will be parsed as `["ls", "-la", "/"]` and clap won't try to
/// parse the `-la` argument itself. /// parse the `-la` argument itself.
/// ///
/// [`Command::trailing_var_arg(true)`]: crate::Command::trailing_var_arg /// [`Command::trailing_var_arg(true)`]: crate::Command::trailing_var_arg
/// [`.multiple_values(true)`]: crate::Arg::multiple_values() /// [`.number_of_values(1..)`]: crate::Arg::number_of_values()
CommandWithArguments, CommandWithArguments,
/// Name of a local operating system user. /// Name of a local operating system user.
Username, Username,

View file

@ -412,7 +412,7 @@ macro_rules! arg_impl {
@arg @arg
({ ({
if $arg.get_long().is_none() && $arg.get_short().is_none() { if $arg.get_long().is_none() && $arg.get_short().is_none() {
$arg.multiple_values(true) $arg.number_of_values(1..)
// Allow collecting arguments interleaved with flags // Allow collecting arguments interleaved with flags
.action($crate::ArgAction::Append) .action($crate::ArgAction::Append)
} else if $arg.is_takes_value_set() { } else if $arg.is_takes_value_set() {

View file

@ -263,9 +263,8 @@ impl ArgMatches {
/// let mut m = Command::new("myprog") /// let mut m = Command::new("myprog")
/// .arg(Arg::new("file") /// .arg(Arg::new("file")
/// .action(ArgAction::Append) /// .action(ArgAction::Append)
/// .multiple_values(true) /// .number_of_values(1..)
/// .required(true) /// .required(true))
/// .action(ArgAction::Set))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "myprog", "file1.txt", "file2.txt", "file3.txt", "file4.txt", /// "myprog", "file1.txt", "file2.txt", "file3.txt", "file4.txt",
/// ]); /// ]);
@ -545,7 +544,7 @@ impl ArgMatches {
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .use_value_delimiter(true) /// .use_value_delimiter(true)
/// .multiple_values(true)) /// .number_of_values(1..))
/// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
/// // ARGV indices: ^0 ^1 /// // ARGV indices: ^0 ^1
/// // clap indices: ^2 ^3 ^4 /// // clap indices: ^2 ^3 ^4
@ -586,8 +585,7 @@ impl ArgMatches {
/// let m = Command::new("myapp") /// let m = Command::new("myapp")
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .use_value_delimiter(true) /// .use_value_delimiter(true))
/// .multiple_values(true))
/// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
/// // ARGV indices: ^0 ^1 /// // ARGV indices: ^0 ^1
/// // clap indices: ^2 ^3 ^4 /// // clap indices: ^2 ^3 ^4
@ -628,7 +626,7 @@ impl ArgMatches {
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .action(ArgAction::Set) /// .action(ArgAction::Set)
/// .multiple_values(true)) /// .number_of_values(1..))
/// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
/// // ARGV indices: ^0 ^1 /// // ARGV indices: ^0 ^1
/// // clap indices: ^2 /// // clap indices: ^2
@ -1328,7 +1326,7 @@ impl<'a> Default for GroupedValues<'a> {
/// let m = Command::new("myapp") /// let m = Command::new("myapp")
/// .arg(Arg::new("output") /// .arg(Arg::new("output")
/// .short('o') /// .short('o')
/// .multiple_values(true) /// .number_of_values(1..)
/// .action(ArgAction::Set)) /// .action(ArgAction::Set))
/// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]); /// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]);
/// ///
@ -1424,7 +1422,7 @@ mod tests {
.arg( .arg(
crate::Arg::new("POTATO") crate::Arg::new("POTATO")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.required(true), .required(true),
) )
.try_get_matches_from(["test", "one"]) .try_get_matches_from(["test", "one"])
@ -1441,7 +1439,7 @@ mod tests {
.arg( .arg(
crate::Arg::new("POTATO") crate::Arg::new("POTATO")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.value_parser(crate::builder::ValueParser::os_string()) .value_parser(crate::builder::ValueParser::os_string())
.required(true), .required(true),
) )
@ -1459,7 +1457,7 @@ mod tests {
.arg( .arg(
crate::Arg::new("POTATO") crate::Arg::new("POTATO")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.required(true), .required(true),
) )
.try_get_matches_from(["test", "one"]) .try_get_matches_from(["test", "one"])

View file

@ -1173,7 +1173,7 @@ fn aaos_opts_mult() {
let res = Command::new("posix") let res = Command::new("posix")
.arg( .arg(
arg!(--opt <val> ... "some option") arg!(--opt <val> ... "some option")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![

View file

@ -87,7 +87,7 @@ fn opt_s_no_space_mult_no_delim() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["", "-o", "val1,val2,val3"]); .try_get_matches_from(vec!["", "-o", "val1,val2,val3"]);
@ -108,7 +108,7 @@ fn opt_eq_mult_def_delim() {
Arg::new("option") Arg::new("option")
.long("opt") .long("opt")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true), .use_value_delimiter(true),
) )
.try_get_matches_from(vec!["", "--opt=val1,val2,val3"]); .try_get_matches_from(vec!["", "--opt=val1,val2,val3"]);

View file

@ -230,7 +230,7 @@ fn multiple_one() {
.env("CLP_TEST_ENV_MO") .env("CLP_TEST_ENV_MO")
.action(ArgAction::Set) .action(ArgAction::Set)
.use_value_delimiter(true) .use_value_delimiter(true)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
@ -256,7 +256,7 @@ fn multiple_three() {
.env("CLP_TEST_ENV_MULTI1") .env("CLP_TEST_ENV_MULTI1")
.action(ArgAction::Set) .action(ArgAction::Set)
.use_value_delimiter(true) .use_value_delimiter(true)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
@ -281,7 +281,7 @@ fn multiple_no_delimiter() {
arg!([arg] "some opt") arg!([arg] "some opt")
.env("CLP_TEST_ENV_MULTI2") .env("CLP_TEST_ENV_MULTI2")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);

View file

@ -526,7 +526,7 @@ fn flag_subcommand_long_short_normal_usage_string() {
.help("search locally installed packages for matching strings") .help("search locally installed packages for matching strings")
.conflicts_with("info") .conflicts_with("info")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.arg( .arg(
Arg::new("info") Arg::new("info")
@ -535,7 +535,7 @@ fn flag_subcommand_long_short_normal_usage_string() {
.conflicts_with("search") .conflicts_with("search")
.help("view package information") .help("view package information")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
), ),
); );
utils::assert_output(cmd, "pacman -Qh", FLAG_SUBCOMMAND_HELP, false); 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") .help("search locally installed packages for matching strings")
.conflicts_with("info") .conflicts_with("info")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.arg( .arg(
Arg::new("info") Arg::new("info")
@ -583,7 +583,7 @@ fn flag_subcommand_long_normal_usage_string() {
.conflicts_with("search") .conflicts_with("search")
.help("view package information") .help("view package information")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
), ),
); );
utils::assert_output( utils::assert_output(
@ -627,7 +627,7 @@ fn flag_subcommand_short_normal_usage_string() {
.help("search locally installed packages for matching strings") .help("search locally installed packages for matching strings")
.conflicts_with("info") .conflicts_with("info")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.arg( .arg(
Arg::new("info") Arg::new("info")
@ -636,7 +636,7 @@ fn flag_subcommand_short_normal_usage_string() {
.conflicts_with("search") .conflicts_with("search")
.help("view package information") .help("view package information")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
), ),
); );
utils::assert_output( utils::assert_output(

View file

@ -9,7 +9,7 @@ fn grouped_value_works() {
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(&[ .try_get_matches_from(&[
@ -41,7 +41,7 @@ fn issue_1026() {
Arg::new("target") Arg::new("target")
.long("target") .long("target")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(&[ .try_get_matches_from(&[
@ -69,7 +69,7 @@ fn grouped_value_long_flag_delimiter() {
.long("option") .long("option")
.action(ArgAction::Set) .action(ArgAction::Set)
.use_value_delimiter(true) .use_value_delimiter(true)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
@ -99,7 +99,7 @@ fn grouped_value_short_flag_delimiter() {
.short('o') .short('o')
.action(ArgAction::Set) .action(ArgAction::Set)
.use_value_delimiter(true) .use_value_delimiter(true)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(vec!["myapp", "-o=foo", "-o=val1,val2,val3", "-o=bar"]) .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") Arg::new("pos")
.help("multiple positionals") .help("multiple positionals")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"myprog", "val1", "val2", "val3", "val4", "val5", "val6", "myprog", "val1", "val2", "val3", "val4", "val5", "val6",
@ -139,7 +139,7 @@ fn grouped_value_multiple_positional_arg() {
Arg::new("pos2") Arg::new("pos2")
.help("multiple positionals") .help("multiple positionals")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"myprog", "val1", "val2", "val3", "val4", "val5", "val6", "myprog", "val1", "val2", "val3", "val4", "val5", "val6",
@ -160,7 +160,7 @@ fn grouped_value_multiple_positional_arg_last_multiple() {
Arg::new("pos2") Arg::new("pos2")
.help("multiple positionals") .help("multiple positionals")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.last(true), .last(true),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
@ -177,7 +177,7 @@ fn grouped_value_multiple_positional_arg_last_multiple() {
#[test] #[test]
fn grouped_interleaved_positional_values() { fn grouped_interleaved_positional_values() {
let cmd = clap::Command::new("foo") let cmd = clap::Command::new("foo")
.arg(clap::Arg::new("pos").multiple_values(true)) .arg(clap::Arg::new("pos").number_of_values(1..))
.arg( .arg(
clap::Arg::new("flag") clap::Arg::new("flag")
.short('f') .short('f')
@ -200,7 +200,7 @@ fn grouped_interleaved_positional_values() {
#[test] #[test]
fn grouped_interleaved_positional_occurrences() { fn grouped_interleaved_positional_occurrences() {
let cmd = clap::Command::new("foo") let cmd = clap::Command::new("foo")
.arg(clap::Arg::new("pos").multiple_values(true)) .arg(clap::Arg::new("pos").number_of_values(1..))
.arg( .arg(
clap::Arg::new("flag") clap::Arg::new("flag")
.short('f') .short('f')

View file

@ -133,7 +133,7 @@ fn group_required_flags_empty() {
#[test] #[test]
fn group_multi_value_single_arg() { fn group_multi_value_single_arg() {
let res = Command::new("group") let res = Command::new("group")
.arg(arg!(-c --color <color> "some option").multiple_values(true)) .arg(arg!(-c --color <color> "some option").number_of_values(1..))
.arg(arg!(-h --hostname <name> "another option").required(false)) .arg(arg!(-h --hostname <name> "another option").required(false))
.group(ArgGroup::new("grp").args(&["hostname", "color"])) .group(ArgGroup::new("grp").args(&["hostname", "color"]))
.try_get_matches_from(vec!["", "-c", "blue", "red", "green"]); .try_get_matches_from(vec!["", "-c", "blue", "red", "green"]);

View file

@ -67,7 +67,7 @@ fn help_multi_subcommand_error() {
-o --option <scoption> "tests options" -o --option <scoption> "tests options"
) )
.required(false) .required(false)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
), ),
), ),
@ -107,13 +107,13 @@ OPTIONS:
.arg( .arg(
Arg::new("FIRST") Arg::new("FIRST")
.help("First") .help("First")
.multiple_values(true) .number_of_values(1..)
.required(true), .required(true),
) )
.arg( .arg(
Arg::new("SECOND") Arg::new("SECOND")
.help("Second") .help("Second")
.multiple_values(true) .number_of_values(1..)
.required(true) .required(true)
.last(true), .last(true),
); );
@ -172,7 +172,7 @@ OPTIONS:
Arg::new("pass through args") Arg::new("pass through args")
.help("Any arguments you wish to pass to the being profiled.") .help("Any arguments you wish to pass to the being profiled.")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.last(true) .last(true)
.value_name("ARGS"), .value_name("ARGS"),
); );
@ -342,7 +342,7 @@ fn multi_level_sc_help() {
-o --option <scoption> "tests options" -o --option <scoption> "tests options"
) )
.required(false) .required(false)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
), ),
), ),
@ -981,7 +981,7 @@ OPTIONS:
.arg( .arg(
Arg::new("arg2") Arg::new("arg2")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.help("some option"), .help("some option"),
) )
.arg( .arg(
@ -1003,7 +1003,7 @@ OPTIONS:
.help("a label") .help("a label")
.short('l') .short('l')
.long("label") .long("label")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Set), .action(ArgAction::Set),
); );
utils::assert_output(cmd, "myapp --help", ISSUE_702, false); utils::assert_output(cmd, "myapp --help", ISSUE_702, false);
@ -1043,23 +1043,6 @@ OPTIONS:
utils::assert_output(cmd, "myapp --help", LONG_ABOUT, false); utils::assert_output(cmd, "myapp --help", LONG_ABOUT, false);
} }
#[test]
#[should_panic = "Argument option: mismatch between `number_of_values` (1) and `multiple_values`"]
fn number_of_values_conflicts_with_multiple_values() {
Command::new("ctest")
.version("0.1")
.arg(
Arg::new("option")
.help("tests options")
.short('o')
.long("option")
.action(ArgAction::Set)
.number_of_values(1)
.multiple_values(true),
)
.build();
}
static RIPGREP_USAGE: &str = "ripgrep 0.5 static RIPGREP_USAGE: &str = "ripgrep 0.5
USAGE: USAGE:
@ -1359,7 +1342,7 @@ OPTIONS:
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.last(true) .last(true)
.help("some"), .help("some"),
); );
@ -1390,7 +1373,7 @@ OPTIONS:
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.last(true) .last(true)
.required(true) .required(true)
.help("some"), .help("some"),
@ -1428,7 +1411,7 @@ SUBCOMMANDS:
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.last(true) .last(true)
.required(true) .required(true)
.help("some"), .help("some"),
@ -1467,7 +1450,7 @@ SUBCOMMANDS:
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.last(true) .last(true)
.help("some"), .help("some"),
) )
@ -1882,7 +1865,7 @@ OPTIONS:
Arg::new("files") Arg::new("files")
.value_name("FILES") .value_name("FILES")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
); );
utils::assert_output(cmd, "demo -h", ISSUE_1364, false); utils::assert_output(cmd, "demo -h", ISSUE_1364, false);
@ -2411,7 +2394,7 @@ fn missing_positional_final_multiple() {
.allow_missing_positional(true) .allow_missing_positional(true)
.arg(Arg::new("foo")) .arg(Arg::new("foo"))
.arg(Arg::new("bar")) .arg(Arg::new("bar"))
.arg(Arg::new("baz").action(ArgAction::Set).multiple_values(true)); .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..));
utils::assert_output( utils::assert_output(
cmd, cmd,
"test --help", "test --help",
@ -2438,7 +2421,7 @@ fn positional_multiple_values_is_dotted() {
Arg::new("foo") Arg::new("foo")
.required(true) .required(true)
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
); );
utils::assert_output( utils::assert_output(
cmd, cmd,
@ -2462,7 +2445,7 @@ OPTIONS:
.required(true) .required(true)
.action(ArgAction::Set) .action(ArgAction::Set)
.value_name("BAR") .value_name("BAR")
.multiple_values(true), .number_of_values(1..),
); );
utils::assert_output( utils::assert_output(
cmd, cmd,
@ -2488,7 +2471,7 @@ fn positional_multiple_occurrences_is_dotted() {
Arg::new("foo") Arg::new("foo")
.required(true) .required(true)
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
); );
utils::assert_output( utils::assert_output(
@ -2513,7 +2496,7 @@ OPTIONS:
.required(true) .required(true)
.action(ArgAction::Set) .action(ArgAction::Set)
.value_name("BAR") .value_name("BAR")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
); );
utils::assert_output( utils::assert_output(

View file

@ -7,14 +7,14 @@ fn indices_mult_opts() {
Arg::new("exclude") Arg::new("exclude")
.short('e') .short('e')
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.arg( .arg(
Arg::new("include") Arg::new("include")
.short('i') .short('i')
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]) .try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"])
.unwrap(); .unwrap();
@ -36,14 +36,14 @@ fn index_mult_opts() {
Arg::new("exclude") Arg::new("exclude")
.short('e') .short('e')
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.arg( .arg(
Arg::new("include") Arg::new("include")
.short('i') .short('i')
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]) .try_get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"])
.unwrap(); .unwrap();
@ -136,7 +136,7 @@ fn indices_mult_opt_value_delim_eq() {
.short('o') .short('o')
.action(ArgAction::Set) .action(ArgAction::Set)
.use_value_delimiter(true) .use_value_delimiter(true)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"]) .try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"])
.unwrap(); .unwrap();
@ -153,7 +153,7 @@ fn indices_mult_opt_value_no_delim_eq() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"]) .try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"])
.unwrap(); .unwrap();

View file

@ -30,7 +30,7 @@ fn multiple_occurrences_of_flags_short() {
fn multiple_occurrences_of_positional() { fn multiple_occurrences_of_positional() {
let cmd = Command::new("test").arg( let cmd = Command::new("test").arg(
Arg::new("multi") Arg::new("multi")
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
); );

View file

@ -8,7 +8,7 @@ fn option_long() {
.long("option") .long("option")
.help("multiple options") .help("multiple options")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
@ -36,7 +36,7 @@ fn option_short() {
.short('o') .short('o')
.help("multiple options") .help("multiple options")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]);
@ -63,7 +63,7 @@ fn option_mixed() {
.short('o') .short('o')
.help("multiple options") .help("multiple options")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
@ -448,7 +448,7 @@ fn positional() {
Arg::new("pos") Arg::new("pos")
.help("multiple positionals") .help("multiple positionals")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]); .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
@ -875,14 +875,14 @@ fn req_delimiter_long() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true) .use_value_delimiter(true)
.require_value_delimiter(true), .require_value_delimiter(true),
) )
.arg( .arg(
Arg::new("args") Arg::new("args")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.index(1), .index(1),
) )
.try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]); .try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]);
@ -913,14 +913,14 @@ fn req_delimiter_long_with_equal() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true) .use_value_delimiter(true)
.require_value_delimiter(true), .require_value_delimiter(true),
) )
.arg( .arg(
Arg::new("args") Arg::new("args")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.index(1), .index(1),
) )
.try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]); .try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]);
@ -951,14 +951,14 @@ fn req_delimiter_short_with_space() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true) .use_value_delimiter(true)
.require_value_delimiter(true), .require_value_delimiter(true),
) )
.arg( .arg(
Arg::new("args") Arg::new("args")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.index(1), .index(1),
) )
.try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
@ -989,14 +989,14 @@ fn req_delimiter_short_with_no_space() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true) .use_value_delimiter(true)
.require_value_delimiter(true), .require_value_delimiter(true),
) )
.arg( .arg(
Arg::new("args") Arg::new("args")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.index(1), .index(1),
) )
.try_get_matches_from(vec!["", "-oval1", "val2", "val3"]); .try_get_matches_from(vec!["", "-oval1", "val2", "val3"]);
@ -1027,14 +1027,14 @@ fn req_delimiter_short_with_equal() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true) .use_value_delimiter(true)
.require_value_delimiter(true), .require_value_delimiter(true),
) )
.arg( .arg(
Arg::new("args") Arg::new("args")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.index(1), .index(1),
) )
.try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]); .try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]);
@ -1066,12 +1066,12 @@ fn req_delimiter_complex() {
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.short('o') .short('o')
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append) .action(ArgAction::Append)
.use_value_delimiter(true) .use_value_delimiter(true)
.require_value_delimiter(true), .require_value_delimiter(true),
) )
.arg(Arg::new("args").multiple_values(true).index(1)) .arg(Arg::new("args").number_of_values(1..).index(1))
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "",
"val1", "val1",
@ -1131,7 +1131,7 @@ fn req_delimiter_complex() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
#[test] #[test]
#[should_panic = "When using a positional argument with \ #[should_panic = "When using a positional argument with \
.multiple_values(true) that is *not the last* positional argument, the last \ .number_of_values(1..) that is *not the last* positional argument, the last \
positional argument (i.e. the one with the highest index) *must* have \ positional argument (i.e. the one with the highest index) *must* have \
.required(true) or .last(true) set."] .required(true) or .last(true) set."]
fn low_index_positional_not_required() { fn low_index_positional_not_required() {
@ -1141,7 +1141,7 @@ fn low_index_positional_not_required() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.required(true) .required(true)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("target").index(2)) .arg(Arg::new("target").index(2))
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
@ -1150,7 +1150,7 @@ fn low_index_positional_not_required() {
// This tests a programmer error and will only succeed with debug_assertions // This tests a programmer error and will only succeed with debug_assertions
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
#[test] #[test]
#[should_panic = "Only one positional argument with .multiple_values(true) \ #[should_panic = "Only one positional argument with .number_of_values(1..) \
set is allowed per command, unless the second one also has .last(true) set"] set is allowed per command, unless the second one also has .last(true) set"]
fn low_index_positional_last_multiple_too() { fn low_index_positional_last_multiple_too() {
let _ = Command::new("lip") let _ = Command::new("lip")
@ -1159,14 +1159,14 @@ fn low_index_positional_last_multiple_too() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.required(true) .required(true)
.multiple_values(true), .number_of_values(1..),
) )
.arg( .arg(
Arg::new("target") Arg::new("target")
.index(2) .index(2)
.action(ArgAction::Set) .action(ArgAction::Set)
.required(true) .required(true)
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
} }
@ -1175,7 +1175,7 @@ fn low_index_positional_last_multiple_too() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
#[test] #[test]
#[should_panic = "Only the last positional argument, or second to \ #[should_panic = "Only the last positional argument, or second to \
last positional argument may be set to .multiple_values(true)"] last positional argument may be set to .number_of_values(1..)"]
fn low_index_positional_too_far_back() { fn low_index_positional_too_far_back() {
let _ = Command::new("lip") let _ = Command::new("lip")
.arg( .arg(
@ -1183,7 +1183,7 @@ fn low_index_positional_too_far_back() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.required(true) .required(true)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("target").required(true).index(2)) .arg(Arg::new("target").required(true).index(2))
.arg(Arg::new("target2").required(true).index(3)) .arg(Arg::new("target2").required(true).index(3))
@ -1198,7 +1198,7 @@ fn low_index_positional() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.required(true) .required(true)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("target").index(2).required(true)) .arg(Arg::new("target").index(2).required(true))
.try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target"]); .try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target"]);
@ -1231,7 +1231,7 @@ fn low_index_positional_in_subcmd() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.required(true) .required(true)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("target").index(2).required(true)), .arg(Arg::new("target").index(2).required(true)),
) )
@ -1264,7 +1264,7 @@ fn low_index_positional_with_option() {
.required(true) .required(true)
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("target").index(2).required(true)) .arg(Arg::new("target").index(2).required(true))
.arg(Arg::new("opt").long("option").action(ArgAction::Set)) .arg(Arg::new("opt").long("option").action(ArgAction::Set))
@ -1302,7 +1302,7 @@ fn low_index_positional_with_flag() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.required(true) .required(true)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("target").index(2).required(true)) .arg(Arg::new("target").index(2).required(true))
.arg(Arg::new("flg").long("flag").action(ArgAction::SetTrue)) .arg(Arg::new("flg").long("flag").action(ArgAction::SetTrue))
@ -1333,7 +1333,7 @@ fn low_index_positional_with_extra_flags() {
.arg(Arg::new("yes").long("yes").action(ArgAction::SetTrue)) .arg(Arg::new("yes").long("yes").action(ArgAction::SetTrue))
.arg(Arg::new("one").long("one").action(ArgAction::Set)) .arg(Arg::new("one").long("one").action(ArgAction::Set))
.arg(Arg::new("two").long("two").action(ArgAction::Set)) .arg(Arg::new("two").long("two").action(ArgAction::Set))
.arg(Arg::new("input").multiple_values(true).required(true)) .arg(Arg::new("input").number_of_values(1..).required(true))
.arg(Arg::new("output").required(true)); .arg(Arg::new("output").required(true));
let m = cmd.try_get_matches_from([ let m = cmd.try_get_matches_from([
"test", "--one", "1", "--two", "2", "3", "4", "5", "6", "7", "8", "test", "--one", "1", "--two", "2", "3", "4", "5", "6", "7", "8",
@ -1370,7 +1370,7 @@ fn multiple_value_terminator_option() {
.short('f') .short('f')
.value_terminator(";") .value_terminator(";")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("other")) .arg(Arg::new("other"))
.try_get_matches_from(vec!["lip", "-f", "val1", "val2", ";", "otherval"]); .try_get_matches_from(vec!["lip", "-f", "val1", "val2", ";", "otherval"]);
@ -1401,7 +1401,7 @@ fn multiple_value_terminator_option_other_arg() {
.short('f') .short('f')
.value_terminator(";") .value_terminator(";")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
) )
.arg(Arg::new("other")) .arg(Arg::new("other"))
.arg(Arg::new("flag").short('F').action(ArgAction::SetTrue)) .arg(Arg::new("flag").short('F').action(ArgAction::SetTrue))
@ -1432,7 +1432,7 @@ fn multiple_vals_with_hyphen() {
.arg( .arg(
Arg::new("cmds") Arg::new("cmds")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.allow_hyphen_values(true) .allow_hyphen_values(true)
.value_terminator(";"), .value_terminator(";"),
) )

View file

@ -177,7 +177,7 @@ fn opts_using_short() {
#[test] #[test]
fn lots_o_vals() { fn lots_o_vals() {
let r = Command::new("opts") let r = Command::new("opts")
.arg(arg!(o: -o <opt> "some opt").multiple_values(true)) .arg(arg!(o: -o <opt> "some opt").number_of_values(1..))
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "-o", "some", "some", "some", "some", "some", "some", "some", "some", "some", "", "-o", "some", "some", "some", "some", "some", "some", "some", "some", "some",
"some", "some", "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") let r = Command::new("mvae")
.arg( .arg(
arg!(o: -o <opt> "some opt") arg!(o: -o <opt> "some opt")
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true), .use_value_delimiter(true),
) )
.arg(arg!([file] "some file")) .arg(arg!([file] "some file"))
@ -380,7 +380,7 @@ fn require_delims() {
let r = Command::new("mvae") let r = Command::new("mvae")
.arg( .arg(
arg!(o: -o <opt> "some opt") arg!(o: -o <opt> "some opt")
.multiple_values(true) .number_of_values(1..)
.use_value_delimiter(true) .use_value_delimiter(true)
.require_value_delimiter(true), .require_value_delimiter(true),
) )
@ -408,7 +408,7 @@ fn leading_hyphen_pass() {
let r = Command::new("mvae") let r = Command::new("mvae")
.arg( .arg(
arg!(o: -o <opt> "some opt") arg!(o: -o <opt> "some opt")
.multiple_values(true) .number_of_values(1..)
.allow_hyphen_values(true), .allow_hyphen_values(true),
) )
.try_get_matches_from(vec!["", "-o", "-2", "3"]); .try_get_matches_from(vec!["", "-o", "-2", "3"]);
@ -439,7 +439,7 @@ fn leading_hyphen_with_flag_after() {
let r = Command::new("mvae") let r = Command::new("mvae")
.arg( .arg(
arg!(o: -o <opt> "some opt") arg!(o: -o <opt> "some opt")
.multiple_values(true) .number_of_values(1..)
.allow_hyphen_values(true), .allow_hyphen_values(true),
) )
.arg(arg!(f: -f "some flag").action(ArgAction::SetTrue)) .arg(arg!(f: -f "some flag").action(ArgAction::SetTrue))

View file

@ -121,7 +121,7 @@ fn positional_multiple() {
Arg::new("positional") Arg::new("positional")
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
]) ])
.try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]); .try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]);
assert!(r.is_ok(), "{:#?}", r); assert!(r.is_ok(), "{:#?}", r);
@ -145,7 +145,7 @@ fn positional_multiple_3() {
Arg::new("positional") Arg::new("positional")
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true), .number_of_values(1..),
]) ])
.try_get_matches_from(vec!["", "test1", "test2", "test3", "--flag"]); .try_get_matches_from(vec!["", "test1", "test2", "test3", "--flag"]);
assert!(r.is_ok(), "{:#?}", r); assert!(r.is_ok(), "{:#?}", r);
@ -330,7 +330,7 @@ fn ignore_hyphen_values_on_last() {
let cmd = clap::Command::new("foo") let cmd = clap::Command::new("foo")
.arg( .arg(
clap::Arg::new("cmd") clap::Arg::new("cmd")
.multiple_values(true) .number_of_values(1..)
.last(true) .last(true)
.allow_hyphen_values(true), .allow_hyphen_values(true),
) )

View file

@ -90,7 +90,7 @@ fn possible_values_of_positional_multiple() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.value_parser(["test123", "test321"]) .value_parser(["test123", "test321"])
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["myprog", "test123", "test321"]); .try_get_matches_from(vec!["myprog", "test123", "test321"]);
@ -115,7 +115,7 @@ fn possible_values_of_positional_multiple_fail() {
.index(1) .index(1)
.action(ArgAction::Set) .action(ArgAction::Set)
.value_parser(["test123", "test321"]) .value_parser(["test123", "test321"])
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["myprog", "test123", "notest"]); .try_get_matches_from(vec!["myprog", "test123", "notest"]);
@ -394,7 +394,7 @@ fn ignore_case_multiple() {
.long("option") .long("option")
.action(ArgAction::Set) .action(ArgAction::Set)
.value_parser(["test123", "test321"]) .value_parser(["test123", "test321"])
.multiple_values(true) .number_of_values(1..)
.ignore_case(true), .ignore_case(true),
) )
.try_get_matches_from(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]); .try_get_matches_from(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]);
@ -419,7 +419,7 @@ fn ignore_case_multiple_fail() {
.long("option") .long("option")
.action(ArgAction::Set) .action(ArgAction::Set)
.value_parser(["test123", "test321"]) .value_parser(["test123", "test321"])
.multiple_values(true), .number_of_values(1..),
) )
.try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]); .try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]);

View file

@ -304,7 +304,7 @@ fn issue_1161_multiple_hyphen_hyphen() {
.arg( .arg(
Arg::new("slop") Arg::new("slop")
.action(ArgAction::Set) .action(ArgAction::Set)
.multiple_values(true) .number_of_values(1..)
.last(true), .last(true),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![

View file

@ -49,7 +49,7 @@ pub fn complex_app() -> Command<'static> {
-o --option <opt> "tests options" -o --option <opt> "tests options"
) )
.required(false) .required(false)
.multiple_values(true) .number_of_values(1..)
.action(ArgAction::Append), .action(ArgAction::Append),
) )
.arg(arg!([positional] "tests positionals")) .arg(arg!([positional] "tests positionals"))
@ -100,7 +100,7 @@ pub fn complex_app() -> Command<'static> {
.arg( .arg(
arg!(-o --option <scoption> "tests options") arg!(-o --option <scoption> "tests options")
.required(false) .required(false)
.multiple_values(true), .number_of_values(1..),
) )
.arg(arg!(-s --subcmdarg <subcmdarg> "tests other args").required(false)) .arg(arg!(-s --subcmdarg <subcmdarg> "tests other args").required(false))
.arg(arg!([scpositional] "tests positionals")), .arg(arg!([scpositional] "tests positionals")),

View file

@ -369,7 +369,7 @@ fn vec_type_with_required() {
fn vec_type_with_multiple_values_only() { fn vec_type_with_multiple_values_only() {
#[derive(Parser, PartialEq, Debug)] #[derive(Parser, PartialEq, Debug)]
struct Opt { struct Opt {
#[clap(short, long, multiple_values(true))] #[clap(short, long, number_of_values(1..))]
arg: Vec<i32>, arg: Vec<i32>,
} }
assert_eq!( assert_eq!(
@ -429,7 +429,7 @@ fn option_vec_type() {
fn option_vec_type_structopt_behavior() { fn option_vec_type_structopt_behavior() {
#[derive(Parser, PartialEq, Debug)] #[derive(Parser, PartialEq, Debug)]
struct Opt { struct Opt {
#[clap(short, long, multiple_values(true), number_of_values(0..))] #[clap(short, long, number_of_values(0..))]
arg: Option<Vec<i32>>, arg: Option<Vec<i32>>,
} }
assert_eq!( assert_eq!(