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

View file

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

View file

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

View file

@ -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).multiple_values(true)),
.arg(Arg::new("command").required(true).number_of_values(1..)),
)
.subcommand(
Command::new("which")

View file

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

View file

@ -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").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-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)
.multiple_values(true)
.number_of_values(1..)
.value_hint(clap::ValueHint::CommandWithArguments),
)
.arg(

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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").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-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)
.multiple_values(true)
.number_of_values(1..)
.value_hint(clap::ValueHint::CommandWithArguments),
)
.arg(

View file

@ -267,7 +267,7 @@ pub fn gen_augment(
if attrs.is_positional() {
quote_spanned! { ty.span()=>
.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
#action
}
@ -284,7 +284,7 @@ pub fn gen_augment(
if attrs.is_positional() {
quote_spanned! { ty.span()=>
.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
#action
}

View file

@ -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)
.multiple_values(true)
.number_of_values(1..)
.value_hint(clap::ValueHint::CommandWithArguments),
)
.arg(

View file

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

View file

@ -22,7 +22,7 @@ fn main() {
.help("search locally installed packages for matching strings")
.conflicts_with("info")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
)
.arg(
Arg::new("info")
@ -31,7 +31,7 @@ fn main() {
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
),
)
// Sync subcommand
@ -48,7 +48,7 @@ fn main() {
.long("search")
.conflicts_with("info")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.help("search remote repositories for matching strings"),
)
.arg(
@ -64,7 +64,7 @@ fn main() {
.help("packages")
.required_unless_present("search")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
),
)
.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
/// with [`Arg::short`] or [`Arg::long`].
///
/// **NOTE:** When utilized with [`Arg::multiple_values(true)`], only the **last** positional argument
/// may be defined as multiple (i.e. with the highest index)
/// **NOTE:** When utilized with [`Arg::number_of_values(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::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
/// [`Command`]: crate::Command
#[inline]
@ -808,7 +808,7 @@ impl<'help> Arg<'help> {
/// assert_eq!(m.get_one::<String>("mode").unwrap(), "fast");
/// ```
/// [`Arg::value_delimiter(char)`]: Arg::value_delimiter()
/// [multiple values]: Arg::multiple_values
/// [multiple values]: Arg::number_of_values
#[inline]
#[must_use]
pub fn takes_value(self, yes: bool) -> Self {
@ -905,170 +905,9 @@ impl<'help> Arg<'help> {
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]
#[must_use]
pub fn multiple_values(self, yes: bool) -> Self {
fn multiple_values(self, yes: bool) -> Self {
if yes {
self.setting(ArgSettings::MultipleValues)
} else {
@ -1222,7 +1061,6 @@ impl<'help> Arg<'help> {
/// assert_eq!(m.get_one::<String>("word").unwrap(), "word");
/// ```
/// [`Arg::value_delimiter(char)`]: Arg::value_delimiter()
/// [multiple values]: Arg::multiple_values
#[inline]
#[must_use]
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
/// 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
///
@ -1336,7 +1174,7 @@ impl<'help> Arg<'help> {
/// [`Arg::next_line_help(true)`]: Arg::next_line_help()
/// [`Arg::number_of_values`]: Arg::number_of_values()
/// [`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]
pub fn value_names(mut self, names: &[&'help str]) -> Self {
self.val_names = names.to_vec();
@ -1368,7 +1206,7 @@ impl<'help> Arg<'help> {
/// .arg(
/// Arg::new("command")
/// .action(ArgAction::Set)
/// .multiple_values(true)
/// .number_of_values(1..)
/// .value_hint(ValueHint::CommandWithArguments)
/// );
/// ```
@ -1417,7 +1255,7 @@ impl<'help> Arg<'help> {
/// .long("option")
/// .action(ArgAction::Set)
/// .ignore_case(true)
/// .multiple_values(true)
/// .number_of_values(1..)
/// .value_parser(["test123", "test321"]))
/// .get_matches_from(vec![
/// "pv", "--option", "TeSt123", "teST123", "tESt321"
@ -1441,7 +1279,7 @@ impl<'help> Arg<'help> {
/// **NOTE:** Setting this requires [`Arg::takes_value`]
///
/// **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
/// constitute the normal, "Only positional args follow" idiom.
///
@ -1666,7 +1504,7 @@ impl<'help> Arg<'help> {
/// .action(ArgAction::Set)
/// .use_value_delimiter(true)
/// .require_value_delimiter(true)
/// .multiple_values(true))
/// .number_of_values(1..))
/// .get_matches_from(vec![
/// "prog", "-o", "val1,val2,val3",
/// ]);
@ -1707,7 +1545,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("opt")
/// .short('o')
/// .action(ArgAction::Set)
/// .multiple_values(true))
/// .number_of_values(1..))
/// .get_matches_from(vec![
/// "prog", "-o", "val1", "val2", "val3",
/// ]);
@ -1728,7 +1566,7 @@ impl<'help> Arg<'help> {
/// Sentinel to **stop** parsing multiple values of a given argument.
///
/// 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
/// for multiple values is used (such as [`number_of_values`]).
///
@ -1743,7 +1581,7 @@ impl<'help> Arg<'help> {
/// # use clap::{Command, Arg, ArgAction};
/// Arg::new("vals")
/// .action(ArgAction::Set)
/// .multiple_values(true)
/// .number_of_values(1..)
/// .value_terminator(";")
/// # ;
/// ```
@ -1756,7 +1594,7 @@ impl<'help> Arg<'help> {
/// let m = Command::new("prog")
/// .arg(Arg::new("cmds")
/// .action(ArgAction::Set)
/// .multiple_values(true)
/// .number_of_values(1..)
/// .allow_hyphen_values(true)
/// .value_terminator(";"))
/// .arg(Arg::new("location"))
@ -1769,7 +1607,7 @@ impl<'help> Arg<'help> {
/// ```
/// [options]: Arg::takes_value()
/// [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()
#[inline]
#[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 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::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::last(true)`]: Arg::last()
#[inline]
@ -2170,7 +2008,7 @@ impl<'help> Arg<'help> {
/// .long("flag")
/// .env("MY_FLAG_MULTI")
/// .action(ArgAction::Set)
/// .multiple_values(true)
/// .number_of_values(1..)
/// .use_value_delimiter(true))
/// .get_matches_from(vec![
/// "prog"
@ -4131,7 +3969,7 @@ impl<'help> Arg<'help> {
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 {
self.is_set(ArgSettings::MultipleValues)
}
@ -4659,7 +4497,7 @@ mod test {
let mut o = Arg::new("opt")
.long("option")
.action(ArgAction::Set)
.multiple_values(true);
.number_of_values(1..);
o._build();
assert_eq!(o.to_string(), "--option <opt>...");
@ -4737,12 +4575,12 @@ mod test {
fn option_display3() {
let mut o = Arg::new("opt")
.short('o')
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Set)
.value_names(&["file", "name"]);
o._build();
assert_eq!(o.to_string(), "-o <file> <name>");
assert_eq!(o.to_string(), "-o <file> <name>...");
}
#[test]
@ -4795,7 +4633,7 @@ mod test {
#[test]
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();
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.
///
/// **NOTE:** The final positional argument **must** have [`Arg::multiple_values(true)`] or the usage
/// string equivalent.
/// **NOTE:** The final positional argument **must** have [`Arg::number_of_values(..)`].
///
/// # Examples
///
@ -2031,7 +2030,7 @@ impl<'help> Command<'help> {
/// let trail: Vec<_> = m.get_many::<String>("cmd").unwrap().collect();
/// 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 {
if yes {
self.setting(AppSettings::TrailingVarArg)
@ -2117,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).multiple_values(true))
/// .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..))
/// .get_matches_from(vec![
/// "prog", "foo", "bar", "baz1", "baz2", "baz3"
/// ]);
@ -2136,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).multiple_values(true))
/// .arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..))
/// .get_matches_from(vec![
/// "prog", "--", "baz1", "baz2", "baz3"
/// ]);
@ -2832,7 +2831,7 @@ impl<'help> Command<'help> {
/// let cmd = Command::new("cmd").subcommand(Command::new("sub")).arg(
/// Arg::new("arg")
/// .long("arg")
/// .multiple_values(true)
/// .number_of_values(1..)
/// .action(ArgAction::Set),
/// );
///
@ -4255,7 +4254,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.",
Arg::new("subcommand")
.index(1)
.action(ArgAction::Append)
.multiple_values(true)
.number_of_values(..)
.value_name("SUBCOMMAND")
.help("The subcommand whose help message to display"),
);

View file

@ -131,7 +131,7 @@ pub(crate) fn assert_app(cmd: &Command) {
panic!(
"Command {}: Argument '{}' has the same index as '{}' \
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",
cmd.get_name(),
first.name,
@ -517,7 +517,7 @@ fn _verify_positionals(cmd: &Command) -> bool {
|| last.is_last_set();
assert!(
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 \
with the highest index) *must* have .required(true) or .last(true) set."
);
@ -527,7 +527,7 @@ fn _verify_positionals(cmd: &Command) -> bool {
assert!(
ok,
"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
@ -544,7 +544,7 @@ fn _verify_positionals(cmd: &Command) -> bool {
&& count == 2);
assert!(
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"
);
}

View file

@ -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
/// [`.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
/// parse the `-la` argument itself.
///
/// [`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,
/// Name of a local operating system user.
Username,

View file

@ -412,7 +412,7 @@ macro_rules! arg_impl {
@arg
({
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
.action($crate::ArgAction::Append)
} else if $arg.is_takes_value_set() {

View file

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

View file

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

View file

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

View file

@ -230,7 +230,7 @@ fn multiple_one() {
.env("CLP_TEST_ENV_MO")
.action(ArgAction::Set)
.use_value_delimiter(true)
.multiple_values(true),
.number_of_values(1..),
)
.try_get_matches_from(vec![""]);
@ -256,7 +256,7 @@ fn multiple_three() {
.env("CLP_TEST_ENV_MULTI1")
.action(ArgAction::Set)
.use_value_delimiter(true)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(1..),
)
.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")
.conflicts_with("info")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(1..),
),
);
utils::assert_output(

View file

@ -9,7 +9,7 @@ fn grouped_value_works() {
Arg::new("option")
.long("option")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
)
.try_get_matches_from(&[
@ -41,7 +41,7 @@ fn issue_1026() {
Arg::new("target")
.long("target")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
)
.try_get_matches_from(&[
@ -69,7 +69,7 @@ fn grouped_value_long_flag_delimiter() {
.long("option")
.action(ArgAction::Set)
.use_value_delimiter(true)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
)
.try_get_matches_from(vec![
@ -99,7 +99,7 @@ fn grouped_value_short_flag_delimiter() {
.short('o')
.action(ArgAction::Set)
.use_value_delimiter(true)
.multiple_values(true)
.number_of_values(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)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true)
.number_of_values(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").multiple_values(true))
.arg(clap::Arg::new("pos").number_of_values(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").multiple_values(true))
.arg(clap::Arg::new("pos").number_of_values(1..))
.arg(
clap::Arg::new("flag")
.short('f')

View file

@ -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").multiple_values(true))
.arg(arg!(-c --color <color> "some option").number_of_values(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"]);

View file

@ -67,7 +67,7 @@ fn help_multi_subcommand_error() {
-o --option <scoption> "tests options"
)
.required(false)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
),
),
@ -107,13 +107,13 @@ OPTIONS:
.arg(
Arg::new("FIRST")
.help("First")
.multiple_values(true)
.number_of_values(1..)
.required(true),
)
.arg(
Arg::new("SECOND")
.help("Second")
.multiple_values(true)
.number_of_values(1..)
.required(true)
.last(true),
);
@ -172,7 +172,7 @@ OPTIONS:
Arg::new("pass through args")
.help("Any arguments you wish to pass to the being profiled.")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.last(true)
.value_name("ARGS"),
);
@ -342,7 +342,7 @@ fn multi_level_sc_help() {
-o --option <scoption> "tests options"
)
.required(false)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
),
),
@ -981,7 +981,7 @@ OPTIONS:
.arg(
Arg::new("arg2")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.help("some option"),
)
.arg(
@ -1003,7 +1003,7 @@ OPTIONS:
.help("a label")
.short('l')
.long("label")
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Set),
);
utils::assert_output(cmd, "myapp --help", ISSUE_702, false);
@ -1043,23 +1043,6 @@ OPTIONS:
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
USAGE:
@ -1359,7 +1342,7 @@ OPTIONS:
.arg(
Arg::new("ARGS")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.last(true)
.help("some"),
);
@ -1390,7 +1373,7 @@ OPTIONS:
.arg(
Arg::new("ARGS")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.last(true)
.required(true)
.help("some"),
@ -1428,7 +1411,7 @@ SUBCOMMANDS:
.arg(
Arg::new("ARGS")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.last(true)
.required(true)
.help("some"),
@ -1467,7 +1450,7 @@ SUBCOMMANDS:
.arg(
Arg::new("ARGS")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.last(true)
.help("some"),
)
@ -1882,7 +1865,7 @@ OPTIONS:
Arg::new("files")
.value_name("FILES")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
);
utils::assert_output(cmd, "demo -h", ISSUE_1364, false);
@ -2411,7 +2394,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).multiple_values(true));
.arg(Arg::new("baz").action(ArgAction::Set).number_of_values(1..));
utils::assert_output(
cmd,
"test --help",
@ -2438,7 +2421,7 @@ fn positional_multiple_values_is_dotted() {
Arg::new("foo")
.required(true)
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
);
utils::assert_output(
cmd,
@ -2462,7 +2445,7 @@ OPTIONS:
.required(true)
.action(ArgAction::Set)
.value_name("BAR")
.multiple_values(true),
.number_of_values(1..),
);
utils::assert_output(
cmd,
@ -2488,7 +2471,7 @@ fn positional_multiple_occurrences_is_dotted() {
Arg::new("foo")
.required(true)
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
);
utils::assert_output(
@ -2513,7 +2496,7 @@ OPTIONS:
.required(true)
.action(ArgAction::Set)
.value_name("BAR")
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
);
utils::assert_output(

View file

@ -7,14 +7,14 @@ fn indices_mult_opts() {
Arg::new("exclude")
.short('e')
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
)
.arg(
Arg::new("include")
.short('i')
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
)
.arg(
Arg::new("include")
.short('i')
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(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)
.use_value_delimiter(true)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(1..),
)
.try_get_matches_from(vec!["myapp", "-o=val1,val2,val3"])
.unwrap();

View file

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

View file

@ -8,7 +8,7 @@ fn option_long() {
.long("option")
.help("multiple options")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
)
.try_get_matches_from(vec![
@ -36,7 +36,7 @@ fn option_short() {
.short('o')
.help("multiple options")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(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)
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append),
)
.try_get_matches_from(vec![
@ -448,7 +448,7 @@ fn positional() {
Arg::new("pos")
.help("multiple positionals")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
)
.try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
@ -875,14 +875,14 @@ fn req_delimiter_long() {
.arg(
Arg::new("option")
.long("option")
.multiple_values(true)
.number_of_values(1..)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.arg(
Arg::new("args")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.index(1),
)
.try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]);
@ -913,14 +913,14 @@ fn req_delimiter_long_with_equal() {
.arg(
Arg::new("option")
.long("option")
.multiple_values(true)
.number_of_values(1..)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.arg(
Arg::new("args")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.index(1),
)
.try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]);
@ -951,14 +951,14 @@ fn req_delimiter_short_with_space() {
.arg(
Arg::new("option")
.short('o')
.multiple_values(true)
.number_of_values(1..)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.arg(
Arg::new("args")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.index(1),
)
.try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
@ -989,14 +989,14 @@ fn req_delimiter_short_with_no_space() {
.arg(
Arg::new("option")
.short('o')
.multiple_values(true)
.number_of_values(1..)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.arg(
Arg::new("args")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.index(1),
)
.try_get_matches_from(vec!["", "-oval1", "val2", "val3"]);
@ -1027,14 +1027,14 @@ fn req_delimiter_short_with_equal() {
.arg(
Arg::new("option")
.short('o')
.multiple_values(true)
.number_of_values(1..)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
.arg(
Arg::new("args")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.index(1),
)
.try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]);
@ -1066,12 +1066,12 @@ fn req_delimiter_complex() {
Arg::new("option")
.long("option")
.short('o')
.multiple_values(true)
.number_of_values(1..)
.action(ArgAction::Append)
.use_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![
"",
"val1",
@ -1131,7 +1131,7 @@ fn req_delimiter_complex() {
#[cfg(debug_assertions)]
#[test]
#[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 \
.required(true) or .last(true) set."]
fn low_index_positional_not_required() {
@ -1141,7 +1141,7 @@ fn low_index_positional_not_required() {
.index(1)
.action(ArgAction::Set)
.required(true)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("target").index(2))
.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
#[cfg(debug_assertions)]
#[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"]
fn low_index_positional_last_multiple_too() {
let _ = Command::new("lip")
@ -1159,14 +1159,14 @@ fn low_index_positional_last_multiple_too() {
.index(1)
.action(ArgAction::Set)
.required(true)
.multiple_values(true),
.number_of_values(1..),
)
.arg(
Arg::new("target")
.index(2)
.action(ArgAction::Set)
.required(true)
.multiple_values(true),
.number_of_values(1..),
)
.try_get_matches_from(vec![""]);
}
@ -1175,7 +1175,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 .multiple_values(true)"]
last positional argument may be set to .number_of_values(1..)"]
fn low_index_positional_too_far_back() {
let _ = Command::new("lip")
.arg(
@ -1183,7 +1183,7 @@ fn low_index_positional_too_far_back() {
.index(1)
.action(ArgAction::Set)
.required(true)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("target").required(true).index(2))
.arg(Arg::new("target2").required(true).index(3))
@ -1198,7 +1198,7 @@ fn low_index_positional() {
.index(1)
.action(ArgAction::Set)
.required(true)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("target").index(2).required(true))
.try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target"]);
@ -1231,7 +1231,7 @@ fn low_index_positional_in_subcmd() {
.index(1)
.action(ArgAction::Set)
.required(true)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("target").index(2).required(true)),
)
@ -1264,7 +1264,7 @@ fn low_index_positional_with_option() {
.required(true)
.index(1)
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("target").index(2).required(true))
.arg(Arg::new("opt").long("option").action(ArgAction::Set))
@ -1302,7 +1302,7 @@ fn low_index_positional_with_flag() {
.index(1)
.action(ArgAction::Set)
.required(true)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("target").index(2).required(true))
.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("one").long("one").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));
let m = cmd.try_get_matches_from([
"test", "--one", "1", "--two", "2", "3", "4", "5", "6", "7", "8",
@ -1370,7 +1370,7 @@ fn multiple_value_terminator_option() {
.short('f')
.value_terminator(";")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("other"))
.try_get_matches_from(vec!["lip", "-f", "val1", "val2", ";", "otherval"]);
@ -1401,7 +1401,7 @@ fn multiple_value_terminator_option_other_arg() {
.short('f')
.value_terminator(";")
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(1..),
)
.arg(Arg::new("other"))
.arg(Arg::new("flag").short('F').action(ArgAction::SetTrue))
@ -1432,7 +1432,7 @@ fn multiple_vals_with_hyphen() {
.arg(
Arg::new("cmds")
.action(ArgAction::Set)
.multiple_values(true)
.number_of_values(1..)
.allow_hyphen_values(true)
.value_terminator(";"),
)

View file

@ -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").multiple_values(true))
.arg(arg!(o: -o <opt> "some opt").number_of_values(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")
.multiple_values(true)
.number_of_values(1..)
.use_value_delimiter(true),
)
.arg(arg!([file] "some file"))
@ -380,7 +380,7 @@ fn require_delims() {
let r = Command::new("mvae")
.arg(
arg!(o: -o <opt> "some opt")
.multiple_values(true)
.number_of_values(1..)
.use_value_delimiter(true)
.require_value_delimiter(true),
)
@ -408,7 +408,7 @@ fn leading_hyphen_pass() {
let r = Command::new("mvae")
.arg(
arg!(o: -o <opt> "some opt")
.multiple_values(true)
.number_of_values(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")
.multiple_values(true)
.number_of_values(1..)
.allow_hyphen_values(true),
)
.arg(arg!(f: -f "some flag").action(ArgAction::SetTrue))

View file

@ -121,7 +121,7 @@ fn positional_multiple() {
Arg::new("positional")
.index(1)
.action(ArgAction::Set)
.multiple_values(true),
.number_of_values(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)
.multiple_values(true),
.number_of_values(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")
.multiple_values(true)
.number_of_values(1..)
.last(true)
.allow_hyphen_values(true),
)

View file

@ -90,7 +90,7 @@ fn possible_values_of_positional_multiple() {
.index(1)
.action(ArgAction::Set)
.value_parser(["test123", "test321"])
.multiple_values(true),
.number_of_values(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"])
.multiple_values(true),
.number_of_values(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"])
.multiple_values(true)
.number_of_values(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"])
.multiple_values(true),
.number_of_values(1..),
)
.try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]);

View file

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

View file

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

View file

@ -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, multiple_values(true))]
#[clap(short, long, number_of_values(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, multiple_values(true), number_of_values(0..))]
#[clap(short, long, number_of_values(0..))]
arg: Option<Vec<i32>>,
}
assert_eq!(