mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +00:00
fix!: Remove multiple occurrences in favor of Append/Count
For num_vals and friends, this only implements hacks until #2688 Fixes #3021
This commit is contained in:
parent
8c7fe8bb2f
commit
6f03b4f948
23 changed files with 101 additions and 217 deletions
|
@ -451,12 +451,7 @@ fn write_opts_of(p: &Command, p_global: Option<&Command>) -> String {
|
|||
let help = o.get_help().map_or(String::new(), escape_help);
|
||||
let conflicts = arg_conflicts(p, o, p_global);
|
||||
|
||||
#[allow(deprecated)]
|
||||
let multiple = if o.is_multiple_occurrences_set() {
|
||||
"*"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let multiple = "*";
|
||||
|
||||
let vn = match o.get_value_names() {
|
||||
None => " ".to_string(),
|
||||
|
@ -555,12 +550,7 @@ fn write_flags_of(p: &Command, p_global: Option<&Command>) -> String {
|
|||
let help = f.get_help().map_or(String::new(), escape_help);
|
||||
let conflicts = arg_conflicts(p, &f, p_global);
|
||||
|
||||
#[allow(deprecated)]
|
||||
let multiple = if f.is_multiple_occurrences_set() {
|
||||
"*"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let multiple = "*";
|
||||
|
||||
if let Some(short) = f.get_short() {
|
||||
let s = format!(
|
||||
|
@ -634,8 +624,7 @@ fn write_positionals_of(p: &Command) -> String {
|
|||
for arg in p.get_positionals() {
|
||||
debug!("write_positionals_of:iter: arg={}", arg.get_id());
|
||||
|
||||
#[allow(deprecated)]
|
||||
let cardinality = if arg.is_multiple_values_set() || arg.is_multiple_occurrences_set() {
|
||||
let cardinality = if arg.is_multiple_values_set() {
|
||||
"*:"
|
||||
} else if !arg.is_required_set() {
|
||||
":"
|
||||
|
|
|
@ -19,10 +19,10 @@ _my-app() {
|
|||
'*-O+[cmd option]: : ' /
|
||||
'*--option=[cmd option]: : ' /
|
||||
'*--opt=[cmd option]: : ' /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
'*-f[cmd flag]' /
|
||||
'*-F[cmd flag]' /
|
||||
'*--flag[cmd flag]' /
|
||||
|
|
|
@ -15,8 +15,8 @@ _my-app() {
|
|||
|
||||
local context curcontext="$curcontext" state line
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-c[]' /
|
||||
'(-c)*-v[]' /
|
||||
":: :_my-app_commands" /
|
||||
|
@ -31,8 +31,8 @@ _my-app() {
|
|||
(test)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'*-d[]' /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-c[]' /
|
||||
&& ret=0
|
||||
;;
|
||||
|
|
|
@ -15,10 +15,10 @@ _my-app() {
|
|||
|
||||
local context curcontext="$curcontext" state line
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
'*-c[some config file]' /
|
||||
'*-C[some config file]' /
|
||||
'*--config[some config file]' /
|
||||
|
@ -37,10 +37,10 @@ _my-app() {
|
|||
(test)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'*--case=[the case to test]: : ' /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(help)
|
||||
|
|
|
@ -15,10 +15,10 @@ _my-app() {
|
|||
|
||||
local context curcontext="$curcontext" state line
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
'*--single-quotes[Can be '/''always'/'', '/''auto'/'', or '/''never'/'']' /
|
||||
'*--double-quotes[Can be "always", "auto", or "never"]' /
|
||||
'*--backticks[For more information see `echo test`]' /
|
||||
|
@ -36,38 +36,38 @@ _my-app() {
|
|||
case $line[1] in
|
||||
(cmd-single-quotes)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(cmd-double-quotes)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(cmd-backticks)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(cmd-backslash)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(cmd-brackets)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(cmd-expansions)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(help)
|
||||
|
|
|
@ -15,10 +15,10 @@ _my-app() {
|
|||
|
||||
local context curcontext="$curcontext" state line
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
'*-c[some config file]' /
|
||||
'*-C[some config file]' /
|
||||
'*--config[some config file]' /
|
||||
|
@ -37,36 +37,36 @@ _my-app() {
|
|||
(test)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'*--case=[the case to test]: : ' /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(some_cmd)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'*--config=[the other case to test]: : ' /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
'*::path:' /
|
||||
&& ret=0
|
||||
;;
|
||||
(some-cmd-with-hyphens)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(some-hidden-cmd)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(help)
|
||||
|
|
|
@ -15,10 +15,10 @@ _my-app() {
|
|||
|
||||
local context curcontext="$curcontext" state line
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
'*-c[some config file]' /
|
||||
'*-C[some config file]' /
|
||||
'*--config[some config file]' /
|
||||
|
@ -37,18 +37,18 @@ _my-app() {
|
|||
(test)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'*--case=[the case to test]: : ' /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(some_cmd)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
":: :_my-app__some_cmd_commands" /
|
||||
"*::: :->some_cmd" /
|
||||
&& ret=0
|
||||
|
@ -62,10 +62,10 @@ _arguments "${_arguments_options[@]}" /
|
|||
(sub_cmd)
|
||||
_arguments "${_arguments_options[@]}" /
|
||||
'*--config=[the other case to test]: :(Lest quotes aren't escaped.)' /
|
||||
'-h[Print help information]' /
|
||||
'--help[Print help information]' /
|
||||
'-V[Print version information]' /
|
||||
'--version[Print version information]' /
|
||||
'*-h[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*-V[Print version information]' /
|
||||
'*--version[Print version information]' /
|
||||
&& ret=0
|
||||
;;
|
||||
(help)
|
||||
|
|
|
@ -35,7 +35,7 @@ _my-app() {
|
|||
'*--host=[]: :_hosts' /
|
||||
'*--url=[]: :_urls' /
|
||||
'*--email=[]: :_email_addresses' /
|
||||
'--help[Print help information]' /
|
||||
'*--help[Print help information]' /
|
||||
'*::command_with_args:_cmdambivalent' /
|
||||
&& ret=0
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ const completion: Fig.Spec = {
|
|||
],
|
||||
args: {
|
||||
name: "subcommand",
|
||||
isVariadic: true,
|
||||
isOptional: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -30,6 +30,7 @@ const completion: Fig.Spec = {
|
|||
description: "Print this message or the help of the given subcommand(s)",
|
||||
args: {
|
||||
name: "subcommand",
|
||||
isVariadic: true,
|
||||
isOptional: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -67,6 +67,7 @@ const completion: Fig.Spec = {
|
|||
description: "Print this message or the help of the given subcommand(s)",
|
||||
args: {
|
||||
name: "subcommand",
|
||||
isVariadic: true,
|
||||
isOptional: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -87,6 +87,7 @@ const completion: Fig.Spec = {
|
|||
description: "Print this message or the help of the given subcommand(s)",
|
||||
args: {
|
||||
name: "subcommand",
|
||||
isVariadic: true,
|
||||
isOptional: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -60,6 +60,7 @@ const completion: Fig.Spec = {
|
|||
description: "Print this message or the help of the given subcommand(s)",
|
||||
args: {
|
||||
name: "subcommand",
|
||||
isVariadic: true,
|
||||
isOptional: true,
|
||||
},
|
||||
},
|
||||
|
@ -80,6 +81,7 @@ const completion: Fig.Spec = {
|
|||
description: "Print this message or the help of the given subcommand(s)",
|
||||
args: {
|
||||
name: "subcommand",
|
||||
isVariadic: true,
|
||||
isOptional: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -752,21 +752,6 @@ impl<'help> Arg<'help> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Deprecated, replaced with [`Arg::action`] ([Issue #3772](https://github.com/clap-rs/clap/issues/3772))
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[cfg_attr(
|
||||
feature = "deprecated",
|
||||
deprecated(since = "3.2.0", note = "Replaced with `Arg::action` (Issue #3772)")
|
||||
)]
|
||||
pub fn multiple_occurrences(self, yes: bool) -> Self {
|
||||
if yes {
|
||||
self.setting(ArgSettings::MultipleOccurrences)
|
||||
} else {
|
||||
self.unset_setting(ArgSettings::MultipleOccurrences)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn is_set(&self, s: ArgSettings) -> bool {
|
||||
self.settings.is_set(s)
|
||||
|
@ -1100,10 +1085,6 @@ impl<'help> Arg<'help> {
|
|||
/// `.number_of_values(3)`, and this argument wouldn't be satisfied unless the user provided
|
||||
/// 3 and only 3 values.
|
||||
///
|
||||
/// **NOTE:** Does *not* require [`Arg::multiple_occurrences(true)`] to be set. Setting
|
||||
/// [`Arg::multiple_occurrences(true)`] would allow `-f <file> <file> <file> -f <file> <file> <file>` where
|
||||
/// as *not* setting it would only allow one occurrence of this argument.
|
||||
///
|
||||
/// **NOTE:** implicitly sets [`Arg::takes_value(true)`] and [`Arg::multiple_values(true)`].
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -1131,7 +1112,6 @@ impl<'help> Arg<'help> {
|
|||
/// assert!(res.is_err());
|
||||
/// assert_eq!(res.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
|
||||
/// ```
|
||||
/// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn number_of_values(mut self, qty: usize) -> Self {
|
||||
|
@ -1145,12 +1125,6 @@ impl<'help> Arg<'help> {
|
|||
/// `-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.
|
||||
///
|
||||
/// **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
|
||||
/// occurrence with multiple values. For positional arguments this **does** set
|
||||
/// [`Arg::multiple_occurrences(true)`] because there is no way to determine the difference between multiple
|
||||
/// occurrences and multiple values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
|
@ -1195,7 +1169,6 @@ impl<'help> Arg<'help> {
|
|||
/// assert!(res.is_err());
|
||||
/// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
|
||||
/// ```
|
||||
/// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn max_values(mut self, qty: usize) -> Self {
|
||||
|
@ -1210,12 +1183,6 @@ impl<'help> Arg<'help> {
|
|||
/// `.min_values(2)`, and this argument would be satisfied if the user provided, 2 or more
|
||||
/// values.
|
||||
///
|
||||
/// **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
|
||||
/// occurrence with multiple values. For positional arguments this **does** set
|
||||
/// [`Arg::multiple_occurrences(true)`] because there is no way to determine the difference between multiple
|
||||
/// occurrences and multiple values.
|
||||
///
|
||||
/// **NOTE:** Passing a non-zero value is not the same as specifying [`Arg::required(true)`].
|
||||
/// This is due to min and max validation only being performed for present arguments,
|
||||
/// marking them as required will thus perform validation and a min value of 1
|
||||
|
@ -1265,7 +1232,6 @@ impl<'help> Arg<'help> {
|
|||
/// assert!(res.is_err());
|
||||
/// assert_eq!(res.unwrap_err().kind(), ErrorKind::TooFewValues);
|
||||
/// ```
|
||||
/// [`Arg::multiple_occurrences(true)`]: Arg::multiple_occurrences()
|
||||
/// [`Arg::required(true)`]: Arg::required()
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1485,8 +1451,7 @@ impl<'help> Arg<'help> {
|
|||
/// **WARNING**: Take caution when using this setting combined with
|
||||
/// [`Arg::multiple_values`], as this becomes ambiguous `$ prog --arg -- -- val`. All
|
||||
/// three `--, --, val` will be values when the user may have thought the second `--` would
|
||||
/// constitute the normal, "Only positional args follow" idiom. To fix this, consider using
|
||||
/// [`Arg::multiple_occurrences`] which only allows a single value at a time.
|
||||
/// constitute the normal, "Only positional args follow" idiom.
|
||||
///
|
||||
/// **WARNING**: When building your CLIs, consider the effects of allowing leading hyphens and
|
||||
/// the user passing in a value that matches a valid short. For example, `prog -opt -F` where
|
||||
|
@ -4164,15 +4129,6 @@ impl<'help> Arg<'help> {
|
|||
self.is_set(ArgSettings::MultipleValues)
|
||||
}
|
||||
|
||||
/// [`Arg::multiple_occurrences`] is going away ([Issue #3772](https://github.com/clap-rs/clap/issues/3772))
|
||||
#[cfg_attr(
|
||||
feature = "deprecated",
|
||||
deprecated(since = "3.2.0", note = "`multiple_occurrences` away (Issue #3772)")
|
||||
)]
|
||||
pub fn is_multiple_occurrences_set(&self) -> bool {
|
||||
self.is_set(ArgSettings::MultipleOccurrences)
|
||||
}
|
||||
|
||||
/// Report whether [`Arg::is_takes_value_set`] is set
|
||||
pub fn is_takes_value_set(&self) -> bool {
|
||||
self.is_set(ArgSettings::TakesValue)
|
||||
|
@ -4328,18 +4284,6 @@ impl<'help> Arg<'help> {
|
|||
} else {
|
||||
self.settings.unset(ArgSettings::TakesValue);
|
||||
}
|
||||
match action {
|
||||
ArgAction::Help | ArgAction::Version => {}
|
||||
ArgAction::Set
|
||||
| ArgAction::Append
|
||||
| ArgAction::SetTrue
|
||||
| ArgAction::SetFalse
|
||||
| ArgAction::Count => {
|
||||
if !self.is_positional() {
|
||||
self.settings.set(ArgSettings::MultipleOccurrences);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.value_parser.is_none() {
|
||||
|
@ -4379,7 +4323,9 @@ impl<'help> Arg<'help> {
|
|||
// Used for positionals when printing
|
||||
pub(crate) fn multiple_str(&self) -> &str {
|
||||
let mult_vals = self.val_names.len() > 1;
|
||||
if (self.is_multiple_values_set() || self.is_multiple_occurrences_set()) && !mult_vals {
|
||||
if (self.is_multiple_values_set() || matches!(*self.get_action(), ArgAction::Append))
|
||||
&& !mult_vals
|
||||
{
|
||||
"..."
|
||||
} else {
|
||||
""
|
||||
|
@ -4417,7 +4363,7 @@ impl<'help> Arg<'help> {
|
|||
|
||||
/// Either multiple values or occurrences
|
||||
pub(crate) fn is_multiple(&self) -> bool {
|
||||
self.is_multiple_values_set() | self.is_multiple_occurrences_set()
|
||||
self.is_multiple_values_set() || matches!(*self.get_action(), ArgAction::Append)
|
||||
}
|
||||
|
||||
pub(crate) fn get_display_order(&self) -> usize {
|
||||
|
@ -4554,7 +4500,7 @@ where
|
|||
F: FnMut(&str, bool) -> Result<T, E>,
|
||||
{
|
||||
let mult_val = arg.is_multiple_values_set();
|
||||
let mult_occ = arg.is_multiple_occurrences_set();
|
||||
let mult_occ = matches!(*arg.get_action(), ArgAction::Append);
|
||||
let delim = if arg.is_require_value_delimiter_set() {
|
||||
arg.val_delim.expect(INTERNAL_ERROR_MSG)
|
||||
} else {
|
||||
|
@ -4622,10 +4568,11 @@ where
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Arg;
|
||||
use super::ArgAction;
|
||||
|
||||
#[test]
|
||||
fn flag_display() {
|
||||
let mut f = Arg::new("flg").multiple_occurrences(true);
|
||||
let mut f = Arg::new("flg").action(ArgAction::Append);
|
||||
f.long = Some("flag");
|
||||
|
||||
assert_eq!(f.to_string(), "--flag");
|
||||
|
@ -4682,7 +4629,7 @@ mod test {
|
|||
let o = Arg::new("opt")
|
||||
.long("option")
|
||||
.takes_value(true)
|
||||
.multiple_occurrences(true);
|
||||
.action(ArgAction::Append);
|
||||
|
||||
assert_eq!(o.to_string(), "--option <opt>");
|
||||
}
|
||||
|
@ -4774,7 +4721,7 @@ mod test {
|
|||
let p = Arg::new("pos")
|
||||
.index(1)
|
||||
.takes_value(true)
|
||||
.multiple_occurrences(true);
|
||||
.action(ArgAction::Append);
|
||||
|
||||
assert_eq!(p.to_string(), "<pos>...");
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ impl Default for ArgFlags {
|
|||
pub(crate) enum ArgSettings {
|
||||
Required,
|
||||
MultipleValues,
|
||||
MultipleOccurrences,
|
||||
Global,
|
||||
Hidden,
|
||||
TakesValue,
|
||||
|
@ -56,7 +55,6 @@ pub(crate) enum ArgSettings {
|
|||
bitflags! {
|
||||
struct Flags: u32 {
|
||||
const REQUIRED = 1;
|
||||
const MULTIPLE_OCC = 1 << 1;
|
||||
const GLOBAL = 1 << 3;
|
||||
const HIDDEN = 1 << 4;
|
||||
const TAKES_VAL = 1 << 5;
|
||||
|
@ -75,7 +73,6 @@ bitflags! {
|
|||
const HIDDEN_SHORT_H = 1 << 18;
|
||||
const HIDDEN_LONG_H = 1 << 19;
|
||||
const MULTIPLE_VALS = 1 << 20;
|
||||
const MULTIPLE = Self::MULTIPLE_OCC.bits | Self::MULTIPLE_VALS.bits;
|
||||
#[cfg(feature = "env")]
|
||||
const HIDE_ENV = 1 << 21;
|
||||
const EXCLUSIVE = 1 << 23;
|
||||
|
@ -85,7 +82,6 @@ bitflags! {
|
|||
|
||||
impl_settings! { ArgSettings, ArgFlags,
|
||||
Required => Flags::REQUIRED,
|
||||
MultipleOccurrences => Flags::MULTIPLE_OCC,
|
||||
MultipleValues => Flags::MULTIPLE_VALS,
|
||||
Global => Flags::GLOBAL,
|
||||
Hidden => Flags::HIDDEN,
|
||||
|
|
|
@ -4239,7 +4239,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.",
|
|||
Arg::new("subcommand")
|
||||
.index(1)
|
||||
.takes_value(true)
|
||||
.multiple_occurrences(true)
|
||||
.multiple_values(true)
|
||||
.value_name("SUBCOMMAND")
|
||||
.help("The subcommand whose help message to display"),
|
||||
);
|
||||
|
|
|
@ -515,13 +515,7 @@ fn _verify_positionals(cmd: &Command) -> bool {
|
|||
// Next we check how many have both Multiple and not a specific number of values set
|
||||
let count = cmd
|
||||
.get_positionals()
|
||||
.filter(|p| {
|
||||
#[allow(deprecated)]
|
||||
{
|
||||
p.is_multiple_occurrences_set()
|
||||
|| (p.is_multiple_values_set() && p.num_vals.is_none())
|
||||
}
|
||||
})
|
||||
.filter(|p| p.is_multiple_values_set() && p.num_vals.is_none())
|
||||
.count();
|
||||
let ok = count <= 1
|
||||
|| (last.is_last_set()
|
||||
|
|
|
@ -207,9 +207,6 @@ pub enum ErrorKind {
|
|||
/// [`Command::subcommand_required`]: crate::Command::subcommand_required
|
||||
MissingSubcommand,
|
||||
|
||||
/// Occurs when the user provides multiple values to an argument which doesn't allow that.
|
||||
UnexpectedMultipleUsage,
|
||||
|
||||
/// Occurs when the user provides a value containing invalid UTF-8.
|
||||
///
|
||||
/// To allow arbitrary data
|
||||
|
@ -333,9 +330,6 @@ impl ErrorKind {
|
|||
Some("One or more required arguments were not provided")
|
||||
}
|
||||
Self::MissingSubcommand => Some("A subcommand is required but one was not provided"),
|
||||
Self::UnexpectedMultipleUsage => {
|
||||
Some("An argument was provided more than once but cannot be used multiple times")
|
||||
}
|
||||
Self::InvalidUtf8 => Some("Invalid UTF-8 was detected in one or more arguments"),
|
||||
Self::DisplayHelp => None,
|
||||
Self::DisplayHelpOnMissingArgumentOrSubcommand => None,
|
||||
|
|
|
@ -412,15 +412,6 @@ impl Error {
|
|||
])
|
||||
}
|
||||
|
||||
pub(crate) fn unexpected_multiple_usage(cmd: &Command, arg: String, usage: String) -> Self {
|
||||
Self::new(ErrorKind::UnexpectedMultipleUsage)
|
||||
.with_cmd(cmd)
|
||||
.extend_context_unchecked([
|
||||
(ContextKind::InvalidArg, ContextValue::String(arg)),
|
||||
(ContextKind::Usage, ContextValue::String(usage)),
|
||||
])
|
||||
}
|
||||
|
||||
pub(crate) fn unknown_argument(
|
||||
cmd: &Command,
|
||||
arg: String,
|
||||
|
@ -715,17 +706,6 @@ impl Error {
|
|||
false
|
||||
}
|
||||
}
|
||||
ErrorKind::UnexpectedMultipleUsage => {
|
||||
let invalid_arg = self.get_context(ContextKind::InvalidArg);
|
||||
if let Some(ContextValue::String(invalid_arg)) = invalid_arg {
|
||||
c.none("The argument '");
|
||||
c.warning(invalid_arg.to_string());
|
||||
c.none("' was provided more than once, but cannot be used multiple times");
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
ErrorKind::UnknownArgument => {
|
||||
let invalid_arg = self.get_context(ContextKind::InvalidArg);
|
||||
if let Some(ContextValue::String(invalid_arg)) = invalid_arg {
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::parser::Identifier;
|
|||
use crate::parser::PendingArg;
|
||||
use crate::parser::{ArgMatches, MatchedArg, SubCommand, ValueSource};
|
||||
use crate::util::Id;
|
||||
use crate::ArgAction;
|
||||
use crate::INTERNAL_ERROR_MSG;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -218,8 +219,7 @@ impl ArgMatcher {
|
|||
true
|
||||
} else if let Some(num) = o.num_vals {
|
||||
debug!("ArgMatcher::needs_more_vals: num_vals...{}", num);
|
||||
#[allow(deprecated)]
|
||||
if o.is_multiple_occurrences_set() {
|
||||
if matches!(o.get_action(), ArgAction::Append) && !o.is_positional() {
|
||||
(current_num % num) != 0
|
||||
} else {
|
||||
num != current_num
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::output::Usage;
|
|||
use crate::parser::{ArgMatcher, MatchedArg, ParseState};
|
||||
use crate::util::ChildGraph;
|
||||
use crate::util::Id;
|
||||
use crate::ArgAction;
|
||||
use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8};
|
||||
|
||||
pub(crate) struct Validator<'help, 'cmd> {
|
||||
|
@ -241,42 +242,20 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
|
|||
);
|
||||
if let Some(arg) = self.cmd.find(name) {
|
||||
self.validate_arg_num_vals(arg, ma)?;
|
||||
self.validate_arg_num_occurs(arg, ma)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn validate_arg_num_occurs(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
|
||||
#![allow(deprecated)]
|
||||
debug!(
|
||||
"Validator::validate_arg_num_occurs: {:?}={}",
|
||||
a.name,
|
||||
ma.get_occurrences()
|
||||
);
|
||||
// Occurrence of positional argument equals to number of values rather
|
||||
// than number of grouped values.
|
||||
if ma.get_occurrences() > 1 && !a.is_multiple_occurrences_set() && !a.is_positional() {
|
||||
// Not the first time, and we don't allow multiples
|
||||
return Err(Error::unexpected_multiple_usage(
|
||||
self.cmd,
|
||||
a.to_string(),
|
||||
Usage::new(self.cmd)
|
||||
.required(&self.required)
|
||||
.create_usage_with_title(&[]),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_num_vals(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
|
||||
debug!("Validator::validate_arg_num_vals");
|
||||
if let Some(num) = a.num_vals {
|
||||
let total_num = ma.num_vals();
|
||||
debug!("Validator::validate_arg_num_vals: num_vals set...{}", num);
|
||||
#[allow(deprecated)]
|
||||
let should_err = if a.is_multiple_occurrences_set() {
|
||||
debug!(
|
||||
"Validator::validate_arg_num_vals: num_vals={}, actual={}",
|
||||
num, total_num
|
||||
);
|
||||
let should_err = if matches!(a.get_action(), ArgAction::Append) && !a.is_positional() {
|
||||
total_num % num != 0
|
||||
} else {
|
||||
num != total_num
|
||||
|
@ -287,8 +266,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
|
|||
self.cmd,
|
||||
a.to_string(),
|
||||
num,
|
||||
#[allow(deprecated)]
|
||||
if a.is_multiple_occurrences_set() {
|
||||
if matches!(a.get_action(), ArgAction::Append) && !a.is_positional() {
|
||||
total_num % num
|
||||
} else {
|
||||
total_num
|
||||
|
|
|
@ -1403,7 +1403,7 @@ fn issue_2229() {
|
|||
"myprog", "val1", "val2", "val3", "val4", "val5", "val6",
|
||||
]);
|
||||
|
||||
assert!(m.is_err()); // This panics, because `m.is_err() == false`.
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ struct PathOpt {
|
|||
#[clap(short, default_value = "../")]
|
||||
default_path: PathBuf,
|
||||
|
||||
#[clap(short, multiple_occurrences(true))]
|
||||
#[clap(short)]
|
||||
vector_path: Vec<PathBuf>,
|
||||
|
||||
#[clap(short)]
|
||||
|
|
Loading…
Reference in a new issue