mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
fix!: Replaced min_values
(tota) with number_of_values
(per occurrence)
This commit is contained in:
parent
ccf35ff70c
commit
30f5b11d06
8 changed files with 47 additions and 115 deletions
|
@ -23,7 +23,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- `Arg::number_of_values` now applies per occurrence rather than the average across all occurrences
|
||||
- `number_of_values(0)` no longer implies `takes_value(true).multiple_values(true)`
|
||||
- `number_of_values(1)` no longer implies `multiple_values(true)`
|
||||
- Remove `Arg::min_values` (across all occurrences) with `Arg::number_of_values` (per occurrence)
|
||||
- Remove `Arg::min_values` (across all occurrences) with `Arg::number_of_values(N..)` (per occurrence)
|
||||
- Remove `Arg::max_values` (across all occurrences) with `Arg::number_of_values(1..=M)` (per occurrence)
|
||||
- `ArgAction::SetTrue` and `ArgAction::SetFalse` now prioritize `Arg::default_missing_value` over their standard behavior
|
||||
- *(help)* Make `DeriveDisplayOrder` the default and removed the setting. To sort help, set `next_display_order(None)` (#2808)
|
||||
- *(help)* Subcommand display order respects `Command::next_display_order` instead of `DeriveDisplayOrder` and using its own initial display order value (#2808)
|
||||
|
|
|
@ -32,7 +32,7 @@ macro_rules! create_app {
|
|||
--multvalsmo <s> "Tests multiple values, not mult occs"
|
||||
).multiple_values(true).required(false).value_names(&["one", "two"]),
|
||||
arg!(--minvals2 <minvals> ... "Tests 2 min vals").number_of_values(2..).multiple_values(true).required(false),
|
||||
arg!(--maxvals3 <maxvals> ... "Tests 3 max vals").max_values(3).multiple_values(true).required(false),
|
||||
arg!(--maxvals3 <maxvals> ... "Tests 3 max vals").number_of_values(1..=3).multiple_values(true).required(false),
|
||||
])
|
||||
.subcommand(
|
||||
Command::new("subcmd")
|
||||
|
@ -132,7 +132,7 @@ pub fn build_from_builder(c: &mut Criterion) {
|
|||
.multiple_values(true)
|
||||
.action(ArgAction::Append)
|
||||
.help("Tests 3 max vals")
|
||||
.max_values(3),
|
||||
.number_of_values(1..=3),
|
||||
)
|
||||
.subcommand(
|
||||
Command::new("subcmd")
|
||||
|
|
|
@ -74,7 +74,6 @@ pub struct Arg<'help> {
|
|||
pub(crate) disp_ord: Option<usize>,
|
||||
pub(crate) val_names: Vec<&'help str>,
|
||||
pub(crate) num_vals: Option<ValuesRange>,
|
||||
pub(crate) max_vals: Option<usize>,
|
||||
pub(crate) val_delim: Option<char>,
|
||||
pub(crate) default_vals: Vec<&'help OsStr>,
|
||||
pub(crate) default_vals_ifs: Vec<(Id, ArgPredicate<'help>, Option<&'help OsStr>)>,
|
||||
|
@ -1066,9 +1065,9 @@ impl<'help> Arg<'help> {
|
|||
///
|
||||
/// [`subcommands`]: crate::Command::subcommand()
|
||||
/// [`Arg::number_of_values(1)`]: Arg::number_of_values()
|
||||
/// [maximum number of values]: Arg::max_values()
|
||||
/// [maximum number of values]: Arg::number_of_values()
|
||||
/// [specific number of values]: Arg::number_of_values()
|
||||
/// [maximum]: Arg::max_values()
|
||||
/// [maximum]: Arg::number_of_values()
|
||||
/// [specific]: Arg::number_of_values()
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1236,63 +1235,6 @@ impl<'help> Arg<'help> {
|
|||
.multiple_values(qty.is_multiple())
|
||||
}
|
||||
|
||||
/// The *maximum* number of values are for this argument.
|
||||
///
|
||||
/// For example, if you had a
|
||||
/// `-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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{Command, Arg};
|
||||
/// Arg::new("file")
|
||||
/// .short('f')
|
||||
/// .max_values(3);
|
||||
/// ```
|
||||
///
|
||||
/// Supplying less than the maximum number of values is allowed
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{Command, Arg, ArgAction};
|
||||
/// let res = Command::new("prog")
|
||||
/// .arg(Arg::new("file")
|
||||
/// .action(ArgAction::Set)
|
||||
/// .max_values(3)
|
||||
/// .short('F'))
|
||||
/// .try_get_matches_from(vec![
|
||||
/// "prog", "-F", "file1", "file2"
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(res.is_ok());
|
||||
/// let m = res.unwrap();
|
||||
/// let files: Vec<_> = m.get_many::<String>("file").unwrap().collect();
|
||||
/// assert_eq!(files, ["file1", "file2"]);
|
||||
/// ```
|
||||
///
|
||||
/// Supplying more than the maximum number of values is an error
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{Command, Arg, ErrorKind, ArgAction};
|
||||
/// let res = Command::new("prog")
|
||||
/// .arg(Arg::new("file")
|
||||
/// .action(ArgAction::Set)
|
||||
/// .max_values(2)
|
||||
/// .short('F'))
|
||||
/// .try_get_matches_from(vec![
|
||||
/// "prog", "-F", "file1", "file2", "file3"
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(res.is_err());
|
||||
/// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn max_values(mut self, qty: usize) -> Self {
|
||||
self.max_vals = Some(qty);
|
||||
self.takes_value(true).multiple_values(true)
|
||||
}
|
||||
|
||||
/// Placeholder for the argument's value in the help message / usage.
|
||||
///
|
||||
/// This name is cosmetic only; the name is **not** used to access arguments.
|
||||
|
@ -1791,7 +1733,7 @@ impl<'help> Arg<'help> {
|
|||
/// By default when
|
||||
/// 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
|
||||
/// for multiple values is used (such as [`max_values`] or [`number_of_values`]).
|
||||
/// for multiple values is used (such as [`number_of_values`]).
|
||||
///
|
||||
/// **NOTE:** This setting only applies to [options] and [positional arguments]
|
||||
///
|
||||
|
@ -1832,7 +1774,6 @@ impl<'help> Arg<'help> {
|
|||
/// [positional arguments]: Arg::index()
|
||||
/// [`multiple_values(true)`]: Arg::multiple_values()
|
||||
/// [`number_of_values`]: Arg::number_of_values()
|
||||
/// [`max_values`]: Arg::max_values()
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn value_terminator(mut self, term: &'help str) -> Self {
|
||||
|
@ -4543,7 +4484,6 @@ impl<'help> fmt::Debug for Arg<'help> {
|
|||
.field("disp_ord", &self.disp_ord)
|
||||
.field("val_names", &self.val_names)
|
||||
.field("num_vals", &self.num_vals)
|
||||
.field("max_vals", &self.max_vals)
|
||||
.field("val_delim", &self.val_delim)
|
||||
.field("default_vals", &self.default_vals)
|
||||
.field("default_vals_ifs", &self.default_vals_ifs)
|
||||
|
|
|
@ -96,7 +96,7 @@ pub enum ErrorKind {
|
|||
ValueValidation,
|
||||
|
||||
/// Occurs when a user provides more values for an argument than were defined by setting
|
||||
/// [`Arg::max_values`].
|
||||
/// [`Arg::number_of_values`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -104,12 +104,14 @@ pub enum ErrorKind {
|
|||
/// # use clap::{Command, Arg, ErrorKind};
|
||||
/// let result = Command::new("prog")
|
||||
/// .arg(Arg::new("arg")
|
||||
/// .max_values(2))
|
||||
/// .try_get_matches_from(vec!["prog", "too", "many", "values"]);
|
||||
/// .number_of_values(1..=2)
|
||||
/// .use_value_delimiter(true)
|
||||
/// .require_value_delimiter(true))
|
||||
/// .try_get_matches_from(vec!["prog", "too,many,values"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues);
|
||||
/// ```
|
||||
/// [`Arg::max_values`]: crate::Arg::max_values()
|
||||
/// [`Arg::number_of_values`]: crate::Arg::number_of_values()
|
||||
TooManyValues,
|
||||
|
||||
/// Occurs when the user provides fewer values for an argument than were defined by setting
|
||||
|
|
|
@ -222,9 +222,6 @@ impl ArgMatcher {
|
|||
expected, num_pending
|
||||
);
|
||||
expected.accepts_more(num_pending)
|
||||
} else if let Some(num) = o.max_vals {
|
||||
debug!("ArgMatcher::needs_more_vals: max_vals...{}", num);
|
||||
current_num < num
|
||||
} else {
|
||||
o.is_multiple_values_set()
|
||||
}
|
||||
|
|
|
@ -314,25 +314,6 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Some(num) = a.max_vals {
|
||||
debug!("Validator::validate_arg_num_vals: max_vals set...{}", num);
|
||||
if ma.num_vals() > num {
|
||||
debug!("Validator::validate_arg_num_vals: Sending error TooManyValues");
|
||||
return Err(Error::too_many_values(
|
||||
self.cmd,
|
||||
ma.raw_vals_flatten()
|
||||
.last()
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.to_str()
|
||||
.expect(INVALID_UTF8)
|
||||
.to_string(),
|
||||
a.to_string(),
|
||||
Usage::new(self.cmd)
|
||||
.required(&self.required)
|
||||
.create_usage_with_title(&[]),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -298,10 +298,10 @@ fn option_max_exact() {
|
|||
Arg::new("option")
|
||||
.short('o')
|
||||
.help("multiple options")
|
||||
.max_values(3)
|
||||
.action(ArgAction::Append),
|
||||
.number_of_values(1..=3)
|
||||
.action(ArgAction::Set),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]);
|
||||
.try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
|
||||
|
||||
assert!(m.is_ok(), "{}", m.unwrap_err());
|
||||
let m = m.unwrap();
|
||||
|
@ -323,10 +323,10 @@ fn option_max_less() {
|
|||
Arg::new("option")
|
||||
.short('o')
|
||||
.help("multiple options")
|
||||
.max_values(3)
|
||||
.action(ArgAction::Append),
|
||||
.number_of_values(1..=3)
|
||||
.action(ArgAction::Set),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]);
|
||||
.try_get_matches_from(vec!["", "-o", "val1", "val2"]);
|
||||
|
||||
assert!(m.is_ok(), "{}", m.unwrap_err());
|
||||
let m = m.unwrap();
|
||||
|
@ -348,8 +348,8 @@ fn option_max_zero() {
|
|||
Arg::new("option")
|
||||
.short('o')
|
||||
.help("multiple options")
|
||||
.max_values(3)
|
||||
.action(ArgAction::Append),
|
||||
.number_of_values(1..=3)
|
||||
.action(ArgAction::Set),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "-o"]);
|
||||
|
||||
|
@ -364,8 +364,8 @@ fn option_max_zero_eq() {
|
|||
Arg::new("option")
|
||||
.short('o')
|
||||
.help("multiple options")
|
||||
.max_values(3)
|
||||
.action(ArgAction::Append),
|
||||
.number_of_values(1..=3)
|
||||
.action(ArgAction::Set),
|
||||
)
|
||||
.try_get_matches_from(vec!["", "-o="]);
|
||||
|
||||
|
@ -389,15 +389,14 @@ fn option_max_more() {
|
|||
Arg::new("option")
|
||||
.short('o')
|
||||
.help("multiple options")
|
||||
.max_values(3)
|
||||
.action(ArgAction::Append),
|
||||
.number_of_values(1..=3)
|
||||
.action(ArgAction::Set),
|
||||
)
|
||||
.try_get_matches_from(vec![
|
||||
"", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4",
|
||||
]);
|
||||
.try_get_matches_from(vec!["", "-o", "val1", "val2", "val3", "val4"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyValues);
|
||||
// Can end up being TooManyValues or UnknownArgument
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -580,7 +579,11 @@ fn positional_min_more() {
|
|||
#[test]
|
||||
fn positional_max_exact() {
|
||||
let m = Command::new("multiple_values")
|
||||
.arg(Arg::new("pos").help("multiple positionals").max_values(3))
|
||||
.arg(
|
||||
Arg::new("pos")
|
||||
.help("multiple positionals")
|
||||
.number_of_values(1..=3),
|
||||
)
|
||||
.try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
|
||||
|
||||
assert!(m.is_ok(), "{}", m.unwrap_err());
|
||||
|
@ -599,7 +602,11 @@ fn positional_max_exact() {
|
|||
#[test]
|
||||
fn positional_max_less() {
|
||||
let m = Command::new("multiple_values")
|
||||
.arg(Arg::new("pos").help("multiple positionals").max_values(3))
|
||||
.arg(
|
||||
Arg::new("pos")
|
||||
.help("multiple positionals")
|
||||
.number_of_values(1..=3),
|
||||
)
|
||||
.try_get_matches_from(vec!["myprog", "val1", "val2"]);
|
||||
|
||||
assert!(m.is_ok(), "{}", m.unwrap_err());
|
||||
|
@ -618,7 +625,11 @@ fn positional_max_less() {
|
|||
#[test]
|
||||
fn positional_max_more() {
|
||||
let m = Command::new("multiple_values")
|
||||
.arg(Arg::new("pos").help("multiple positionals").max_values(3))
|
||||
.arg(
|
||||
Arg::new("pos")
|
||||
.help("multiple positionals")
|
||||
.number_of_values(1..=3),
|
||||
)
|
||||
.try_get_matches_from(vec!["myprog", "val1", "val2", "val3", "val4"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
|
@ -1454,7 +1465,7 @@ fn multiple_vals_with_hyphen() {
|
|||
#[test]
|
||||
fn issue_1480_max_values_consumes_extra_arg_1() {
|
||||
let res = Command::new("prog")
|
||||
.arg(Arg::new("field").max_values(1).long("field"))
|
||||
.arg(Arg::new("field").number_of_values(..=1).long("field"))
|
||||
.arg(Arg::new("positional").required(true).index(1))
|
||||
.try_get_matches_from(vec!["prog", "--field", "1", "file"]);
|
||||
|
||||
|
@ -1464,7 +1475,7 @@ fn issue_1480_max_values_consumes_extra_arg_1() {
|
|||
#[test]
|
||||
fn issue_1480_max_values_consumes_extra_arg_2() {
|
||||
let res = Command::new("prog")
|
||||
.arg(Arg::new("field").max_values(1).long("field"))
|
||||
.arg(Arg::new("field").number_of_values(..=1).long("field"))
|
||||
.try_get_matches_from(vec!["prog", "--field", "1", "2"]);
|
||||
|
||||
assert!(res.is_err());
|
||||
|
@ -1474,7 +1485,7 @@ fn issue_1480_max_values_consumes_extra_arg_2() {
|
|||
#[test]
|
||||
fn issue_1480_max_values_consumes_extra_arg_3() {
|
||||
let res = Command::new("prog")
|
||||
.arg(Arg::new("field").max_values(1).long("field"))
|
||||
.arg(Arg::new("field").number_of_values(..=1).long("field"))
|
||||
.try_get_matches_from(vec!["prog", "--field", "1", "2", "3"]);
|
||||
|
||||
assert!(res.is_err());
|
||||
|
|
|
@ -83,7 +83,7 @@ pub fn complex_app() -> Command<'static> {
|
|||
.number_of_values(2..),
|
||||
arg!(--maxvals3 <maxvals> "Tests 3 max vals")
|
||||
.required(false)
|
||||
.max_values(3),
|
||||
.number_of_values(1..=3),
|
||||
arg!(--optvaleq <optval> "Tests optional value, require = sign")
|
||||
.required(false)
|
||||
.number_of_values(0..=1)
|
||||
|
|
Loading…
Reference in a new issue