Demangle interlinking flags

This commit is contained in:
ldm0 2021-02-24 15:07:57 +00:00
parent 2bedad2bfa
commit 886b873709
34 changed files with 306 additions and 65 deletions

View file

@ -229,6 +229,7 @@ fn main() {
.arg(Arg::new("v")
.short('v')
.multiple(true)
.takes_value(true)
.about("Sets the level of verbosity"))
.subcommand(App::new("test")
.about("controls testing features")

View file

@ -57,6 +57,7 @@ pub fn build_from_builder(c: &mut Criterion) {
.about("tests options")
.short('o')
.long("option")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences),
)
@ -99,6 +100,7 @@ pub fn build_from_builder(c: &mut Criterion) {
)
.arg(
Arg::new("positional3")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.about("tests positionals with specific values")
@ -114,6 +116,7 @@ pub fn build_from_builder(c: &mut Criterion) {
.arg(
Arg::new("multvalsmo")
.long("multvalsmo")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.about("Tests multiple values, not mult occs")
@ -122,6 +125,7 @@ pub fn build_from_builder(c: &mut Criterion) {
.arg(
Arg::new("minvals")
.long("minvals2")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.about("Tests 2 min vals")
@ -130,6 +134,7 @@ pub fn build_from_builder(c: &mut Criterion) {
.arg(
Arg::new("maxvals")
.long("maxvals3")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.about("Tests 3 max vals")
@ -144,6 +149,7 @@ pub fn build_from_builder(c: &mut Criterion) {
Arg::new("scoption")
.short('o')
.long("option")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.about("tests options"),

View file

@ -112,6 +112,7 @@ fn app_example7<'c>() -> App<'c> {
.arg(
Arg::new("input")
.about("the input file to use")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.setting(ArgSettings::Required)
@ -129,6 +130,7 @@ fn app_example8<'c>() -> App<'c> {
.arg(
Arg::new("input")
.about("the input file to use")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.setting(ArgSettings::Required)

View file

@ -326,6 +326,7 @@ where
]))
.arg(
arg("path")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences),
)
@ -350,6 +351,7 @@ where
.arg(
flag("color")
.value_name("WHEN")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::HidePossibleValues)
.possible_values(&["never", "auto", "always", "ansi"]),
)

View file

@ -265,6 +265,7 @@ fn build_cli() -> App<'static> {
.arg(
Arg::new("command")
.setting(ArgSettings::Required)
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences),
),

View file

@ -72,6 +72,7 @@ fn build_cli() -> App<'static> {
)
.arg(
Arg::new("command_with_args")
.takes_value(true)
.multiple_values(true)
.value_hint(ValueHint::CommandWithArguments),
)

View file

@ -56,6 +56,7 @@ pub fn build_app_with_value_hints() -> App<'static> {
)
.arg(
Arg::new("command_with_args")
.takes_value(true)
.multiple_values(true)
.value_hint(ValueHint::CommandWithArguments),
)

View file

@ -18,6 +18,7 @@ fn main() {
.about("turns up the awesome") // Displayed when showing help info
.short('a') // Trigger this arg with "-a"
.long("awesome") // Trigger this arg with "--awesome"
.takes_value(true)
.multiple(true) // This flag should allow multiple
// occurrences such as "-aaa" or "-a -a"
.requires("config") // Says, "If the user uses -a, they MUST

View file

@ -29,6 +29,7 @@ args:
help: demo flag argument
short: F
multiple: true
takes_value: true
global: true
# Conflicts, mutual overrides, and requirements can all be defined as a
# list, where the key is the name of the other argument

View file

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

View file

@ -40,6 +40,7 @@ fn main() {
.long("search")
.about("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
@ -48,6 +49,7 @@ fn main() {
.short('i')
.conflicts_with("search")
.about("view package information")
.takes_value(true)
.multiple_values(true),
),
)

View file

@ -329,7 +329,7 @@ pub enum AppSettings {
/// .setting(AppSettings::AllowMissingPositional)
/// .arg(Arg::new("foo"))
/// .arg(Arg::new("bar"))
/// .arg(Arg::new("baz").multiple(true))
/// .arg(Arg::new("baz").takes_value(true).multiple(true))
/// .get_matches_from(vec![
/// "prog", "foo", "bar", "baz1", "baz2", "baz3"
/// ]);
@ -348,7 +348,7 @@ pub enum AppSettings {
/// .setting(AppSettings::AllowMissingPositional)
/// .arg(Arg::new("foo"))
/// .arg(Arg::new("bar"))
/// .arg(Arg::new("baz").multiple(true))
/// .arg(Arg::new("baz").takes_value(true).multiple(true))
/// .get_matches_from(vec![
/// "prog", "--", "baz1", "baz2", "baz3"
/// ]);

View file

@ -7,7 +7,7 @@ pub(crate) fn assert_arg(arg: &Arg) {
// TODO: this check should be recursive
assert!(
!arg.blacklist.iter().any(|x| *x == arg.id),
"Argument '{}' cannot conflict with itarg",
"Argument '{}' cannot conflict with itself",
arg.name,
);
@ -42,4 +42,44 @@ pub(crate) fn assert_arg(arg: &Arg) {
arg.name
);
}
assert_app_flag(arg);
}
fn assert_app_flag(arg: &Arg) {
use ArgSettings::*;
if arg.is_set(AllowEmptyValues) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(RequireDelimiter) {
assert!(arg.is_set(TakesValue));
assert!(arg.is_set(UseValueDelimiter));
}
if arg.is_set(HidePossibleValues) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(AllowHyphenValues) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(RequireEquals) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(Last) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(HideDefaultValue) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(MultipleValues) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(HideEnv) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(HideEnvValues) {
assert!(arg.is_set(TakesValue));
}
if arg.is_set(IgnoreCase) {
assert!(arg.is_set(TakesValue));
}
}

View file

@ -1799,6 +1799,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg};
/// let m = App::new("prog")
/// .arg(Arg::new("cmds")
/// .takes_value(true)
/// .multiple(true)
/// .allow_hyphen_values(true)
/// .value_terminator(";"))
@ -3137,7 +3138,7 @@ impl<'help> Arg<'help> {
/// **NOTE**: This setting only applies to positional arguments, and has no affect on FLAGS /
/// OPTIONS
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// **CAUTION:** Using this setting *and* having child subcommands is not
/// recommended with the exception of *also* using [`AppSettings::ArgsNegateSubcommands`]
@ -3149,6 +3150,7 @@ impl<'help> Arg<'help> {
/// ```rust
/// # use clap::{Arg, ArgSettings};
/// Arg::new("args")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::Last)
/// # ;
/// ```
@ -3162,6 +3164,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("first"))
/// .arg(Arg::new("second"))
/// .arg(Arg::new("third")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::Last))
/// .try_get_matches_from(vec![
/// "prog", "one", "--", "three"
@ -3182,6 +3185,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("first"))
/// .arg(Arg::new("second"))
/// .arg(Arg::new("third")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::Last))
/// .try_get_matches_from(vec![
/// "prog", "one", "two", "three"
@ -3320,7 +3324,7 @@ impl<'help> Arg<'help> {
/// Allows values which start with a leading hyphen (`-`)
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// **WARNING**: Take caution when using this setting combined with
/// [`ArgSettings::MultipleValues`], as this becomes ambiguous `$ prog --arg -- -- val`. All
@ -3340,6 +3344,7 @@ impl<'help> Arg<'help> {
/// ```rust
/// # use clap::{Arg, ArgSettings};
/// Arg::new("pattern")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::AllowHyphenValues)
/// # ;
/// ```
@ -3348,6 +3353,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("pat")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::AllowHyphenValues)
/// .long("pattern"))
/// .get_matches_from(vec![
@ -3389,7 +3395,7 @@ impl<'help> Arg<'help> {
/// Requires that options use the `--option=val` syntax (i.e. an equals between the option and
/// associated value) **Default:** `false`
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// # Examples
///
@ -3397,6 +3403,7 @@ impl<'help> Arg<'help> {
/// # use clap::{Arg, ArgSettings};
/// Arg::new("config")
/// .long("config")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::RequireEquals)
/// # ;
/// ```
@ -3408,6 +3415,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ArgSettings};
/// let res = App::new("prog")
/// .arg(Arg::new("cfg")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::RequireEquals)
/// .long("config"))
/// .try_get_matches_from(vec![
@ -3424,6 +3432,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ErrorKind, ArgSettings};
/// let res = App::new("prog")
/// .arg(Arg::new("cfg")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::RequireEquals)
/// .long("config"))
/// .try_get_matches_from(vec![
@ -3439,8 +3448,7 @@ impl<'help> Arg<'help> {
#[inline]
pub fn require_equals(self, r: bool) -> Self {
if r {
self.unset_setting(ArgSettings::AllowEmptyValues)
.setting(ArgSettings::RequireEquals)
self.setting(ArgSettings::RequireEquals)
} else {
self.unset_setting(ArgSettings::RequireEquals)
}
@ -3502,7 +3510,7 @@ impl<'help> Arg<'help> {
///
/// **NOTE:** The default is `false`.
///
/// **NOTE:** Setting this implies [`ArgSettings::UseValueDelimiter`] and
/// **NOTE:** Setting this requires [`ArgSettings::UseValueDelimiter`] and
/// [`ArgSettings::TakesValue`]
///
/// **NOTE:** It's a good idea to inform the user that use of a delimiter is required, either
@ -3518,6 +3526,8 @@ impl<'help> Arg<'help> {
/// let delims = App::new("prog")
/// .arg(Arg::new("opt")
/// .short('o')
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::UseValueDelimiter)
/// .setting(ArgSettings::RequireDelimiter)
/// .setting(ArgSettings::MultipleValues))
/// .get_matches_from(vec![
@ -3534,6 +3544,8 @@ impl<'help> Arg<'help> {
/// let res = App::new("prog")
/// .arg(Arg::new("opt")
/// .short('o')
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::UseValueDelimiter)
/// .setting(ArgSettings::RequireDelimiter))
/// .try_get_matches_from(vec![
/// "prog", "-o", "val1", "val2", "val3",
@ -3555,6 +3567,7 @@ impl<'help> Arg<'help> {
/// let delims = App::new("prog")
/// .arg(Arg::new("opt")
/// .short('o')
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues))
/// .get_matches_from(vec![
/// "prog", "-o", "val1", "val2", "val3",
@ -3568,9 +3581,7 @@ impl<'help> Arg<'help> {
#[inline]
pub fn require_delimiter(self, d: bool) -> Self {
if d {
self.takes_value(true)
.setting(ArgSettings::UseValueDelimiter)
.setting(ArgSettings::RequireDelimiter)
self.setting(ArgSettings::RequireDelimiter)
} else {
self.unset_setting(ArgSettings::RequireDelimiter)
}
@ -3582,13 +3593,14 @@ impl<'help> Arg<'help> {
/// This is useful for args with many values, or ones which are explained elsewhere in the
/// help text.
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// # Examples
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("config")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HidePossibleValues)
/// # ;
/// ```
@ -3599,6 +3611,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("mode")
/// .long("mode")
/// .possible_values(&["fast", "slow"])
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HidePossibleValues));
/// ```
/// If we were to run the above program with `--help` the `[values: fast, slow]` portion of
@ -3616,13 +3629,14 @@ impl<'help> Arg<'help> {
///
/// This is useful when default behavior of an arg is explained elsewhere in the help text.
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// # Examples
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("config")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HideDefaultValue)
/// # ;
/// ```
@ -3633,6 +3647,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("host")
/// .long("host")
/// .default_value("localhost")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HideDefaultValue));
///
/// ```
@ -3698,7 +3713,7 @@ impl<'help> Arg<'help> {
/// When used with [`Arg::possible_values`] it allows the argument value to pass validation even
/// if the case differs from that of the specified `possible_value`.
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// # Examples
///
@ -3707,6 +3722,7 @@ impl<'help> Arg<'help> {
/// let m = App::new("pv")
/// .arg(Arg::new("option")
/// .long("--option")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::IgnoreCase)
/// .possible_value("test123"))
/// .get_matches_from(vec![
@ -3725,6 +3741,7 @@ impl<'help> Arg<'help> {
/// .short('o')
/// .long("--option")
/// .setting(ArgSettings::IgnoreCase)
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .possible_value("test123")
/// .possible_value("test321"))
@ -3809,13 +3826,14 @@ impl<'help> Arg<'help> {
///
/// This is useful when the variable option is explained elsewhere in the help text.
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// # Examples
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("config")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HideEnv)
/// # ;
/// ```
@ -3826,6 +3844,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("mode")
/// .long("mode")
/// .env("MODE")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HideEnv));
///
/// ```
@ -3846,14 +3865,15 @@ impl<'help> Arg<'help> {
///
/// This is useful when ENV vars contain sensitive values.
///
/// **NOTE:** Setting this implies [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`]
///
/// # Examples
///
/// ```rust
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("config")
/// .setting(ArgSettings::HideDefaultValue)
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HideEnvValues)
/// # ;
/// ```
///
@ -3863,6 +3883,7 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("host")
/// .long("host")
/// .env("CONNECT")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::HideEnvValues));
///
/// ```
@ -3987,6 +4008,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("debug")
/// .short('d')
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// # ;
/// ```
@ -4012,7 +4034,8 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::MultipleValues) // implies TakesValue
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .get_matches_from(vec![
/// "prog", "-F", "file1", "file2", "file3"
@ -4029,7 +4052,8 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ErrorKind, ArgSettings};
/// let res = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::MultipleValues) // implies TakesValue
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .try_get_matches_from(vec![
/// "prog", "-F", "file1", "-F", "file2", "-F", "file3"
@ -4045,7 +4069,8 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ArgSettings};
/// let m = App::new("prog")
/// .arg(Arg::new("file")
/// .setting(ArgSettings::MultipleValues) // implies TakesValue
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::MultipleValues)
/// .short('F'))
/// .arg(Arg::new("word")
/// .index(1))
@ -4123,7 +4148,7 @@ impl<'help> Arg<'help> {
///
/// **NOTE:** By default empty values are *not* allowed
///
/// **NOTE:** Implicitly sets [`ArgSettings::TakesValue`]
/// **NOTE:** Setting this requires [`ArgSettings::TakesValue`].
///
/// # Examples
///
@ -4131,6 +4156,7 @@ impl<'help> Arg<'help> {
/// # use clap::{App, Arg, ArgSettings};
/// Arg::new("file")
/// .long("file")
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::AllowEmptyValues)
/// # ;
/// ```
@ -4158,7 +4184,8 @@ impl<'help> Arg<'help> {
/// .arg(Arg::new("cfg")
/// .long("config")
/// .short('v')
/// .setting(ArgSettings::AllowEmptyValues)) // implies TakesValue
/// .setting(ArgSettings::TakesValue)
/// .setting(ArgSettings::AllowEmptyValues))
/// .try_get_matches_from(vec![
/// "prog", "--config="
/// ]);
@ -4259,16 +4286,20 @@ impl<'help> Arg<'help> {
/// may not be exactly what you are expecting and using [`AppSettings::TrailingVarArg`]
/// may be more appropriate.
///
/// **NOTE:** Implicitly sets [`Arg::multiple(true)`], [`Arg::allow_hyphen_values(true)`], and
/// **NOTE:** Implicitly sets [`Arg::takes_value(true)`] [`Arg::multiple(true)`], [`Arg::allow_hyphen_values(true)`], and
/// [`Arg::last(true)`] when set to `true`
///
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
/// [`Arg::allow_hyphen_values(true)`]: ./struct.Arg.html#method.allow_hyphen_values
/// [`Arg::last(true)`]: ./struct.Arg.html#method.last
/// [`AppSettings::TrailingVarArg`]: ./enum.AppSettings.html#variant.TrailingVarArg
#[inline]
pub fn raw(self, raw: bool) -> Self {
self.multiple(raw).allow_hyphen_values(raw).last(raw)
self.takes_value(true)
.multiple(raw)
.allow_hyphen_values(raw)
.last(raw)
}
/// Hides an argument from short help message output.
@ -4503,6 +4534,7 @@ impl<'help> Arg<'help> {
/// .setting(AppSettings::TrailingVarArg)
/// .arg(
/// Arg::new("command")
/// .takes_value(true)
/// .multiple(true)
/// .value_hint(ValueHint::CommandWithArguments)
/// )
@ -4954,6 +4986,7 @@ mod test {
fn option_display3() {
let o2 = Arg::new("opt")
.short('o')
.takes_value(true)
.multiple(true)
.value_names(&["file", "name"]);
@ -5008,6 +5041,7 @@ mod test {
fn positiona_display_mult() {
let p = Arg::new("pos")
.index(1)
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues);
assert_eq!(&*format!("{}", p), "<pos>...");

View file

@ -8,26 +8,26 @@ bitflags! {
struct Flags: u32 {
const REQUIRED = 1;
const MULTIPLE_OCC = 1 << 1;
const EMPTY_VALS = 1 << 2 | Self::TAKES_VAL.bits;
const EMPTY_VALS = 1 << 2;
const GLOBAL = 1 << 3;
const HIDDEN = 1 << 4;
const TAKES_VAL = 1 << 5;
const USE_DELIM = 1 << 6;
const NEXT_LINE_HELP = 1 << 7;
const R_UNLESS_ALL = 1 << 8;
const REQ_DELIM = 1 << 9 | Self::TAKES_VAL.bits | Self::USE_DELIM.bits;
const REQ_DELIM = 1 << 9;
const DELIM_NOT_SET = 1 << 10;
const HIDE_POS_VALS = 1 << 11 | Self::TAKES_VAL.bits;
const ALLOW_TAC_VALS = 1 << 12 | Self::TAKES_VAL.bits;
const REQUIRE_EQUALS = 1 << 13 | Self::TAKES_VAL.bits;
const LAST = 1 << 14 | Self::TAKES_VAL.bits;
const HIDE_DEFAULT_VAL = 1 << 15 | Self::TAKES_VAL.bits;
const HIDE_POS_VALS = 1 << 11;
const ALLOW_TAC_VALS = 1 << 12;
const REQUIRE_EQUALS = 1 << 13;
const LAST = 1 << 14;
const HIDE_DEFAULT_VAL = 1 << 15;
const CASE_INSENSITIVE = 1 << 16;
const HIDE_ENV_VALS = 1 << 17;
const HIDDEN_SHORT_H = 1 << 18;
const HIDDEN_LONG_H = 1 << 19;
const MULTIPLE_VALS = 1 << 20 | Self::TAKES_VAL.bits;
const HIDE_ENV = 1 << 21 | Self::TAKES_VAL.bits;
const MULTIPLE_VALS = 1 << 20;
const HIDE_ENV = 1 << 21;
}
}

View file

@ -71,6 +71,7 @@ impl<'help> UsageParser<'help> {
};
if !arg.has_switch() && arg.is_set(ArgSettings::MultipleOccurrences) {
// We had a positional and need to set mult vals too
arg.settings.set(ArgSettings::TakesValue);
arg.settings.set(ArgSettings::MultipleValues);
}
debug!("UsageParser::parse: vals...{:?}", arg.val_names);

View file

@ -461,7 +461,7 @@ macro_rules! clap_app {
$crate::clap_app!{ @arg ($arg.value_name(stringify!($var))) (+) $($tail)* }
};
(@arg ($arg:expr) $modes:tt ... $($tail:tt)*) => {
$crate::clap_app!{ @arg ($arg) $modes +multiple $($tail)* }
$crate::clap_app!{ @arg ($arg) $modes +multiple +takes_value $($tail)* }
};
// Shorthand magic
(@arg ($arg:expr) $modes:tt #{$n:expr, $m:expr} $($tail:tt)*) => {

View file

@ -155,6 +155,7 @@ pub enum ErrorKind {
/// # use clap::{App, Arg, ErrorKind};
/// let result = App::new("prog")
/// .arg(Arg::new("arg")
/// .takes_value(true)
/// .multiple(true)
/// .max_values(2))
/// .try_get_matches_from(vec!["prog", "too", "many", "values"]);

View file

@ -40,6 +40,7 @@ pub(crate) struct SubCommand {
/// .takes_value(true))
/// .arg(Arg::new("debug")
/// .short('d')
/// .takes_value(true)
/// .multiple(true))
/// .arg(Arg::new("cfg")
/// .short('c')

View file

@ -794,6 +794,7 @@ impl<'help, 'app> Parser<'help, 'app> {
if help_help {
let mut pb = Arg::new("subcommand")
.index(1)
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.about("The subcommand whose help message to display");

View file

@ -951,6 +951,8 @@ fn aaos_opts_mult() {
.arg(
Arg::from("--opt [val]... 'some option'")
.number_of_values(1)
.takes_value(true)
.use_delimiter(true)
.require_delimiter(true),
)
.try_get_matches_from(vec!["", "--opt=some", "--opt=other", "--opt=one,two"]);

View file

@ -96,6 +96,7 @@ fn opt_s_no_space_mult_no_delim() {
.arg(
Arg::new("option")
.short('o')
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues),
)
.try_get_matches_from(vec!["", "-o", "val1,val2,val3"]);
@ -114,9 +115,9 @@ fn opt_eq_mult_def_delim() {
.arg(
Arg::new("option")
.long("opt")
.takes_value(true)
.multiple(true)
.use_delimiter(true)
.setting(ArgSettings::TakesValue),
.use_delimiter(true),
)
.try_get_matches_from(vec!["", "--opt=val1,val2,val3"]);

View file

@ -12,6 +12,7 @@ args:
- option:
short: o
long: option
takes_value: true
multiple: true
about: tests options
- positional:
@ -26,6 +27,7 @@ args:
- flag:
short: f
long: flag
takes_value: true
multiple: true
about: tests flags
global: true
@ -71,7 +73,9 @@ args:
- multvalsdelim:
long: multvalsdelim
about: Tests multiple values with required delimiter
takes_value: true
multiple: true
use_delimiter: true
require_delimiter: true
- singlealias:
long: singlealias

View file

@ -12,5 +12,6 @@ args:
- opt:
short: o
long: option
takes_value: true
multiple: true
about: tests options

View file

@ -443,6 +443,7 @@ fn flag_subcommand_long_short_normal_usage_string() {
.long("search")
.about("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
@ -451,6 +452,7 @@ fn flag_subcommand_long_short_normal_usage_string() {
.short('i')
.conflicts_with("search")
.about("view package information")
.takes_value(true)
.multiple_values(true),
),
);
@ -497,6 +499,7 @@ fn flag_subcommand_long_normal_usage_string() {
.long("search")
.about("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
@ -505,6 +508,7 @@ fn flag_subcommand_long_normal_usage_string() {
.short('i')
.conflicts_with("search")
.about("view package information")
.takes_value(true)
.multiple_values(true),
),
);
@ -551,6 +555,7 @@ fn flag_subcommand_short_normal_usage_string() {
.long("search")
.about("search locally installed packages for matching strings")
.conflicts_with("info")
.takes_value(true)
.multiple_values(true),
)
.arg(
@ -559,6 +564,7 @@ fn flag_subcommand_short_normal_usage_string() {
.short('i')
.conflicts_with("search")
.about("view package information")
.takes_value(true)
.multiple_values(true),
),
);

View file

@ -17,6 +17,7 @@ fn issue_1076() {
Arg::new("GLOBAL_FLAG")
.long("global-flag")
.about("Specifies something needed by the subcommands")
.takes_value(true)
.multiple(true)
.global(true),
)

View file

@ -5,7 +5,12 @@ use clap::{App, AppSettings, Arg};
#[test]
fn grouped_value_works() {
let m = App::new("cli")
.arg(Arg::new("option").long("option").multiple(true))
.arg(
Arg::new("option")
.long("option")
.takes_value(true)
.multiple(true),
)
.get_matches_from(&[
"cli",
"--option",
@ -30,7 +35,12 @@ fn issue_1026() {
let m = App::new("cli")
.arg(Arg::new("server").short('s').takes_value(true))
.arg(Arg::new("user").short('u').takes_value(true))
.arg(Arg::new("target").long("target").multiple(true))
.arg(
Arg::new("target")
.long("target")
.takes_value(true)
.multiple(true),
)
.get_matches_from(&[
"backup", "-s", "server", "-u", "user", "--target", "target1", "file1", "file2",
"file3", "--target", "target2", "file4", "file5", "file6", "file7", "--target",
@ -96,7 +106,12 @@ fn grouped_value_short_flag_delimiter() {
#[test]
fn grouped_value_positional_arg() {
let m = App::new("multiple_values")
.arg(Arg::new("pos").about("multiple positionals").multiple(true))
.arg(
Arg::new("pos")
.about("multiple positionals")
.takes_value(true)
.multiple(true),
)
.get_matches_from(vec![
"myprog", "val1", "val2", "val3", "val4", "val5", "val6",
]);
@ -114,6 +129,7 @@ fn grouped_value_multiple_positional_arg() {
.arg(
Arg::new("pos2")
.about("multiple positionals")
.takes_value(true)
.multiple(true),
)
.get_matches_from(vec![
@ -133,6 +149,7 @@ fn grouped_value_multiple_positional_arg_last_multiple() {
.arg(
Arg::new("pos2")
.about("multiple positionals")
.takes_value(true)
.multiple(true)
.last(true),
)

View file

@ -758,6 +758,7 @@ fn args_with_last_usage() {
.arg(
Arg::new("pass through args")
.about("Any arguments you wish to pass to the being profiled.")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::MultipleValues)
.setting(ArgSettings::MultipleOccurrences)
.setting(ArgSettings::Last)
@ -1209,7 +1210,12 @@ fn issue_702_multiple_values() {
.author("foo")
.about("bar")
.arg(Arg::new("arg1").about("some option"))
.arg(Arg::new("arg2").multiple(true).about("some option"))
.arg(
Arg::new("arg2")
.takes_value(true)
.multiple(true)
.about("some option"),
)
.arg(
Arg::new("some")
.about("some option")
@ -1511,7 +1517,13 @@ fn last_arg_mult_usage() {
.version("0.1")
.arg(Arg::new("TARGET").required(true).about("some"))
.arg(Arg::new("CORPUS").about("some"))
.arg(Arg::new("ARGS").multiple(true).last(true).about("some"));
.arg(
Arg::new("ARGS")
.takes_value(true)
.multiple(true)
.last(true)
.about("some"),
);
assert!(utils::compare_output(app, "last --help", LAST_ARG, false));
}
@ -1523,6 +1535,7 @@ fn last_arg_mult_usage_req() {
.arg(Arg::new("CORPUS").about("some"))
.arg(
Arg::new("ARGS")
.takes_value(true)
.multiple(true)
.last(true)
.required(true)
@ -1545,6 +1558,7 @@ fn last_arg_mult_usage_req_with_sc() {
.arg(Arg::new("CORPUS").about("some"))
.arg(
Arg::new("ARGS")
.takes_value(true)
.multiple(true)
.last(true)
.required(true)
@ -1566,7 +1580,13 @@ fn last_arg_mult_usage_with_sc() {
.setting(AppSettings::ArgsNegateSubcommands)
.arg(Arg::new("TARGET").required(true).about("some"))
.arg(Arg::new("CORPUS").about("some"))
.arg(Arg::new("ARGS").multiple(true).last(true).about("some"))
.arg(
Arg::new("ARGS")
.takes_value(true)
.multiple(true)
.last(true)
.about("some"),
)
.subcommand(App::new("test").about("some"));
assert!(utils::compare_output(
app,
@ -1680,6 +1700,8 @@ fn issue_1052_require_delim_help() {
.version("1.3")
.arg(
Arg::from("-f, --fake <some> <val> 'some help'")
.takes_value(true)
.use_delimiter(true)
.require_delimiter(true)
.value_delimiter(":"),
);
@ -1804,6 +1826,8 @@ fn custom_headers_headers() {
.version("1.4")
.arg(
Arg::from("-f, --fake <some> <val> 'some help'")
.takes_value(true)
.use_delimiter(true)
.require_delimiter(true)
.value_delimiter(":"),
)
@ -1856,6 +1880,8 @@ fn multiple_custom_help_headers() {
.version("1.4")
.arg(
Arg::from("-f, --fake <some> <val> 'some help'")
.takes_value(true)
.use_delimiter(true)
.require_delimiter(true)
.value_delimiter(":"),
)
@ -1970,7 +1996,12 @@ fn issue_1364_no_short_options() {
.value_name("BAZ")
.hidden_short_help(true),
)
.arg(Arg::new("files").value_name("FILES").multiple(true));
.arg(
Arg::new("files")
.value_name("FILES")
.takes_value(true)
.multiple(true),
);
assert!(utils::compare_output(app, "demo -h", ISSUE_1364, false));
}

View file

@ -350,7 +350,12 @@ fn option_max_more() {
#[test]
fn positional() {
let m = App::new("multiple_values")
.arg(Arg::new("pos").about("multiple positionals").multiple(true))
.arg(
Arg::new("pos")
.about("multiple positionals")
.takes_value(true)
.multiple(true),
)
.try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
assert!(m.is_ok());
@ -627,6 +632,7 @@ fn sep_positional() {
.arg(
Arg::new("option")
.about("multiple options")
.takes_value(true)
.use_delimiter(true)
.multiple(true),
)
@ -736,7 +742,7 @@ fn req_delimiter_long() {
.require_delimiter(true)
.takes_value(true),
)
.arg(Arg::new("args").multiple(true).index(1))
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]);
assert!(m.is_ok());
@ -765,7 +771,7 @@ fn req_delimiter_long_with_equal() {
.require_delimiter(true)
.takes_value(true),
)
.arg(Arg::new("args").multiple(true).index(1))
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]);
assert!(m.is_ok());
@ -794,7 +800,7 @@ fn req_delimiter_short_with_space() {
.require_delimiter(true)
.takes_value(true),
)
.arg(Arg::new("args").multiple(true).index(1))
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
assert!(m.is_ok());
@ -823,7 +829,7 @@ fn req_delimiter_short_with_no_space() {
.require_delimiter(true)
.takes_value(true),
)
.arg(Arg::new("args").multiple(true).index(1))
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "-oval1", "val2", "val3"]);
assert!(m.is_ok());
@ -852,7 +858,7 @@ fn req_delimiter_short_with_equal() {
.require_delimiter(true)
.takes_value(true),
)
.arg(Arg::new("args").multiple(true).index(1))
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]);
assert!(m.is_ok());
@ -882,7 +888,7 @@ fn req_delimiter_complex() {
.require_delimiter(true)
.takes_value(true),
)
.arg(Arg::new("args").multiple(true).index(1))
.arg(Arg::new("args").takes_value(true).multiple(true).index(1))
.try_get_matches_from(vec![
"",
"val1",
@ -942,7 +948,13 @@ positional argument (i.e. the one with the highest index) *must* have \
.required(true) or .last(true) set."]
fn low_index_positional_not_required() {
let _ = App::new("lip")
.arg(Arg::new("files").index(1).required(true).multiple(true))
.arg(
Arg::new("files")
.index(1)
.takes_value(true)
.required(true)
.multiple(true),
)
.arg(Arg::new("target").index(2))
.try_get_matches_from(vec![""]);
}
@ -954,8 +966,20 @@ fn low_index_positional_not_required() {
set is allowed per command, unless the second one also has .last(true) set"]
fn low_index_positional_last_multiple_too() {
let _ = App::new("lip")
.arg(Arg::new("files").index(1).required(true).multiple(true))
.arg(Arg::new("target").index(2).required(true).multiple(true))
.arg(
Arg::new("files")
.index(1)
.takes_value(true)
.required(true)
.multiple(true),
)
.arg(
Arg::new("target")
.index(2)
.takes_value(true)
.required(true)
.multiple(true),
)
.try_get_matches_from(vec![""]);
}
@ -966,7 +990,13 @@ fn low_index_positional_last_multiple_too() {
last positional argument may be set to .multiple(true)"]
fn low_index_positional_too_far_back() {
let _ = App::new("lip")
.arg(Arg::new("files").index(1).required(true).multiple(true))
.arg(
Arg::new("files")
.index(1)
.takes_value(true)
.required(true)
.multiple(true),
)
.arg(Arg::new("target").required(true).index(2))
.arg(Arg::new("target2").required(true).index(3))
.try_get_matches_from(vec![""]);
@ -975,7 +1005,13 @@ fn low_index_positional_too_far_back() {
#[test]
fn low_index_positional() {
let m = App::new("lip")
.arg(Arg::new("files").index(1).required(true).multiple(true))
.arg(
Arg::new("files")
.index(1)
.takes_value(true)
.required(true)
.multiple(true),
)
.arg(Arg::new("target").index(2).required(true))
.try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target"]);
@ -998,7 +1034,13 @@ fn low_index_positional_in_subcmd() {
let m = App::new("lip")
.subcommand(
App::new("test")
.arg(Arg::new("files").index(1).required(true).multiple(true))
.arg(
Arg::new("files")
.index(1)
.takes_value(true)
.required(true)
.multiple(true),
)
.arg(Arg::new("target").index(2).required(true)),
)
.try_get_matches_from(vec!["lip", "test", "file1", "file2", "file3", "target"]);
@ -1021,7 +1063,13 @@ fn low_index_positional_in_subcmd() {
#[test]
fn low_index_positional_with_option() {
let m = App::new("lip")
.arg(Arg::new("files").required(true).index(1).multiple(true))
.arg(
Arg::new("files")
.required(true)
.index(1)
.takes_value(true)
.multiple(true),
)
.arg(Arg::new("target").index(2).required(true))
.arg(Arg::new("opt").long("option").takes_value(true))
.try_get_matches_from(vec![
@ -1046,7 +1094,13 @@ fn low_index_positional_with_option() {
#[test]
fn low_index_positional_with_flag() {
let m = App::new("lip")
.arg(Arg::new("files").index(1).required(true).multiple(true))
.arg(
Arg::new("files")
.index(1)
.takes_value(true)
.required(true)
.multiple(true),
)
.arg(Arg::new("target").index(2).required(true))
.arg(Arg::new("flg").long("flag"))
.try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target", "--flag"]);
@ -1073,6 +1127,7 @@ fn multiple_value_terminator_option() {
Arg::new("files")
.short('f')
.value_terminator(";")
.takes_value(true)
.multiple(true),
)
.arg(Arg::new("other"))
@ -1098,6 +1153,7 @@ fn multiple_value_terminator_option_other_arg() {
Arg::new("files")
.short('f')
.value_terminator(";")
.takes_value(true)
.multiple(true),
)
.arg(Arg::new("other"))
@ -1122,6 +1178,7 @@ fn multiple_vals_with_hyphen() {
let res = App::new("do")
.arg(
Arg::new("cmds")
.takes_value(true)
.multiple(true)
.allow_hyphen_values(true)
.value_terminator(";"),

View file

@ -47,6 +47,7 @@ fn require_equals_min_values_zero() {
let res = App::new("prog")
.arg(
Arg::new("cfg")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::RequireEquals)
.min_values(0)
.long("config"),
@ -64,6 +65,7 @@ fn double_hyphen_as_value() {
let res = App::new("prog")
.arg(
Arg::new("cfg")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::AllowHyphenValues)
.long("config"),
)
@ -77,6 +79,7 @@ fn require_equals_no_empty_values_fail() {
let res = App::new("prog")
.arg(
Arg::new("cfg")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::RequireEquals)
.long("config"),
)
@ -91,6 +94,7 @@ fn require_equals_empty_vals_pass() {
let res = App::new("prog")
.arg(
Arg::new("cfg")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::RequireEquals)
.setting(ArgSettings::AllowEmptyValues)
.long("config"),
@ -104,6 +108,7 @@ fn require_equals_pass() {
let res = App::new("prog")
.arg(
Arg::new("cfg")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::RequireEquals)
.long("config"),
)
@ -284,7 +289,11 @@ fn multiple_vals_pos_arg_delim() {
#[test]
fn require_delims_no_delim() {
let r = App::new("mvae")
.arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::RequireDelimiter))
.arg(
Arg::from("-o [opt]... 'some opt'")
.setting(ArgSettings::UseValueDelimiter)
.setting(ArgSettings::RequireDelimiter),
)
.arg(Arg::from("[file] 'some file'"))
.try_get_matches_from(vec!["mvae", "-o", "1", "2", "some"]);
assert!(r.is_err());
@ -295,7 +304,11 @@ fn require_delims_no_delim() {
#[test]
fn require_delims() {
let r = App::new("mvae")
.arg(Arg::from("-o [opt]... 'some opt'").setting(ArgSettings::RequireDelimiter))
.arg(
Arg::from("-o [opt]... 'some opt'")
.setting(ArgSettings::UseValueDelimiter)
.setting(ArgSettings::RequireDelimiter),
)
.arg(Arg::from("[file] 'some file'"))
.try_get_matches_from(vec!["", "-o", "1,2", "some"]);
assert!(r.is_ok());
@ -359,6 +372,7 @@ fn leading_hyphen_with_only_pos_follows() {
.arg(
Arg::from("-o [opt]... 'some opt'")
.number_of_values(1)
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::AllowHyphenValues),
)
.arg("[arg] 'some arg'")
@ -400,6 +414,7 @@ fn issue_1047_min_zero_vals_default_val() {
Arg::new("del")
.short('d')
.long("del")
.setting(ArgSettings::TakesValue)
.setting(ArgSettings::RequireEquals)
.min_values(0)
.default_missing_value("default"),

View file

@ -104,7 +104,10 @@ fn positional_multiple() {
let r = App::new("positional_multiple")
.args(&[
Arg::from("-f, --flag 'some flag'"),
Arg::new("positional").index(1).multiple(true),
Arg::new("positional")
.index(1)
.takes_value(true)
.multiple(true),
])
.try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]);
assert!(r.is_ok(), "{:#?}", r);
@ -122,7 +125,10 @@ fn positional_multiple_3() {
let r = App::new("positional_multiple")
.args(&[
Arg::from("-f, --flag 'some flag'"),
Arg::new("positional").index(1).multiple(true),
Arg::new("positional")
.index(1)
.takes_value(true)
.multiple(true),
])
.try_get_matches_from(vec!["", "test1", "test2", "test3", "--flag"]);
assert!(r.is_ok(), "{:#?}", r);

View file

@ -41,6 +41,8 @@ fn mult_option_require_delim_overrides_itself() {
Arg::from("--opt [val]... 'some option'")
.overrides_with("opt")
.number_of_values(1)
.takes_value(true)
.use_delimiter(true)
.require_delimiter(true),
)
.try_get_matches_from(vec!["", "--opt=some", "--opt=other", "--opt=one,two"]);

View file

@ -71,6 +71,7 @@ fn possible_values_of_positional_multiple() {
.arg(
Arg::new("positional")
.index(1)
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple(true),
@ -93,6 +94,7 @@ fn possible_values_of_positional_multiple_fail() {
.arg(
Arg::new("positional")
.index(1)
.takes_value(true)
.possible_value("test123")
.possible_value("test321")
.multiple(true),

View file

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