Removed Arg::multiple

This commit is contained in:
Pavan Kumar Sunkara 2021-06-16 06:28:25 +01:00
parent 43909ddefc
commit 3f94d17c71
31 changed files with 465 additions and 480 deletions

View file

@ -15,6 +15,7 @@ TODO: `cargo`, `std` features
* **Removed Methods** * **Removed Methods**
* **Arg** * **Arg**
* `Arg::settings` in favor of `Arg::setting(Setting1 | Setting2)` * `Arg::settings` in favor of `Arg::setting(Setting1 | Setting2)`
* `Arg::multiple` in favour of `Arg::multiple_values` and `Arg::multiple_occurrences`
* **Renamed Settings** * **Renamed Settings**
* `AppSettings::DisableHelpFlags` => `AppSettings::DisableHelpFlag` * `AppSettings::DisableHelpFlags` => `AppSettings::DisableHelpFlag`
* `AppSettings::DisableVersion` => `AppSettings::DisableVersionFlag` * `AppSettings::DisableVersion` => `AppSettings::DisableVersionFlag`

View file

@ -231,7 +231,7 @@ fn main() {
.index(1)) .index(1))
.arg(Arg::new("v") .arg(Arg::new("v")
.short('v') .short('v')
.multiple(true) .multiple_occurrences(true)
.takes_value(true) .takes_value(true)
.about("Sets the level of verbosity")) .about("Sets the level of verbosity"))
.subcommand(App::new("test") .subcommand(App::new("test")

View file

@ -291,7 +291,7 @@ pub fn gen_app_augmentation(
Ty::OptionOption => quote_spanned! { ty.span()=> Ty::OptionOption => quote_spanned! { ty.span()=>
.takes_value(true) .takes_value(true)
.multiple(false) .multiple_values(false)
.min_values(0) .min_values(0)
.max_values(1) .max_values(1)
#validator #validator
@ -299,7 +299,7 @@ pub fn gen_app_augmentation(
Ty::OptionVec => quote_spanned! { ty.span()=> Ty::OptionVec => quote_spanned! { ty.span()=>
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.min_values(0) .min_values(0)
#validator #validator
}, },
@ -315,7 +315,7 @@ pub fn gen_app_augmentation(
quote_spanned! { ty.span()=> quote_spanned! { ty.span()=>
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
#possible_values #possible_values
#validator #validator
} }
@ -327,7 +327,7 @@ pub fn gen_app_augmentation(
Ty::Other if flag => quote_spanned! { ty.span()=> Ty::Other if flag => quote_spanned! { ty.span()=>
.takes_value(false) .takes_value(false)
.multiple(false) .multiple_values(false)
}, },
Ty::Other => { Ty::Other => {

View file

@ -25,7 +25,7 @@ fn basic() {
assert_eq!(Opt { arg: vec![] }, Opt::parse_from(&["test"])); assert_eq!(Opt { arg: vec![] }, Opt::parse_from(&["test"]));
assert_eq!( assert_eq!(
Opt { arg: vec![24, 42] }, Opt { arg: vec![24, 42] },
Opt::parse_from(&["test", "-a24", "--arg", "42"]) Opt::parse_from(&["test", "--arg", "24", "42"])
); );
} }

View file

@ -26,7 +26,7 @@ struct PathOpt {
#[clap(short, default_value = "../", parse(from_os_str))] #[clap(short, default_value = "../", parse(from_os_str))]
default_path: PathBuf, default_path: PathBuf,
#[clap(short, parse(from_os_str))] #[clap(short, parse(from_os_str), multiple_occurrences(true))]
vector_path: Vec<PathBuf>, vector_path: Vec<PathBuf>,
#[clap(short, parse(from_os_str))] #[clap(short, parse(from_os_str))]
@ -254,7 +254,7 @@ fn test_custom_bool() {
verbose: bool, verbose: bool,
#[clap(short, parse(try_from_str = parse_bool))] #[clap(short, parse(try_from_str = parse_bool))]
tribool: Option<bool>, tribool: Option<bool>,
#[clap(short, parse(try_from_str = parse_bool))] #[clap(short, parse(try_from_str = parse_bool), multiple_occurrences(true))]
bitset: Vec<bool>, bitset: Vec<bool>,
} }

View file

@ -7,7 +7,7 @@ use utils::*;
fn explicit_short_long_no_rename() { fn explicit_short_long_no_rename() {
#[derive(Clap, PartialEq, Debug)] #[derive(Clap, PartialEq, Debug)]
struct Opt { struct Opt {
#[clap(short = '.', long = ".foo")] #[clap(short = '.', long = ".foo", multiple_occurrences(true))]
foo: Vec<String>, foo: Vec<String>,
} }

View file

@ -70,7 +70,7 @@ fn option_with_raw_default() {
fn options() { fn options() {
#[derive(Clap, PartialEq, Debug)] #[derive(Clap, PartialEq, Debug)]
struct Opt { struct Opt {
#[clap(short, long)] #[clap(short, long, multiple_occurrences(true))]
arg: Vec<i32>, arg: Vec<i32>,
} }
assert_eq!(Opt { arg: vec![24] }, Opt::parse_from(&["test", "-a24"])); assert_eq!(Opt { arg: vec![24] }, Opt::parse_from(&["test", "-a24"]));
@ -120,7 +120,7 @@ fn option_from_str() {
fn optional_argument_for_optional_option() { fn optional_argument_for_optional_option() {
#[derive(Clap, PartialEq, Debug)] #[derive(Clap, PartialEq, Debug)]
struct Opt { struct Opt {
#[clap(short)] #[clap(short, multiple_occurrences(true))]
#[allow(clippy::option_option)] #[allow(clippy::option_option)]
arg: Option<Option<i32>>, arg: Option<Option<i32>>,
} }
@ -193,7 +193,7 @@ fn two_option_options() {
fn optional_vec() { fn optional_vec() {
#[derive(Clap, PartialEq, Debug)] #[derive(Clap, PartialEq, Debug)]
struct Opt { struct Opt {
#[clap(short)] #[clap(short, multiple_occurrences(true))]
arg: Option<Vec<i32>>, arg: Option<Vec<i32>>,
} }
assert_eq!( assert_eq!(
@ -250,10 +250,10 @@ fn optional_vec() {
fn two_optional_vecs() { fn two_optional_vecs() {
#[derive(Clap, PartialEq, Debug)] #[derive(Clap, PartialEq, Debug)]
struct Opt { struct Opt {
#[clap(short)] #[clap(short, multiple_occurrences(true))]
arg: Option<Vec<i32>>, arg: Option<Vec<i32>>,
#[clap(short)] #[clap(short, multiple_occurrences(true))]
b: Option<Vec<i32>>, b: Option<Vec<i32>>,
} }

View file

@ -4,7 +4,7 @@ use clap::Clap;
fn raw_idents() { fn raw_idents() {
#[derive(Clap, Debug, PartialEq)] #[derive(Clap, Debug, PartialEq)]
struct Opt { struct Opt {
#[clap(short, long)] #[clap(short, long, multiple_occurrences(true))]
r#type: Vec<String>, r#type: Vec<String>,
} }

View file

@ -18,8 +18,7 @@ fn main() {
.about("turns up the awesome") // Displayed when showing help info .about("turns up the awesome") // Displayed when showing help info
.short('a') // Trigger this arg with "-a" .short('a') // Trigger this arg with "-a"
.long("awesome") // Trigger this arg with "--awesome" .long("awesome") // Trigger this arg with "--awesome"
.takes_value(true) .multiple_occurrences(true) // This flag should allow multiple
.multiple(true) // This flag should allow multiple
// occurrences such as "-aaa" or "-a -a" // occurrences such as "-aaa" or "-a -a"
.requires("config") // Says, "If the user uses -a, they MUST .requires("config") // Says, "If the user uses -a, they MUST
// also use this other 'config' arg too" // also use this other 'config' arg too"
@ -39,9 +38,9 @@ fn main() {
println!("Awesomeness is turned on"); println!("Awesomeness is turned on");
} }
// If we set the multiple() option of a flag we can check how many times the user specified // If we set the multiple option of a flag we can check how many times the user specified
// //
// Note: if we did not specify the multiple() option, and the user used "awesome" we would get // Note: if we did not specify the multiple option, and the user used "awesome" we would get
// a 1 (no matter how many times they actually used it), or a 0 if they didn't use it at all // a 1 (no matter how many times they actually used it), or a 0 if they didn't use it at all
match matches.occurrences_of("awesome") { match matches.occurrences_of("awesome") {
0 => println!("Nothing is awesome"), 0 => println!("Nothing is awesome"),

View file

@ -19,7 +19,7 @@ fn main() {
.takes_value(true) // MUST be set to true in order to be an "option" argument .takes_value(true) // MUST be set to true in order to be an "option" argument
.short('i') // This argument is triggered with "-i" .short('i') // This argument is triggered with "-i"
.long("input") // This argument is triggered with "--input" .long("input") // This argument is triggered with "--input"
.multiple(true) // Set to true if you wish to allow multiple occurrences .multiple_occurrences(true) // Set to true if you wish to allow multiple occurrences
// such as "-i file -i other_file -i third_file" // such as "-i file -i other_file -i third_file"
.required(true) // By default this argument MUST be present .required(true) // By default this argument MUST be present
// NOTE: mutual exclusions take precedence over // NOTE: mutual exclusions take precedence over
@ -44,13 +44,13 @@ fn main() {
// We can also get the value for "input" // We can also get the value for "input"
// //
// NOTE: If we specified multiple(), this will only return the _FIRST_ // NOTE: If we specified multiple_occurrences(), this will only return the _FIRST_
// occurrence // occurrence
if let Some(ref in_file) = matches.value_of("input") { if let Some(ref in_file) = matches.value_of("input") {
println!("An input file: {}", in_file); println!("An input file: {}", in_file);
} }
// If we specified the multiple() setting we can get all the values // If we specified the multiple_occurrences() setting we can get all the values
if let Some(in_v) = matches.values_of("input") { if let Some(in_v) = matches.values_of("input") {
for in_file in in_v { for in_file in in_v {
println!("An input file: {}", in_file); println!("An input file: {}", in_file);
@ -59,7 +59,7 @@ fn main() {
// We can see how many times the option was used with the occurrences_of() method // We can see how many times the option was used with the occurrences_of() method
// //
// NOTE: Just like with flags, if we did not specify the multiple() setting this will only // NOTE: Just like with flags, if we did not specify the multiple_occurrences() setting this will only
// return 1 no matter how many times the argument was used (unless it wasn't used at all, in // return 1 no matter how many times the argument was used (unless it wasn't used at all, in
// in which case 0 is returned) // in which case 0 is returned)
println!( println!(

View file

@ -79,7 +79,7 @@ fn main() {
.long("stuff") .long("stuff")
.about("Stuff to add") .about("Stuff to add")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
), ),
) )
.get_matches(); .get_matches();

View file

@ -5,7 +5,12 @@ fn main() {
let matches = App::new("myprog") let matches = App::new("myprog")
.arg(Arg::new("eff").short('f')) .arg(Arg::new("eff").short('f'))
.arg(Arg::new("pea").short('p').takes_value(true)) .arg(Arg::new("pea").short('p').takes_value(true))
.arg(Arg::new("slop").takes_value(true).multiple(true).last(true)) .arg(
Arg::new("slop")
.takes_value(true)
.multiple_values(true)
.last(true),
)
.get_matches(); .get_matches();
println!("-f used: {:?}", matches.is_present("eff")); println!("-f used: {:?}", matches.is_present("eff"));

View file

@ -80,9 +80,9 @@ fn main() {
.arg( .arg(
Arg::new("package") Arg::new("package")
.about("packages") .about("packages")
.multiple(true)
.required_unless_present("search") .required_unless_present("search")
.takes_value(true), .takes_value(true)
.multiple_values(true),
), ),
) )
.get_matches(); .get_matches();

View file

@ -338,7 +338,7 @@ pub enum AppSettings {
/// .setting(AppSettings::AllowMissingPositional) /// .setting(AppSettings::AllowMissingPositional)
/// .arg(Arg::new("foo")) /// .arg(Arg::new("foo"))
/// .arg(Arg::new("bar")) /// .arg(Arg::new("bar"))
/// .arg(Arg::new("baz").takes_value(true).multiple(true)) /// .arg(Arg::new("baz").takes_value(true).multiple_values(true))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog", "foo", "bar", "baz1", "baz2", "baz3" /// "prog", "foo", "bar", "baz1", "baz2", "baz3"
/// ]); /// ]);
@ -357,7 +357,7 @@ pub enum AppSettings {
/// .setting(AppSettings::AllowMissingPositional) /// .setting(AppSettings::AllowMissingPositional)
/// .arg(Arg::new("foo")) /// .arg(Arg::new("foo"))
/// .arg(Arg::new("bar")) /// .arg(Arg::new("bar"))
/// .arg(Arg::new("baz").takes_value(true).multiple(true)) /// .arg(Arg::new("baz").takes_value(true).multiple_values(true))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog", "--", "baz1", "baz2", "baz3" /// "prog", "--", "baz1", "baz2", "baz3"
/// ]); /// ]);
@ -476,7 +476,7 @@ pub enum AppSettings {
/// let app = App::new("app").subcommand(App::new("sub")).arg( /// let app = App::new("app").subcommand(App::new("sub")).arg(
/// Arg::new("arg") /// Arg::new("arg")
/// .long("arg") /// .long("arg")
/// .multiple(true) /// .multiple_values(true)
/// .takes_value(true), /// .takes_value(true),
/// ); /// );
/// ///
@ -994,7 +994,7 @@ pub enum AppSettings {
/// ///
/// 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(true)`] or the usage /// **NOTE:** The final positional argument **must** have [`Arg::multiple_values(true)`] or the usage
/// string equivalent. /// string equivalent.
/// ///
/// # Examples /// # Examples
@ -1009,7 +1009,7 @@ pub enum AppSettings {
/// let trail: Vec<&str> = m.values_of("cmd").unwrap().collect(); /// let trail: Vec<&str> = m.values_of("cmd").unwrap().collect();
/// assert_eq!(trail, ["arg1", "-r", "val1"]); /// assert_eq!(trail, ["arg1", "-r", "val1"]);
/// ``` /// ```
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_values(true)`]: Arg::multiple_values()
TrailingVarArg, TrailingVarArg,
/// Groups flags and options together, presenting a more unified help message /// Groups flags and options together, presenting a more unified help message

View file

@ -1749,7 +1749,7 @@ impl<'help> Arg<'help> {
/// assigned in order of evaluation. Utilizing the `index` method allows for setting /// assigned in order of evaluation. Utilizing the `index` method allows for setting
/// indexes out of order /// indexes out of order
/// ///
/// **NOTE:** When utilized with [`Arg::multiple(true)`], only the **last** positional argument /// **NOTE:** When utilized with [`Arg::multiple_values(true)`], only the **last** positional argument
/// may be defined as multiple (i.e. with the highest index) /// may be defined as multiple (i.e. with the highest index)
/// ///
/// # Panics /// # Panics
@ -1784,7 +1784,7 @@ impl<'help> Arg<'help> {
/// ``` /// ```
/// [`Arg::short`]: Arg::short() /// [`Arg::short`]: Arg::short()
/// [`Arg::long`]: Arg::long() /// [`Arg::long`]: Arg::long()
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_values(true)`]: Arg::multiple_values()
/// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html /// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html
#[inline] #[inline]
pub fn index(mut self, idx: usize) -> Self { pub fn index(mut self, idx: usize) -> Self {
@ -1793,7 +1793,7 @@ impl<'help> Arg<'help> {
} }
/// Specifies a value that *stops* parsing multiple values of a give argument. By default when /// Specifies a value that *stops* parsing multiple values of a give argument. By default when
/// one sets [`multiple(true)`] on an argument, clap will continue parsing values for that /// one sets [`multiple_values(true)`] 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 [`min_values`], [`max_values`] or /// for multiple values is used (such as [`min_values`], [`max_values`] or
/// [`number_of_values`]). /// [`number_of_values`]).
@ -1809,10 +1809,11 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg}; /// # use clap::{App, Arg};
/// Arg::new("vals") /// Arg::new("vals")
/// .takes_value(true) /// .takes_value(true)
/// .multiple(true) /// .multiple_values(true)
/// .value_terminator(";") /// .value_terminator(";")
/// # ; /// # ;
/// ``` /// ```
///
/// The following example uses two arguments, a sequence of commands, and the location in which /// The following example uses two arguments, a sequence of commands, and the location in which
/// to perform them /// to perform them
/// ///
@ -1821,7 +1822,7 @@ impl<'help> Arg<'help> {
/// let m = App::new("prog") /// let m = App::new("prog")
/// .arg(Arg::new("cmds") /// .arg(Arg::new("cmds")
/// .takes_value(true) /// .takes_value(true)
/// .multiple(true) /// .multiple_values(true)
/// .allow_hyphen_values(true) /// .allow_hyphen_values(true)
/// .value_terminator(";")) /// .value_terminator(";"))
/// .arg(Arg::new("location")) /// .arg(Arg::new("location"))
@ -1834,7 +1835,7 @@ impl<'help> Arg<'help> {
/// ``` /// ```
/// [options]: Arg::takes_value() /// [options]: Arg::takes_value()
/// [positional arguments]: Arg::index() /// [positional arguments]: Arg::index()
/// [`multiple(true)`]: Arg::multiple() /// [`multiple_values(true)`]: Arg::multiple_values()
/// [`min_values`]: Arg::min_values() /// [`min_values`]: Arg::min_values()
/// [`number_of_values`]: Arg::number_of_values() /// [`number_of_values`]: Arg::number_of_values()
/// [`max_values`]: Arg::max_values() /// [`max_values`]: Arg::max_values()
@ -2028,9 +2029,9 @@ impl<'help> Arg<'help> {
/// `.number_of_values(3)`, and this argument wouldn't be satisfied unless the user provided /// `.number_of_values(3)`, and this argument wouldn't be satisfied unless the user provided
/// 3 and only 3 values. /// 3 and only 3 values.
/// ///
/// **NOTE:** Does *not* require [`Arg::multiple(true)`] to be set. Setting /// **NOTE:** Does *not* require [`Arg::multiple_occurrences(true)`] to be set. Setting
/// [`Arg::multiple(true)`] would allow `-f <file> <file> <file> -f <file> <file> <file>` where /// [`Arg::multiple_occurrences(true)`] would allow `-f <file> <file> <file> -f <file> <file> <file>` where
/// as *not* setting [`Arg::multiple(true)`] would only allow one occurrence of this argument. /// as *not* setting it would only allow one occurrence of this argument.
/// ///
/// # Examples /// # Examples
/// ///
@ -2038,8 +2039,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg}; /// # use clap::{App, Arg};
/// Arg::new("file") /// Arg::new("file")
/// .short('f') /// .short('f')
/// .number_of_values(3) /// .number_of_values(3);
/// # ;
/// ``` /// ```
/// ///
/// Not supplying the correct number of values is an error /// Not supplying the correct number of values is an error
@ -2058,7 +2058,7 @@ impl<'help> Arg<'help> {
/// assert!(res.is_err()); /// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind, ErrorKind::WrongNumberOfValues); /// assert_eq!(res.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
/// ``` /// ```
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
#[inline] #[inline]
pub fn number_of_values(mut self, qty: usize) -> Self { pub fn number_of_values(mut self, qty: usize) -> Self {
self.num_vals = Some(qty); self.num_vals = Some(qty);
@ -2227,10 +2227,10 @@ impl<'help> Arg<'help> {
/// `-f <file>` argument where you wanted up to 3 'files' you would set `.max_values(3)`, and /// `-f <file>` argument where you wanted up to 3 'files' you would set `.max_values(3)`, and
/// this argument would be satisfied if the user provided, 1, 2, or 3 values. /// this argument would be satisfied if the user provided, 1, 2, or 3 values.
/// ///
/// **NOTE:** This does *not* implicitly set [`Arg::multiple(true)`]. This is because /// **NOTE:** This does *not* implicitly set [`Arg::multiple_occurrences(true)`]. This is because
/// `-o val -o val` is multiple occurrences but a single value and `-o val1 val2` is a single /// `-o val -o val` is multiple occurrences but a single value and `-o val1 val2` is a single
/// occurrence with multiple values. For positional arguments this **does** set /// occurrence with multiple values. For positional arguments this **does** set
/// [`Arg::multiple(true)`] because there is no way to determine the difference between multiple /// [`Arg::multiple_occurrences(true)`] because there is no way to determine the difference between multiple
/// occurrences and multiple values. /// occurrences and multiple values.
/// ///
/// # Examples /// # Examples
@ -2239,8 +2239,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg}; /// # use clap::{App, Arg};
/// Arg::new("file") /// Arg::new("file")
/// .short('f') /// .short('f')
/// .max_values(3) /// .max_values(3);
/// # ;
/// ``` /// ```
/// ///
/// Supplying less than the maximum number of values is allowed /// Supplying less than the maximum number of values is allowed
@ -2278,7 +2277,7 @@ impl<'help> Arg<'help> {
/// assert!(res.is_err()); /// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument); /// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument);
/// ``` /// ```
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
#[inline] #[inline]
pub fn max_values(mut self, qty: usize) -> Self { pub fn max_values(mut self, qty: usize) -> Self {
self.max_vals = Some(qty); self.max_vals = Some(qty);
@ -2290,10 +2289,10 @@ impl<'help> Arg<'help> {
/// `.min_values(2)`, and this argument would be satisfied if the user provided, 2 or more /// `.min_values(2)`, and this argument would be satisfied if the user provided, 2 or more
/// values. /// values.
/// ///
/// **NOTE:** This does not implicitly set [`Arg::multiple(true)`]. This is because /// **NOTE:** This does not implicitly set [`Arg::multiple_occurrences(true)`]. This is because
/// `-o val -o val` is multiple occurrences but a single value and `-o val1 val2` is a single /// `-o val -o val` is multiple occurrences but a single value and `-o val1 val2` is a single
/// occurrence with multiple values. For positional arguments this **does** set /// occurrence with multiple values. For positional arguments this **does** set
/// [`Arg::multiple(true)`] because there is no way to determine the difference between multiple /// [`Arg::multiple_occurrences(true)`] because there is no way to determine the difference between multiple
/// occurrences and multiple values. /// occurrences and multiple values.
/// ///
/// # Examples /// # Examples
@ -2302,8 +2301,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg}; /// # use clap::{App, Arg};
/// Arg::new("file") /// Arg::new("file")
/// .short('f') /// .short('f')
/// .min_values(3) /// .min_values(3);
/// # ;
/// ``` /// ```
/// ///
/// Supplying more than the minimum number of values is allowed /// Supplying more than the minimum number of values is allowed
@ -2341,7 +2339,7 @@ impl<'help> Arg<'help> {
/// assert!(res.is_err()); /// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind, ErrorKind::TooFewValues); /// assert_eq!(res.unwrap_err().kind, ErrorKind::TooFewValues);
/// ``` /// ```
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
#[inline] #[inline]
pub fn min_values(mut self, qty: usize) -> Self { pub fn min_values(mut self, qty: usize) -> Self {
self.min_vals = Some(qty); self.min_vals = Some(qty);
@ -2393,13 +2391,9 @@ 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:** This implicitly sets [`Arg::number_of_values`] if the number of value names is
/// greater than one. I.e. be aware that the number of "names" you set for the values, will be
/// the *exact* number of values required to satisfy this argument
///
/// **NOTE:** implicitly sets [`Arg::takes_value(true)`] /// **NOTE:** implicitly sets [`Arg::takes_value(true)`]
/// ///
/// **NOTE:** Does *not* require or imply [`Arg::multiple(true)`]. /// **NOTE:** Does *not* require or imply [`Arg::multiple_values(true)`].
/// ///
/// # Examples /// # Examples
/// ///
@ -2407,8 +2401,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg}; /// # use clap::{App, Arg};
/// Arg::new("speed") /// Arg::new("speed")
/// .short('s') /// .short('s')
/// .value_names(&["fast", "slow"]) /// .value_names(&["fast", "slow"]);
/// # ;
/// ``` /// ```
/// ///
/// ```rust /// ```rust
@ -2421,6 +2414,7 @@ impl<'help> Arg<'help> {
/// "prog", "--help" /// "prog", "--help"
/// ]); /// ]);
/// ``` /// ```
///
/// Running the above program produces the following output /// Running the above program produces the following output
/// ///
/// ```text /// ```text
@ -2439,7 +2433,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::takes_value(true)`]: Arg::takes_value() /// [`Arg::takes_value(true)`]: Arg::takes_value()
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_values(true)`]: Arg::multiple_values()
pub fn value_names(mut self, names: &[&'help str]) -> Self { pub fn value_names(mut self, names: &[&'help str]) -> Self {
let mut i = self.val_names.len(); let mut i = self.val_names.len();
for s in names { for s in names {
@ -3069,7 +3063,7 @@ impl<'help> Arg<'help> {
/// .long("flag") /// .long("flag")
/// .env("MY_FLAG_MULTI") /// .env("MY_FLAG_MULTI")
/// .takes_value(true) /// .takes_value(true)
/// .multiple(true) /// .multiple_values(true)
/// .use_delimiter(true)) /// .use_delimiter(true))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
/// "prog" /// "prog"
@ -3081,7 +3075,6 @@ impl<'help> Arg<'help> {
/// [`ArgMatches::value_of`]: ArgMatches::value_of() /// [`ArgMatches::value_of`]: ArgMatches::value_of()
/// [`ArgMatches::is_present`]: ArgMatches::is_present() /// [`ArgMatches::is_present`]: ArgMatches::is_present()
/// [`Arg::takes_value(true)`]: Arg::takes_value() /// [`Arg::takes_value(true)`]: Arg::takes_value()
/// [`Arg::multiple(true)`]: Arg::multiple()
/// [`Arg::use_delimiter(true)`]: Arg::use_delimiter() /// [`Arg::use_delimiter(true)`]: Arg::use_delimiter()
#[inline] #[inline]
pub fn env(self, name: &'help str) -> Self { pub fn env(self, name: &'help str) -> Self {
@ -3562,6 +3555,7 @@ impl<'help> Arg<'help> {
/// assert!(delims.is_present("opt")); /// assert!(delims.is_present("opt"));
/// assert_eq!(delims.values_of("opt").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]); /// assert_eq!(delims.values_of("opt").unwrap().collect::<Vec<_>>(), ["val1", "val2", "val3"]);
/// ``` /// ```
///
/// In this next example, we will *not* use a delimiter. Notice it's now an error. /// In this next example, we will *not* use a delimiter. Notice it's now an error.
/// ///
/// ```rust /// ```rust
@ -3580,6 +3574,7 @@ impl<'help> Arg<'help> {
/// let err = res.unwrap_err(); /// let err = res.unwrap_err();
/// assert_eq!(err.kind, ErrorKind::UnknownArgument); /// assert_eq!(err.kind, ErrorKind::UnknownArgument);
/// ``` /// ```
///
/// What's happening is `-o` is getting `val1`, and because delimiters are required yet none /// What's happening is `-o` is getting `val1`, and because delimiters are required yet none
/// were present, it stops parsing `-o`. At this point it reaches `val2` and because no /// were present, it stops parsing `-o`. At this point it reaches `val2` and because no
/// positional arguments have been defined, it's an error of an unexpected argument. /// positional arguments have been defined, it's an error of an unexpected argument.
@ -3982,196 +3977,6 @@ impl<'help> Arg<'help> {
} }
} }
/// Specifies that the argument may have an unknown number of multiple 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:** Implicitly sets [`ArgSettings::TakesValue`]
///
/// **WARNING:**
///
/// Setting `MultipleValues` 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 `-`)
///
/// **WARNING:**
///
/// When using args with `MultipleValues` 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 `MultipleValues` 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* [`MultipleOccurrences`]. 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
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("debug")
/// .short('d')
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// # ;
/// ```
/// An example with flags
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("verbose")
/// .setting(ArgSettings::MultipleOccurrences)
/// .short('v'))
/// .get_matches_from(vec![
/// "prog", "-v", "-v", "-v" // note, -vvv would have same result
/// ]);
///
/// assert!(m.is_present("verbose"));
/// assert_eq!(m.occurrences_of("verbose"), 3);
/// ```
///
/// An example with options
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3"
/// ]);
///
/// assert!(m.is_present("file"));
/// assert_eq!(m.occurrences_of("file"), 1); // notice only one occurrence
/// let files: Vec<_> = m.values_of("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3"]);
/// ```
/// Although `MultipleVlaues` has been specified, we cannot use the argument more than once.
///
/// ```rust
/// # use clap::{App, Arg, ErrorKind, ArgSettings};
/// let res = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .try_get_matches_from(vec![
/// "prog", "-F", "file1", "-F", "file2", "-F", "file3"
/// ]);
/// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage)
/// ```
///
/// A common mistake is to define an option which allows multiple values, and a positional
/// argument.
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .arg(Arg::new("word")
/// .index(1))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3", "word"
/// ]);
///
/// assert!(m.is_present("file"));
/// let files: Vec<_> = m.values_of("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3", "word"]); // wait...what?!
/// assert!(!m.is_present("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 [maxium], or [specific]
/// number, or to say [`MultipleOccurrences`] is ok, but multiple values is not.
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::MultipleOccurrences)
/// .setting(ArgSettings::TakesValue)
/// .short('F'))
/// .arg(Arg::new("word")
/// .index(1))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "-F", "file2", "-F", "file3", "word"
/// ]);
///
/// assert!(m.is_present("file"));
/// let files: Vec<_> = m.values_of("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3"]);
/// assert!(m.is_present("word"));
/// assert_eq!(m.value_of("word"), Some("word"));
/// ```
/// As a final example, let's fix the above error and get a pretty message to the user :)
///
/// ```rust
/// # use clap::{App, Arg, ErrorKind, ArgSettings};
/// let res = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::MultipleOccurrences)
/// .setting(ArgSettings::TakesValue)
/// .short('F'))
/// .arg(Arg::new("word")
/// .index(1))
/// .try_get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3", "word"
/// ]);
///
/// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument);
/// ```
/// [option]: ArgSettings::TakesValue
/// [options]: ArgSettings::TakesValue
/// [subcommands]: App::subcommand()
/// [positionals]: Arg::index()
/// [`Arg::number_of_values(1)`]: Arg::number_of_values()
/// [`MultipleOccurrences`]: ArgSettings::MultipleOccurrences
/// [`MultipleValues`]: ArgSettings::MultipleValues
/// [maximum number of values]: Arg::max_values()
/// [specific number of values]: Arg::number_of_values()
/// [maximum]: Arg::max_values()
/// [specific]: Arg::number_of_values()
#[inline]
pub fn multiple(self, multi: bool) -> Self {
self.multiple_occurrences(multi).multiple_values(multi)
}
/// Don't allow an argument to accept explicitly empty values. An empty value /// Don't allow an argument to accept explicitly empty values. An empty value
/// must be specified at the command line with an explicit `""`, `''`, or /// must be specified at the command line with an explicit `""`, `''`, or
/// `--option=` /// `--option=`
@ -4234,7 +4039,177 @@ impl<'help> Arg<'help> {
} }
} }
/// @TODO@ @release @docs /// Specifies that the argument may have an unknown number of multiple 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 [`ArgSettings::TakesValue`].
///
/// **WARNING:**
///
/// Setting `MultipleValues` 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 `-`)
///
/// **WARNING:**
///
/// When using args with `MultipleValues` 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 `MultipleValues` 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* [`MultipleOccurrences`]. 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
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("debug")
/// .short('d')
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues);
/// ```
///
/// An example with options
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3"
/// ]);
///
/// assert!(m.is_present("file"));
/// assert_eq!(m.occurrences_of("file"), 1); // notice only one occurrence
/// let files: Vec<_> = m.values_of("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3"]);
/// ```
///
/// Although `MultipleVlaues` has been specified, we cannot use the argument more than once.
///
/// ```rust
/// # use clap::{App, Arg, ErrorKind, ArgSettings};
/// let res = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .try_get_matches_from(vec![
/// "prog", "-F", "file1", "-F", "file2", "-F", "file3"
/// ]);
///
/// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage)
/// ```
///
/// A common mistake is to define an option which allows multiple values, and a positional
/// argument.
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .arg(Arg::new("word")
/// .index(1))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3", "word"
/// ]);
///
/// assert!(m.is_present("file"));
/// let files: Vec<_> = m.values_of("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3", "word"]); // wait...what?!
/// assert!(!m.is_present("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 [`MultipleOccurrences`] is ok, but multiple values is not.
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::MultipleOccurrences)
/// .setting(ArgSettings::TakesValue)
/// .short('F'))
/// .arg(Arg::new("word")
/// .index(1))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "-F", "file2", "-F", "file3", "word"
/// ]);
///
/// assert!(m.is_present("file"));
/// let files: Vec<_> = m.values_of("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3"]);
/// assert!(m.is_present("word"));
/// assert_eq!(m.value_of("word"), Some("word"));
/// ```
///
/// As a final example, let's fix the above error and get a pretty message to the user :)
///
/// ```rust
/// # use clap::{App, Arg, ErrorKind, ArgSettings};
/// let res = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::MultipleOccurrences)
/// .setting(ArgSettings::TakesValue)
/// .short('F'))
/// .arg(Arg::new("word")
/// .index(1))
/// .try_get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3", "word"
/// ]);
///
/// assert!(res.is_err());
/// assert_eq!(res.unwrap_err().kind, ErrorKind::UnknownArgument);
/// ```
///
/// [`subcommands`]: App::subcommand()
/// [`Arg::number_of_values(1)`]: Arg::number_of_values()
/// [`MultipleOccurrences`]: ArgSettings::MultipleOccurrences
/// [`MultipleValues`]: ArgSettings::MultipleValues
/// [maximum number of values]: Arg::max_values()
/// [specific number of values]: Arg::number_of_values()
/// [maximum]: Arg::max_values()
/// [specific]: Arg::number_of_values()
#[inline] #[inline]
pub fn multiple_values(self, multi: bool) -> Self { pub fn multiple_values(self, multi: bool) -> Self {
if multi { if multi {
@ -4244,8 +4219,7 @@ impl<'help> Arg<'help> {
} }
} }
/// Specifies that the argument may appear more than once. /// Specifies that the argument may appear more than once. For flags, this results
/// For flags, this results
/// in the number of occurrences of the flag being recorded. For example `-ddd` or `-d -d -d` /// in the number of occurrences of the flag being recorded. For example `-ddd` or `-d -d -d`
/// would count as three occurrences. For options or arguments that take a value, this /// would count as three occurrences. For options or arguments that take a value, this
/// *does not* affect how many values they can accept. (i.e. only one at a time is allowed) /// *does not* affect how many values they can accept. (i.e. only one at a time is allowed)
@ -4258,9 +4232,9 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ArgSettings}; /// # use clap::{App, Arg, ArgSettings};
/// Arg::new("debug") /// Arg::new("debug")
/// .short('d') /// .short('d')
/// .setting(ArgSettings::MultipleOccurrences) /// .setting(ArgSettings::MultipleOccurrences);
/// # ;
/// ``` /// ```
///
/// An example with flags /// An example with flags
/// ///
/// ```rust /// ```rust
@ -4295,17 +4269,6 @@ impl<'help> Arg<'help> {
/// let files: Vec<_> = m.values_of("file").unwrap().collect(); /// let files: Vec<_> = m.values_of("file").unwrap().collect();
/// assert_eq!(files, ["file1", "file2", "file3"]); /// assert_eq!(files, ["file1", "file2", "file3"]);
/// ``` /// ```
/// [option]: ArgSettings::TakesValue
/// [options]: ArgSettings::TakesValue
/// [subcommands]: App::subcommand()
/// [positionals]: Arg::index()
/// [`Arg::number_of_values(1)`]: Arg::number_of_values()
/// [`MultipleOccurrences`]: ArgSettings::MultipleOccurrences
/// [`MultipleValues`]: ArgSettings::MultipleValues
/// [maximum number of values]: Arg::max_values()
/// [specific number of values]: Arg::number_of_values()
/// [maximum]: Arg::max_values()
/// [specific]: Arg::number_of_values()
#[inline] #[inline]
pub fn multiple_occurrences(self, multi: bool) -> Self { pub fn multiple_occurrences(self, multi: bool) -> Self {
if multi { if multi {
@ -4323,21 +4286,22 @@ impl<'help> Arg<'help> {
/// ```text /// ```text
/// --foo something -- -v -v -v -b -b -b --baz -q -u -x /// --foo something -- -v -v -v -b -b -b --baz -q -u -x
/// ``` /// ```
///
/// Will result in everything after `--` to be considered one raw argument. This behavior /// Will result in everything after `--` to be considered one raw argument. This behavior
/// may not be exactly what you are expecting and using [`AppSettings::TrailingVarArg`] /// may not be exactly what you are expecting and using [`AppSettings::TrailingVarArg`]
/// may be more appropriate. /// may be more appropriate.
/// ///
/// **NOTE:** Implicitly sets [`Arg::takes_value(true)`] [`Arg::multiple(true)`], [`Arg::allow_hyphen_values(true)`], and /// **NOTE:** Implicitly sets [`Arg::takes_value(true)`] [`Arg::multiple_values(true)`],
/// [`Arg::last(true)`] when set to `true` /// [`Arg::allow_hyphen_values(true)`], and [`Arg::last(true)`] when set to `true`
/// ///
/// [`Arg::takes_value(true)`]: Arg::takes_value() /// [`Arg::takes_value(true)`]: Arg::takes_value()
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_values(true)`]: Arg::multiple_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]
pub fn raw(self, raw: bool) -> Self { pub fn raw(self, raw: bool) -> Self {
self.takes_value(raw) self.takes_value(raw)
.multiple(raw) .multiple_values(raw)
.allow_hyphen_values(raw) .allow_hyphen_values(raw)
.last(raw) .last(raw)
} }
@ -4354,9 +4318,9 @@ impl<'help> Arg<'help> {
/// ```rust /// ```rust
/// # use clap::{App, Arg}; /// # use clap::{App, Arg};
/// Arg::new("debug") /// Arg::new("debug")
/// .hidden_short_help(true) /// .hidden_short_help(true);
/// # ;
/// ``` /// ```
///
/// Setting `hidden_short_help(true)` will hide the argument when displaying short help text /// Setting `hidden_short_help(true)` will hide the argument when displaying short help text
/// ///
/// ```rust /// ```rust
@ -4555,16 +4519,17 @@ impl<'help> Arg<'help> {
/// Currently this is only supported by the zsh completions generator. /// Currently this is only supported by the zsh completions generator.
/// ///
/// For example, to take a username as argument: /// For example, to take a username as argument:
///
/// ``` /// ```
/// # use clap::{Arg, ValueHint}; /// # use clap::{Arg, ValueHint};
/// Arg::new("user") /// Arg::new("user")
/// .short('u') /// .short('u')
/// .long("user") /// .long("user")
/// .value_hint(ValueHint::Username) /// .value_hint(ValueHint::Username);
/// # ;
/// ``` /// ```
/// ///
/// To take a full command line and its arguments (for example, when writing a command wrapper): /// To take a full command line and its arguments (for example, when writing a command wrapper):
///
/// ``` /// ```
/// # use clap::{App, AppSettings, Arg, ValueHint}; /// # use clap::{App, AppSettings, Arg, ValueHint};
/// App::new("prog") /// App::new("prog")
@ -4572,10 +4537,9 @@ impl<'help> Arg<'help> {
/// .arg( /// .arg(
/// Arg::new("command") /// Arg::new("command")
/// .takes_value(true) /// .takes_value(true)
/// .multiple(true) /// .multiple_values(true)
/// .value_hint(ValueHint::CommandWithArguments) /// .value_hint(ValueHint::CommandWithArguments)
/// ) /// );
/// # ;
/// ``` /// ```
pub fn value_hint(mut self, value_hint: ValueHint) -> Self { pub fn value_hint(mut self, value_hint: ValueHint) -> Self {
self.settings.set(ArgSettings::TakesValue); self.settings.set(ArgSettings::TakesValue);
@ -4614,11 +4578,10 @@ impl<'help> Arg<'help> {
// Used for positionals when printing // Used for positionals when printing
pub(crate) fn multiple_str(&self) -> &str { pub(crate) fn multiple_str(&self) -> &str {
// FIXME: This should probably be > 1 let mult_vals = self.val_names.len() > 1;
let mult_vals = self.val_names.len() < 2;
if (self.is_set(ArgSettings::MultipleValues) if (self.is_set(ArgSettings::MultipleValues)
|| self.is_set(ArgSettings::MultipleOccurrences)) || self.is_set(ArgSettings::MultipleOccurrences))
&& mult_vals && !mult_vals
{ {
"..." "..."
} else { } else {
@ -4810,11 +4773,13 @@ impl<'help> Display for Arg<'help> {
if self.index.is_some() || (self.long.is_none() && self.short.is_none()) { if self.index.is_some() || (self.long.is_none() && self.short.is_none()) {
// Positional // Positional
let mut delim = String::new(); let mut delim = String::new();
delim.push(if self.is_set(ArgSettings::RequireDelimiter) { delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
self.val_delim.expect(INTERNAL_ERROR_MSG) self.val_delim.expect(INTERNAL_ERROR_MSG)
} else { } else {
' ' ' '
}); });
if !self.val_names.is_empty() { if !self.val_names.is_empty() {
write!( write!(
f, f,
@ -4828,9 +4793,9 @@ impl<'help> Display for Arg<'help> {
} else { } else {
write!(f, "<{}>", self.name)?; write!(f, "<{}>", self.name)?;
} }
if self.settings.is_set(ArgSettings::MultipleValues) && self.val_names.len() < 2 {
write!(f, "...")?; write!(f, "{}", self.multiple_str())?;
}
return Ok(()); return Ok(());
} else if !self.is_set(ArgSettings::TakesValue) { } else if !self.is_set(ArgSettings::TakesValue) {
// Flag // Flag
@ -4842,17 +4807,20 @@ impl<'help> Display for Arg<'help> {
return Ok(()); return Ok(());
} }
let sep = if self.is_set(ArgSettings::RequireEquals) { let sep = if self.is_set(ArgSettings::RequireEquals) {
"=" "="
} else { } else {
" " " "
}; };
// Write the name such --long or -l // Write the name such --long or -l
if let Some(l) = self.long { if let Some(l) = self.long {
write!(f, "--{}{}", l, sep)?; write!(f, "--{}{}", l, sep)?;
} else { } else {
write!(f, "-{}{}", self.short.unwrap(), sep)?; write!(f, "-{}{}", self.short.unwrap(), sep)?;
} }
let delim = if self.is_set(ArgSettings::RequireDelimiter) { let delim = if self.is_set(ArgSettings::RequireDelimiter) {
self.val_delim.expect(INTERNAL_ERROR_MSG) self.val_delim.expect(INTERNAL_ERROR_MSG)
} else { } else {
@ -4861,25 +4829,29 @@ impl<'help> Display for Arg<'help> {
// Write the values such as <name1> <name2> // Write the values such as <name1> <name2>
if !self.val_names.is_empty() { if !self.val_names.is_empty() {
let num = self.val_names.len();
let mut it = self.val_names.iter().peekable(); let mut it = self.val_names.iter().peekable();
while let Some((_, val)) = it.next() { while let Some((_, val)) = it.next() {
write!(f, "<{}>", val)?; write!(f, "<{}>", val)?;
if it.peek().is_some() { if it.peek().is_some() {
write!(f, "{}", delim)?; write!(f, "{}", delim)?;
} }
} }
let num = self.val_names.len();
if self.is_set(ArgSettings::MultipleValues) && num == 1 { if self.is_set(ArgSettings::MultipleValues) && num == 1 {
write!(f, "...")?; write!(f, "...")?;
} }
} else if let Some(num) = self.num_vals { } else if let Some(num) = self.num_vals {
let mut it = (0..num).peekable(); let mut it = (0..num).peekable();
while let Some(_) = it.next() { while let Some(_) = it.next() {
write!(f, "<{}>", self.name)?; write!(f, "<{}>", self.name)?;
if it.peek().is_some() { if it.peek().is_some() {
write!(f, "{}", delim)?; write!(f, "{}", delim)?;
} }
} }
if self.is_set(ArgSettings::MultipleValues) && num == 1 { if self.is_set(ArgSettings::MultipleValues) && num == 1 {
write!(f, "...")?; write!(f, "...")?;
} }
@ -4888,7 +4860,7 @@ impl<'help> Display for Arg<'help> {
f, f,
"<{}>{}", "<{}>{}",
self.name, self.name,
if self.is_set(ArgSettings::MultipleOccurrences) { if self.is_set(ArgSettings::MultipleValues) {
"..." "..."
} else { } else {
"" ""
@ -5026,11 +4998,21 @@ mod test {
// Options // Options
#[test] #[test]
fn option_display1() { fn option_display_multiple_occurrences() {
let o = Arg::new("opt") let o = Arg::new("opt")
.long("option") .long("option")
.takes_value(true) .takes_value(true)
.multiple(true); .multiple_occurrences(true);
assert_eq!(&*format!("{}", o), "--option <opt>");
}
#[test]
fn option_display_multiple_values() {
let o = Arg::new("opt")
.long("option")
.takes_value(true)
.multiple_values(true);
assert_eq!(&*format!("{}", o), "--option <opt>..."); assert_eq!(&*format!("{}", o), "--option <opt>...");
} }
@ -5047,7 +5029,7 @@ mod test {
let o2 = Arg::new("opt") let o2 = Arg::new("opt")
.short('o') .short('o')
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.value_names(&["file", "name"]); .value_names(&["file", "name"]);
assert_eq!(&*format!("{}", o2), "-o <file> <name>"); assert_eq!(&*format!("{}", o2), "-o <file> <name>");
@ -5098,7 +5080,7 @@ mod test {
// Positionals // Positionals
#[test] #[test]
fn positiona_display_mult() { fn positional_display_multiple_values() {
let p = Arg::new("pos") let p = Arg::new("pos")
.index(1) .index(1)
.setting(ArgSettings::TakesValue) .setting(ArgSettings::TakesValue)
@ -5107,6 +5089,16 @@ mod test {
assert_eq!(&*format!("{}", p), "<pos>..."); assert_eq!(&*format!("{}", p), "<pos>...");
} }
#[test]
fn positional_display_multiple_occurrences() {
let p = Arg::new("pos")
.index(1)
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleOccurrences);
assert_eq!(&*format!("{}", p), "<pos>...");
}
#[test] #[test]
fn positional_display_required() { fn positional_display_required() {
let p2 = Arg::new("pos").index(1).setting(ArgSettings::Required); let p2 = Arg::new("pos").index(1).setting(ArgSettings::Required);

View file

@ -45,11 +45,11 @@ 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(true)`] and App must use [`AppSettings::TrailingVarArg`]. The result is that the /// [`.multiple_values(true)`] and App must use [`AppSettings::TrailingVarArg`]. 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.
/// ///
/// [`.multiple(true)`]: Arg::multiple() /// [`.multiple_values(true)`]: Arg::multiple_values()
CommandWithArguments, CommandWithArguments,
/// Name of a local operating system user. /// Name of a local operating system user.
Username, Username,

View file

@ -246,7 +246,8 @@ macro_rules! app_from_crate {
/// ///
/// * A single hyphen followed by a character (such as `-c`) sets the [`Arg::short`] /// * A single hyphen followed by a character (such as `-c`) sets the [`Arg::short`]
/// * A double hyphen followed by a character or word (such as `--config`) sets [`Arg::long`] /// * A double hyphen followed by a character or word (such as `--config`) sets [`Arg::long`]
/// * Three dots (`...`) sets [`Arg::multiple(true)`] /// * Three dots (`...`) sets [`Arg::multiple_values(true)`]
/// * Three dots (`...`) sets [`Arg::multiple_occurrences(true)`]
/// * Angled brackets after either a short or long will set [`Arg::value_name`] and /// * Angled brackets after either a short or long will set [`Arg::value_name`] and
/// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and /// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and
/// `Arg::required(true)` /// `Arg::required(true)`
@ -287,7 +288,8 @@ macro_rules! app_from_crate {
/// ///
/// [`Arg::short`]: Arg::short() /// [`Arg::short`]: Arg::short()
/// [`Arg::long`]: Arg::long() /// [`Arg::long`]: Arg::long()
/// [`Arg::multiple(true)`]: Arg::multiple() /// [`Arg::multiple_values(true)`]: Arg::multiple_values()
/// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
/// [`Arg::value_name`]: Arg::value_name() /// [`Arg::value_name`]: Arg::value_name()
/// [`Arg::min_values(min)`]: Arg::min_values() /// [`Arg::min_values(min)`]: Arg::min_values()
/// [`Arg::max_values(max)`]: Arg::max_values() /// [`Arg::max_values(max)`]: Arg::max_values()
@ -461,7 +463,7 @@ macro_rules! clap_app {
$crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* } $crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* }
}; };
(@arg ($arg:expr) $modes:tt ... $($tail:tt)*) => { (@arg ($arg:expr) $modes:tt ... $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg) $modes +multiple +takes_value $($tail)* } $crate::clap_app!{ @arg ($arg) $modes +multiple_values +takes_value $($tail)* }
}; };
// Shorthand magic // Shorthand magic
(@arg ($arg:expr) $modes:tt #{$n:expr, $m:expr} $($tail:tt)*) => { (@arg ($arg:expr) $modes:tt #{$n:expr, $m:expr} $($tail:tt)*) => {

View file

@ -173,8 +173,6 @@ pub enum ErrorKind {
/// # use clap::{App, Arg, ErrorKind}; /// # use clap::{App, Arg, ErrorKind};
/// let result = App::new("prog") /// let result = App::new("prog")
/// .arg(Arg::new("arg") /// .arg(Arg::new("arg")
/// .takes_value(true)
/// .multiple(true)
/// .max_values(2)) /// .max_values(2))
/// .try_get_matches_from(vec!["prog", "too", "many", "values"]); /// .try_get_matches_from(vec!["prog", "too", "many", "values"]);
/// assert!(result.is_err()); /// assert!(result.is_err());
@ -285,7 +283,7 @@ pub enum ErrorKind {
/// let result = App::new("prog") /// let result = App::new("prog")
/// .arg(Arg::new("debug") /// .arg(Arg::new("debug")
/// .long("debug") /// .long("debug")
/// .multiple(false)) /// .multiple_occurrences(false))
/// .try_get_matches_from(vec!["prog", "--debug", "--debug"]); /// .try_get_matches_from(vec!["prog", "--debug", "--debug"]);
/// assert!(result.is_err()); /// assert!(result.is_err());
/// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage); /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage);

View file

@ -40,8 +40,7 @@ pub(crate) struct SubCommand {
/// .takes_value(true)) /// .takes_value(true))
/// .arg(Arg::new("debug") /// .arg(Arg::new("debug")
/// .short('d') /// .short('d')
/// .takes_value(true) /// .multiple_occurrences(true))
/// .multiple(true))
/// .arg(Arg::new("cfg") /// .arg(Arg::new("cfg")
/// .short('c') /// .short('c')
/// .takes_value(true)) /// .takes_value(true))
@ -64,7 +63,7 @@ pub(crate) struct SubCommand {
/// // Another way to check if an argument was present, or if it occurred multiple times is to /// // Another way to check if an argument was present, or if it occurred multiple times is to
/// // use occurrences_of() which returns 0 if an argument isn't found at runtime, or the /// // use occurrences_of() which returns 0 if an argument isn't found at runtime, or the
/// // number of times that it occurred, if it was. To allow an argument to appear more than /// // number of times that it occurred, if it was. To allow an argument to appear more than
/// // once, you must use the .multiple(true) method, otherwise it will only return 1 or 0. /// // once, you must use the .multiple_occurrences(true) method, otherwise it will only return 1 or 0.
/// if matches.occurrences_of("debug") > 2 { /// if matches.occurrences_of("debug") > 2 {
/// println!("Debug mode is REALLY on, don't be crazy"); /// println!("Debug mode is REALLY on, don't be crazy");
/// } else { /// } else {
@ -219,7 +218,7 @@ impl ArgMatches {
/// # use clap::{App, Arg}; /// # use clap::{App, Arg};
/// let m = App::new("myprog") /// let m = App::new("myprog")
/// .arg(Arg::new("output") /// .arg(Arg::new("output")
/// .multiple(true) /// .multiple_values(true)
/// .short('o') /// .short('o')
/// .takes_value(true)) /// .takes_value(true))
/// .get_matches_from(vec![ /// .get_matches_from(vec![
@ -683,8 +682,7 @@ impl ArgMatches {
/// .short('z')) /// .short('z'))
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .takes_value(true) /// .takes_value(true))
/// .multiple(true))
/// .get_matches_from(vec!["myapp", "-fzFoval"]); /// .get_matches_from(vec!["myapp", "-fzFoval"]);
/// // ARGV idices: ^0 ^1 /// // ARGV idices: ^0 ^1
/// // clap idices: ^1,2,3^5 /// // clap idices: ^1,2,3^5
@ -704,9 +702,8 @@ impl ArgMatches {
/// let m = App::new("myapp") /// let m = App::new("myapp")
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .takes_value(true)
/// .use_delimiter(true) /// .use_delimiter(true)
/// .multiple(true)) /// .multiple_values(true))
/// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
/// // ARGV idices: ^0 ^1 /// // ARGV idices: ^0 ^1
/// // clap idices: ^2 ^3 ^4 /// // clap idices: ^2 ^3 ^4
@ -744,9 +741,8 @@ impl ArgMatches {
/// let m = App::new("myapp") /// let m = App::new("myapp")
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .takes_value(true)
/// .use_delimiter(true) /// .use_delimiter(true)
/// .multiple(true)) /// .multiple_values(true))
/// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
/// // ARGV idices: ^0 ^1 /// // ARGV idices: ^0 ^1
/// // clap idices: ^2 ^3 ^4 /// // clap idices: ^2 ^3 ^4
@ -764,7 +760,7 @@ impl ArgMatches {
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .takes_value(true) /// .takes_value(true)
/// .multiple(true)) /// .multiple_occurrences(true))
/// .arg(Arg::new("flag") /// .arg(Arg::new("flag")
/// .short('f') /// .short('f')
/// .multiple_occurrences(true)) /// .multiple_occurrences(true))
@ -787,7 +783,7 @@ impl ArgMatches {
/// .arg(Arg::new("option") /// .arg(Arg::new("option")
/// .short('o') /// .short('o')
/// .takes_value(true) /// .takes_value(true)
/// .multiple(true)) /// .multiple_values(true))
/// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); /// .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
/// // ARGV idices: ^0 ^1 /// // ARGV idices: ^0 ^1
/// // clap idices: ^2 /// // clap idices: ^2
@ -972,7 +968,7 @@ impl ArgMatches {
/// let m = App::new("myapp") /// let m = App::new("myapp")
/// .arg(Arg::new("output") /// .arg(Arg::new("output")
/// .short('o') /// .short('o')
/// .multiple(true) /// .multiple_values(true)
/// .takes_value(true)) /// .takes_value(true))
/// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]); /// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]);
/// ///
@ -1121,7 +1117,7 @@ impl Default for OsValues<'_> {
/// let m = App::new("myapp") /// let m = App::new("myapp")
/// .arg(Arg::new("output") /// .arg(Arg::new("output")
/// .short('o') /// .short('o')
/// .multiple(true) /// .multiple_values(true)
/// .takes_value(true)) /// .takes_value(true))
/// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]); /// .get_matches_from(vec!["myapp", "-o", "val1", "val2"]);
/// ///

View file

@ -147,7 +147,7 @@ impl<'help, 'app> Parser<'help, 'app> {
num_p num_p
); );
// Next we verify that only the highest index has a .multiple(true) (if any) // Next we verify that only the highest index has a .multiple_values(true) (if any)
let only_highest = |a: &Arg| { let only_highest = |a: &Arg| {
a.is_set(ArgSettings::MultipleValues) && (a.index.unwrap_or(0) != highest_idx) a.is_set(ArgSettings::MultipleValues) && (a.index.unwrap_or(0) != highest_idx)
}; };
@ -171,7 +171,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|| last.is_set(ArgSettings::Last); || last.is_set(ArgSettings::Last);
assert!( assert!(
ok, ok,
"When using a positional argument with .multiple(true) that is *not the \ "When using a positional argument with .multiple_values(true) 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."
); );
@ -182,7 +182,7 @@ impl<'help, 'app> Parser<'help, 'app> {
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(true)" argument may be set to .multiple_values(true)"
); );
// 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
@ -198,7 +198,7 @@ impl<'help, 'app> Parser<'help, 'app> {
&& count == 2); && count == 2);
assert!( assert!(
ok, ok,
"Only one positional argument with .multiple(true) set is allowed per \ "Only one positional argument with .multiple_values(true) set is allowed per \
command, unless the second one also has .last(true) set" command, unless the second one also has .last(true) set"
); );
} }
@ -456,7 +456,7 @@ impl<'help, 'app> Parser<'help, 'app> {
let is_second_to_last = pos_counter + 1 == positional_count; let is_second_to_last = pos_counter + 1 == positional_count;
// The last positional argument, or second to last positional // The last positional argument, or second to last positional
// argument may be set to .multiple(true) // argument may be set to .multiple_values(true)
let low_index_mults = is_second_to_last let low_index_mults = is_second_to_last
&& self.app.get_positionals().any(|a| { && self.app.get_positionals().any(|a| {
a.is_set(ArgSettings::MultipleValues) a.is_set(ArgSettings::MultipleValues)

View file

@ -116,7 +116,7 @@ fn opt_eq_mult_def_delim() {
Arg::new("option") Arg::new("option")
.long("opt") .long("opt")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.use_delimiter(true), .use_delimiter(true),
) )
.try_get_matches_from(vec!["", "--opt=val1,val2,val3"]); .try_get_matches_from(vec!["", "--opt=val1,val2,val3"]);

View file

@ -189,7 +189,7 @@ fn multiple_one() {
.env("CLP_TEST_ENV_MO") .env("CLP_TEST_ENV_MO")
.takes_value(true) .takes_value(true)
.use_delimiter(true) .use_delimiter(true)
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
@ -210,7 +210,7 @@ fn multiple_three() {
.env("CLP_TEST_ENV_MULTI1") .env("CLP_TEST_ENV_MULTI1")
.takes_value(true) .takes_value(true)
.use_delimiter(true) .use_delimiter(true)
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
@ -233,7 +233,7 @@ fn multiple_no_delimiter() {
Arg::from("[arg] 'some opt'") Arg::from("[arg] 'some opt'")
.env("CLP_TEST_ENV_MULTI2") .env("CLP_TEST_ENV_MULTI2")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);

View file

@ -202,13 +202,7 @@ fn flag_subcommand_short_after_long_arg() {
.short_flag('S') .short_flag('S')
.arg(Arg::new("clean").short('c')), .arg(Arg::new("clean").short('c')),
) )
.arg( .arg(Arg::new("arg").long("arg").takes_value(true))
Arg::new("arg")
.long("arg")
.takes_value(true)
.multiple(false)
.global(true),
)
.get_matches_from(vec!["pacman", "--arg", "foo", "-Sc"]); .get_matches_from(vec!["pacman", "--arg", "foo", "-Sc"]);
let subm = m.subcommand_matches("sync"); let subm = m.subcommand_matches("sync");
assert!(subm.is_some()); assert!(subm.is_some());

View file

@ -17,9 +17,8 @@ fn issue_1076() {
Arg::new("GLOBAL_FLAG") Arg::new("GLOBAL_FLAG")
.long("global-flag") .long("global-flag")
.about("Specifies something needed by the subcommands") .about("Specifies something needed by the subcommands")
.takes_value(true) .global(true)
.multiple(true) .takes_value(true),
.global(true),
) )
.subcommand(App::new("outer").subcommand(App::new("inner"))); .subcommand(App::new("outer").subcommand(App::new("inner")));
let _ = app.try_get_matches_from_mut(vec!["myprog"]); let _ = app.try_get_matches_from_mut(vec!["myprog"]);

View file

@ -9,7 +9,8 @@ fn grouped_value_works() {
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.get_matches_from(&[ .get_matches_from(&[
"cli", "cli",
@ -39,7 +40,8 @@ fn issue_1026() {
Arg::new("target") Arg::new("target")
.long("target") .long("target")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.get_matches_from(&[ .get_matches_from(&[
"backup", "-s", "server", "-u", "user", "--target", "target1", "file1", "file2", "backup", "-s", "server", "-u", "user", "--target", "target1", "file1", "file2",
@ -65,7 +67,8 @@ fn grouped_value_long_flag_delimiter() {
.long("option") .long("option")
.takes_value(true) .takes_value(true)
.use_delimiter(true) .use_delimiter(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.get_matches_from(vec![ .get_matches_from(vec![
"myapp", "myapp",
@ -93,7 +96,8 @@ fn grouped_value_short_flag_delimiter() {
.short('o') .short('o')
.takes_value(true) .takes_value(true)
.use_delimiter(true) .use_delimiter(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.get_matches_from(vec!["myapp", "-o=foo", "-o=val1,val2,val3", "-o=bar"]); .get_matches_from(vec!["myapp", "-o=foo", "-o=val1,val2,val3", "-o=bar"]);
let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect(); let grouped_vals: Vec<_> = m.grouped_values_of("option").unwrap().collect();
@ -110,7 +114,8 @@ fn grouped_value_positional_arg() {
Arg::new("pos") Arg::new("pos")
.about("multiple positionals") .about("multiple positionals")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.get_matches_from(vec![ .get_matches_from(vec![
"myprog", "val1", "val2", "val3", "val4", "val5", "val6", "myprog", "val1", "val2", "val3", "val4", "val5", "val6",
@ -130,7 +135,8 @@ fn grouped_value_multiple_positional_arg() {
Arg::new("pos2") Arg::new("pos2")
.about("multiple positionals") .about("multiple positionals")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.get_matches_from(vec![ .get_matches_from(vec![
"myprog", "val1", "val2", "val3", "val4", "val5", "val6", "myprog", "val1", "val2", "val3", "val4", "val5", "val6",
@ -150,7 +156,8 @@ fn grouped_value_multiple_positional_arg_last_multiple() {
Arg::new("pos2") Arg::new("pos2")
.about("multiple positionals") .about("multiple positionals")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.multiple_occurrences(true)
.last(true), .last(true),
) )
.get_matches_from(vec![ .get_matches_from(vec![

View file

@ -175,7 +175,7 @@ FLAGS:
OPTIONS: OPTIONS:
-o, --opt <FILE> tests options"; -o, --opt <FILE> tests options";
// Using number_of_values(1) with multiple(true) misaligns help message // Using number_of_values(1) with multiple_values(true) misaligns help message
static ISSUE_760: &str = "ctest 0.1 static ISSUE_760: &str = "ctest 0.1
USAGE: USAGE:
@ -1213,7 +1213,7 @@ fn issue_702_multiple_values() {
.arg( .arg(
Arg::new("arg2") Arg::new("arg2")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.about("some option"), .about("some option"),
) )
.arg( .arg(
@ -1235,7 +1235,7 @@ fn issue_702_multiple_values() {
.about("a label") .about("a label")
.short('l') .short('l')
.long("label") .long("label")
.multiple(true) .multiple_values(true)
.takes_value(true), .takes_value(true),
); );
assert!(utils::compare_output(app, "myapp --help", ISSUE_702, false)); assert!(utils::compare_output(app, "myapp --help", ISSUE_702, false));
@ -1269,7 +1269,7 @@ fn issue_760() {
.short('o') .short('o')
.long("option") .long("option")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.number_of_values(1), .number_of_values(1),
) )
.arg( .arg(
@ -1520,7 +1520,7 @@ fn last_arg_mult_usage() {
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.last(true) .last(true)
.about("some"), .about("some"),
); );
@ -1536,7 +1536,7 @@ fn last_arg_mult_usage_req() {
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.last(true) .last(true)
.required(true) .required(true)
.about("some"), .about("some"),
@ -1559,7 +1559,7 @@ fn last_arg_mult_usage_req_with_sc() {
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.last(true) .last(true)
.required(true) .required(true)
.about("some"), .about("some"),
@ -1583,7 +1583,7 @@ fn last_arg_mult_usage_with_sc() {
.arg( .arg(
Arg::new("ARGS") Arg::new("ARGS")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.last(true) .last(true)
.about("some"), .about("some"),
) )
@ -2000,7 +2000,7 @@ fn issue_1364_no_short_options() {
Arg::new("files") Arg::new("files")
.value_name("FILES") .value_name("FILES")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
); );
assert!(utils::compare_output(app, "demo -h", ISSUE_1364, false)); assert!(utils::compare_output(app, "demo -h", ISSUE_1364, false));

View file

@ -9,13 +9,14 @@ fn indices_mult_opts() {
Arg::new("exclude") Arg::new("exclude")
.short('e') .short('e')
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.arg( .arg(
Arg::new("include") Arg::new("include")
.short('i') .short('i')
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]); .get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]);
@ -36,13 +37,14 @@ fn index_mult_opts() {
Arg::new("exclude") Arg::new("exclude")
.short('e') .short('e')
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.arg( .arg(
Arg::new("include") Arg::new("include")
.short('i') .short('i')
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]); .get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]);
@ -152,7 +154,7 @@ fn indices_mult_opt_value_delim_eq() {
.short('o') .short('o')
.takes_value(true) .takes_value(true)
.use_delimiter(true) .use_delimiter(true)
.multiple(true), .multiple_values(true),
) )
.get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
assert_eq!( assert_eq!(
@ -168,7 +170,7 @@ fn indices_mult_opt_value_no_delim_eq() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]); assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]);

View file

@ -8,7 +8,8 @@ fn option_long() {
.long("option") .long("option")
.about("multiple options") .about("multiple options")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "--option", "val1", "--option", "val2", "--option", "val3", "", "--option", "val1", "--option", "val2", "--option", "val3",
@ -33,7 +34,8 @@ fn option_short() {
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]);
@ -57,7 +59,8 @@ fn option_mixed() {
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true)
.multiple_occurrences(true),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "-o", "val1", "--option", "val2", "--option", "val3", "-o", "val4", "", "-o", "val1", "--option", "val2", "--option", "val3", "-o", "val4",
@ -81,9 +84,8 @@ fn option_exact_exact() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .number_of_values(3)
.multiple(true) .multiple_occurrences(true),
.number_of_values(3),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]);
@ -105,7 +107,6 @@ fn option_exact_exact_not_mult() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true)
.number_of_values(3), .number_of_values(3),
) )
.try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
@ -128,9 +129,8 @@ fn option_exact_exact_mult() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .number_of_values(3)
.multiple(true) .multiple_occurrences(true),
.number_of_values(3),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "-o", "val1", "val2", "val3", "-o", "val4", "val5", "val6", "", "-o", "val1", "val2", "val3", "-o", "val4", "val5", "val6",
@ -154,9 +154,8 @@ fn option_exact_less() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .number_of_values(3)
.multiple(true) .multiple_occurrences(true),
.number_of_values(3),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]);
@ -171,9 +170,8 @@ fn option_exact_more() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .number_of_values(3)
.multiple(true) .multiple_occurrences(true),
.number_of_values(3),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4", "", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4",
@ -190,9 +188,8 @@ fn option_min_exact() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .min_values(3)
.multiple(true) .multiple_occurrences(true),
.min_values(3),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]);
@ -214,9 +211,8 @@ fn option_min_less() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .min_values(3)
.multiple(true) .multiple_occurrences(true),
.min_values(3),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]);
@ -232,9 +228,8 @@ fn option_short_min_more_mult_occurs() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .min_values(3)
.multiple(true) .multiple_occurrences(true),
.min_values(3),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "pos", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4", "", "pos", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4",
@ -261,8 +256,6 @@ fn option_short_min_more_single_occur() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true)
.multiple(true)
.min_values(3), .min_values(3),
) )
.try_get_matches_from(vec!["", "pos", "-o", "val1", "val2", "val3", "val4"]); .try_get_matches_from(vec!["", "pos", "-o", "val1", "val2", "val3", "val4"]);
@ -287,9 +280,8 @@ fn option_max_exact() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .max_values(3)
.multiple(true) .multiple_occurrences(true),
.max_values(3),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]);
@ -311,9 +303,8 @@ fn option_max_less() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .max_values(3)
.multiple(true) .multiple_occurrences(true),
.max_values(3),
) )
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]); .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]);
@ -335,9 +326,8 @@ fn option_max_more() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.takes_value(true) .max_values(3)
.multiple(true) .multiple_occurrences(true),
.max_values(3),
) )
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4", "", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4",
@ -354,7 +344,7 @@ fn positional() {
Arg::new("pos") Arg::new("pos")
.about("multiple positionals") .about("multiple positionals")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]); .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
@ -512,10 +502,8 @@ fn sep_long_equals() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.use_delimiter(true)
.about("multiple options") .about("multiple options")
.takes_value(true) .use_delimiter(true),
.multiple(true),
) )
.try_get_matches_from(vec!["", "--option=val1,val2,val3"]); .try_get_matches_from(vec!["", "--option=val1,val2,val3"]);
@ -536,10 +524,8 @@ fn sep_long_space() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.use_delimiter(true)
.about("multiple options") .about("multiple options")
.takes_value(true) .use_delimiter(true),
.multiple(true),
) )
.try_get_matches_from(vec!["", "--option", "val1,val2,val3"]); .try_get_matches_from(vec!["", "--option", "val1,val2,val3"]);
@ -561,9 +547,7 @@ fn sep_short_equals() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.use_delimiter(true) .use_delimiter(true),
.takes_value(true)
.multiple(true),
) )
.try_get_matches_from(vec!["", "-o=val1,val2,val3"]); .try_get_matches_from(vec!["", "-o=val1,val2,val3"]);
@ -585,9 +569,7 @@ fn sep_short_space() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.use_delimiter(true) .use_delimiter(true),
.takes_value(true)
.multiple(true),
) )
.try_get_matches_from(vec!["", "-o", "val1,val2,val3"]); .try_get_matches_from(vec!["", "-o", "val1,val2,val3"]);
@ -609,9 +591,7 @@ fn sep_short_no_space() {
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.about("multiple options") .about("multiple options")
.use_delimiter(true) .use_delimiter(true),
.takes_value(true)
.multiple(true),
) )
.try_get_matches_from(vec!["", "-oval1,val2,val3"]); .try_get_matches_from(vec!["", "-oval1,val2,val3"]);
@ -632,9 +612,7 @@ fn sep_positional() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.about("multiple options") .about("multiple options")
.takes_value(true) .use_delimiter(true),
.use_delimiter(true)
.multiple(true),
) )
.try_get_matches_from(vec!["", "val1,val2,val3"]); .try_get_matches_from(vec!["", "val1,val2,val3"]);
@ -656,7 +634,6 @@ fn different_sep() {
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.about("multiple options") .about("multiple options")
.takes_value(true)
.value_delimiter(";"), .value_delimiter(";"),
) )
.try_get_matches_from(vec!["", "--option=val1;val2;val3"]); .try_get_matches_from(vec!["", "--option=val1;val2;val3"]);
@ -719,6 +696,7 @@ fn no_sep_positional() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.about("multiple options") .about("multiple options")
.takes_value(true)
.use_delimiter(false), .use_delimiter(false),
) )
.try_get_matches_from(vec!["", "val1,val2,val3"]); .try_get_matches_from(vec!["", "val1,val2,val3"]);
@ -737,12 +715,16 @@ fn req_delimiter_long() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.multiple(true) .multiple_values(true)
.use_delimiter(true) .use_delimiter(true)
.require_delimiter(true) .require_delimiter(true),
.takes_value(true), )
.arg(
Arg::new("args")
.takes_value(true)
.multiple_values(true)
.index(1),
) )
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]); .try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]);
assert!(m.is_ok()); assert!(m.is_ok());
@ -766,12 +748,16 @@ fn req_delimiter_long_with_equal() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.multiple(true) .multiple_values(true)
.use_delimiter(true) .use_delimiter(true)
.require_delimiter(true) .require_delimiter(true),
.takes_value(true), )
.arg(
Arg::new("args")
.takes_value(true)
.multiple_values(true)
.index(1),
) )
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]); .try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]);
assert!(m.is_ok()); assert!(m.is_ok());
@ -795,12 +781,16 @@ fn req_delimiter_short_with_space() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.multiple(true) .multiple_values(true)
.use_delimiter(true) .use_delimiter(true)
.require_delimiter(true) .require_delimiter(true),
.takes_value(true), )
.arg(
Arg::new("args")
.takes_value(true)
.multiple_values(true)
.index(1),
) )
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]); .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
assert!(m.is_ok()); assert!(m.is_ok());
@ -824,12 +814,16 @@ fn req_delimiter_short_with_no_space() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.multiple(true) .multiple_values(true)
.use_delimiter(true) .use_delimiter(true)
.require_delimiter(true) .require_delimiter(true),
.takes_value(true), )
.arg(
Arg::new("args")
.takes_value(true)
.multiple_values(true)
.index(1),
) )
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "-oval1", "val2", "val3"]); .try_get_matches_from(vec!["", "-oval1", "val2", "val3"]);
assert!(m.is_ok()); assert!(m.is_ok());
@ -853,12 +847,16 @@ fn req_delimiter_short_with_equal() {
.arg( .arg(
Arg::new("option") Arg::new("option")
.short('o') .short('o')
.multiple(true) .multiple_values(true)
.use_delimiter(true) .use_delimiter(true)
.require_delimiter(true) .require_delimiter(true),
.takes_value(true), )
.arg(
Arg::new("args")
.takes_value(true)
.multiple_values(true)
.index(1),
) )
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]); .try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]);
assert!(m.is_ok()); assert!(m.is_ok());
@ -883,12 +881,17 @@ fn req_delimiter_complex() {
Arg::new("option") Arg::new("option")
.long("option") .long("option")
.short('o') .short('o')
.multiple(true) .multiple_values(true)
.multiple_occurrences(true)
.use_delimiter(true) .use_delimiter(true)
.require_delimiter(true) .require_delimiter(true),
.takes_value(true), )
.arg(
Arg::new("args")
.takes_value(true)
.multiple_values(true)
.index(1),
) )
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"", "",
"val1", "val1",
@ -943,7 +946,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(true) that is *not the last* positional argument, the last \ .multiple_values(true) 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() {
@ -953,7 +956,7 @@ fn low_index_positional_not_required() {
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.multiple(true), .multiple_values(true),
) )
.arg(Arg::new("target").index(2)) .arg(Arg::new("target").index(2))
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
@ -962,7 +965,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(true) \ #[should_panic = "Only one positional argument with .multiple_values(true) \
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 _ = App::new("lip") let _ = App::new("lip")
@ -971,14 +974,14 @@ fn low_index_positional_last_multiple_too() {
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.multiple(true), .multiple_values(true),
) )
.arg( .arg(
Arg::new("target") Arg::new("target")
.index(2) .index(2)
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec![""]); .try_get_matches_from(vec![""]);
} }
@ -987,7 +990,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(true)"] last positional argument may be set to .multiple_values(true)"]
fn low_index_positional_too_far_back() { fn low_index_positional_too_far_back() {
let _ = App::new("lip") let _ = App::new("lip")
.arg( .arg(
@ -995,7 +998,7 @@ fn low_index_positional_too_far_back() {
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.multiple(true), .multiple_values(true),
) )
.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))
@ -1010,7 +1013,7 @@ fn low_index_positional() {
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.multiple(true), .multiple_values(true),
) )
.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"]);
@ -1039,7 +1042,7 @@ fn low_index_positional_in_subcmd() {
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.multiple(true), .multiple_values(true),
) )
.arg(Arg::new("target").index(2).required(true)), .arg(Arg::new("target").index(2).required(true)),
) )
@ -1068,7 +1071,7 @@ fn low_index_positional_with_option() {
.required(true) .required(true)
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.arg(Arg::new("target").index(2).required(true)) .arg(Arg::new("target").index(2).required(true))
.arg(Arg::new("opt").long("option").takes_value(true)) .arg(Arg::new("opt").long("option").takes_value(true))
@ -1099,7 +1102,7 @@ fn low_index_positional_with_flag() {
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.multiple(true), .multiple_values(true),
) )
.arg(Arg::new("target").index(2).required(true)) .arg(Arg::new("target").index(2).required(true))
.arg(Arg::new("flg").long("flag")) .arg(Arg::new("flg").long("flag"))
@ -1128,7 +1131,7 @@ fn multiple_value_terminator_option() {
.short('f') .short('f')
.value_terminator(";") .value_terminator(";")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.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"]);
@ -1154,7 +1157,7 @@ fn multiple_value_terminator_option_other_arg() {
.short('f') .short('f')
.value_terminator(";") .value_terminator(";")
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
) )
.arg(Arg::new("other")) .arg(Arg::new("other"))
.arg(Arg::new("flag").short('F')) .arg(Arg::new("flag").short('F'))
@ -1179,7 +1182,7 @@ fn multiple_vals_with_hyphen() {
.arg( .arg(
Arg::new("cmds") Arg::new("cmds")
.takes_value(true) .takes_value(true)
.multiple(true) .multiple_values(true)
.allow_hyphen_values(true) .allow_hyphen_values(true)
.value_terminator(";"), .value_terminator(";"),
) )
@ -1205,13 +1208,7 @@ fn multiple_vals_with_hyphen() {
#[test] #[test]
fn issue_1480_max_values_consumes_extra_arg_1() { fn issue_1480_max_values_consumes_extra_arg_1() {
let res = App::new("prog") let res = App::new("prog")
.arg( .arg(Arg::new("field").max_values(1).long("field"))
Arg::new("field")
.takes_value(true)
.multiple(false)
.max_values(1)
.long("field"),
)
.arg(Arg::new("positional").required(true).index(1)) .arg(Arg::new("positional").required(true).index(1))
.try_get_matches_from(vec!["prog", "--field", "1", "file"]); .try_get_matches_from(vec!["prog", "--field", "1", "file"]);
@ -1221,13 +1218,7 @@ fn issue_1480_max_values_consumes_extra_arg_1() {
#[test] #[test]
fn issue_1480_max_values_consumes_extra_arg_2() { fn issue_1480_max_values_consumes_extra_arg_2() {
let res = App::new("prog") let res = App::new("prog")
.arg( .arg(Arg::new("field").max_values(1).long("field"))
Arg::new("field")
.takes_value(true)
.multiple(false)
.max_values(1)
.long("field"),
)
.try_get_matches_from(vec!["prog", "--field", "1", "2"]); .try_get_matches_from(vec!["prog", "--field", "1", "2"]);
assert!(res.is_err()); assert!(res.is_err());
@ -1237,13 +1228,7 @@ fn issue_1480_max_values_consumes_extra_arg_2() {
#[test] #[test]
fn issue_1480_max_values_consumes_extra_arg_3() { fn issue_1480_max_values_consumes_extra_arg_3() {
let res = App::new("prog") let res = App::new("prog")
.arg( .arg(Arg::new("field").max_values(1).long("field"))
Arg::new("field")
.takes_value(true)
.multiple(false)
.max_values(1)
.long("field"),
)
.try_get_matches_from(vec!["prog", "--field", "1", "2", "3"]); .try_get_matches_from(vec!["prog", "--field", "1", "2", "3"]);
assert!(res.is_err()); assert!(res.is_err());

View file

@ -107,7 +107,7 @@ fn positional_multiple() {
Arg::new("positional") Arg::new("positional")
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
]) ])
.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);
@ -128,7 +128,7 @@ fn positional_multiple_3() {
Arg::new("positional") Arg::new("positional")
.index(1) .index(1)
.takes_value(true) .takes_value(true)
.multiple(true), .multiple_values(true),
]) ])
.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);

View file

@ -74,7 +74,7 @@ fn possible_values_of_positional_multiple() {
.takes_value(true) .takes_value(true)
.possible_value("test123") .possible_value("test123")
.possible_value("test321") .possible_value("test321")
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec!["myprog", "test123", "test321"]); .try_get_matches_from(vec!["myprog", "test123", "test321"]);
@ -97,7 +97,7 @@ fn possible_values_of_positional_multiple_fail() {
.takes_value(true) .takes_value(true)
.possible_value("test123") .possible_value("test123")
.possible_value("test321") .possible_value("test321")
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec!["myprog", "test123", "notest"]); .try_get_matches_from(vec!["myprog", "test123", "notest"]);
@ -150,7 +150,7 @@ fn possible_values_of_option_multiple() {
.takes_value(true) .takes_value(true)
.possible_value("test123") .possible_value("test123")
.possible_value("test321") .possible_value("test321")
.multiple(true), .multiple_occurrences(true),
) )
.try_get_matches_from(vec!["", "--option", "test123", "--option", "test321"]); .try_get_matches_from(vec!["", "--option", "test123", "--option", "test321"]);
@ -174,7 +174,7 @@ fn possible_values_of_option_multiple_fail() {
.takes_value(true) .takes_value(true)
.possible_value("test123") .possible_value("test123")
.possible_value("test321") .possible_value("test321")
.multiple(true), .multiple_occurrences(true),
) )
.try_get_matches_from(vec!["", "--option", "test123", "--option", "notest"]); .try_get_matches_from(vec!["", "--option", "test123", "--option", "notest"]);
@ -259,7 +259,7 @@ fn case_insensitive_multiple() {
.takes_value(true) .takes_value(true)
.possible_value("test123") .possible_value("test123")
.possible_value("test321") .possible_value("test321")
.multiple(true) .multiple_values(true)
.case_insensitive(true), .case_insensitive(true),
) )
.try_get_matches_from(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]); .try_get_matches_from(vec!["pv", "--option", "TeSt123", "teST123", "tESt321"]);
@ -281,7 +281,7 @@ fn case_insensitive_multiple_fail() {
.takes_value(true) .takes_value(true)
.possible_value("test123") .possible_value("test123")
.possible_value("test321") .possible_value("test321")
.multiple(true), .multiple_values(true),
) )
.try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]); .try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]);

View file

@ -362,7 +362,12 @@ fn issue_1161_multiple_hyphen_hyphen() {
let res = App::new("myprog") let res = App::new("myprog")
.arg(Arg::new("eff").short('f')) .arg(Arg::new("eff").short('f'))
.arg(Arg::new("pea").short('p').takes_value(true)) .arg(Arg::new("pea").short('p').takes_value(true))
.arg(Arg::new("slop").takes_value(true).multiple(true).last(true)) .arg(
Arg::new("slop")
.takes_value(true)
.multiple_values(true)
.last(true),
)
.try_get_matches_from(vec![ .try_get_matches_from(vec![
"-f", "-f",
"-p=bob", "-p=bob",