From 9b5b49ceec66781d64ccf39e0cbff390145c3d82 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 25 May 2022 12:38:58 -0500 Subject: [PATCH 1/9] fix(parser): Error, don't panicon on get_many type mismatch --- src/parser/matches/arg_matches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index 5c3bd965c8a..e19fc3ab6ad 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -1412,7 +1412,7 @@ impl ArgMatches { name: &str, ) -> Result>, MatchesError> { let id = Id::from(name); - let arg = match self.try_get_arg(&id)? { + let arg = match self.try_get_arg_t::(&id)? { Some(arg) => arg, None => return Ok(None), }; From 5b6d68f24738f1484dacdd99e6bb44fd958cd1bb Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 25 May 2022 12:40:56 -0500 Subject: [PATCH 2/9] fix(parser): Show cause of panic in backtrace --- src/parser/matches/arg_matches.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index e19fc3ab6ad..f739f6bf10b 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -159,6 +159,7 @@ impl ArgMatches { /// .collect(); /// assert_eq!(vals, [22, 80, 2020]); /// ``` + #[track_caller] pub fn get_many( &self, name: &str, @@ -208,6 +209,7 @@ impl ArgMatches { /// [`OsSt`]: std::ffi::OsStr /// [values]: OsValues /// [`String`]: std::string::String + #[track_caller] pub fn get_raw(&self, name: &str) -> Option> { let id = Id::from(name); MatchesError::unwrap(&id, self.try_get_raw(name)) @@ -249,6 +251,7 @@ impl ArgMatches { /// [`ArgMatches::values_of`]: ArgMatches::values_of() /// [`default_value`]: crate::Arg::default_value() /// [`occurrences_of`]: crate::ArgMatches::occurrences_of() + #[track_caller] pub fn remove_one(&mut self, name: &str) -> Option { let id = Id::from(name); MatchesError::unwrap(&id, self.try_remove_one(name)) @@ -284,6 +287,7 @@ impl ArgMatches { /// .collect(); /// assert_eq!(vals, ["file1.txt", "file2.txt", "file3.txt", "file4.txt"]); /// ``` + #[track_caller] pub fn remove_many( &mut self, name: &str, From f15a1aab1a17976b099df47a47577c15cb3aec84 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 23 May 2022 07:23:16 -0500 Subject: [PATCH 3/9] fix: Deprecate allow_invalid_utf8 --- src/builder/arg.rs | 40 +++++++------------------------ src/builder/debug_asserts.rs | 5 +++- src/builder/value_parser.rs | 25 +++++++++++++++++++ src/parser/matches/arg_matches.rs | 6 ++--- tests/builder/default_vals.rs | 12 ++++++---- tests/builder/utf8.rs | 38 +++++++++++++++++++---------- 6 files changed, 73 insertions(+), 53 deletions(-) diff --git a/src/builder/arg.rs b/src/builder/arg.rs index e76128d04d8..29138998ac6 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -1990,39 +1990,14 @@ impl<'help> Arg<'help> { } } - /// The argument's values can be invalid UTF-8 and should *not* be treated as an error. - /// - /// **NOTE:** Using argument values with invalid UTF-8 code points requires using - /// [`ArgMatches::value_of_os`], [`ArgMatches::values_of_os`], [`ArgMatches::value_of_lossy`], - /// or [`ArgMatches::values_of_lossy`] for those particular arguments which may contain invalid - /// UTF-8 values. - /// - /// **NOTE:** Setting this requires [`Arg::takes_value`] - /// - /// # Examples - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```rust")] - /// # use clap::{Command, Arg}; - /// use std::ffi::OsString; - /// use std::os::unix::ffi::{OsStrExt,OsStringExt}; - /// let r = Command::new("myprog") - /// .arg(Arg::new("arg").allow_invalid_utf8(true)) - /// .try_get_matches_from(vec![ - /// OsString::from("myprog"), - /// OsString::from_vec(vec![0xe9]) - /// ]); - /// - /// assert!(r.is_ok()); - /// let m = r.unwrap(); - /// assert_eq!(m.value_of_os("arg").unwrap().as_bytes(), &[0xe9]); - /// ``` - /// [`ArgMatches::value_of_os`]: crate::ArgMatches::value_of_os() - /// [`ArgMatches::values_of_os`]: crate::ArgMatches::values_of_os() - /// [`ArgMatches::value_of_lossy`]: crate::ArgMatches::value_of_lossy() - /// [`ArgMatches::values_of_lossy`]: crate::ArgMatches::values_of_lossy() + /// Deprecated, replaced with [`Arg::value_parser(...)`] with either [`ValueParser::os_string()`][crate::builder::ValueParser::os_string] + /// or [`ValueParser::path_buf()`][crate::builder::ValueParser::path_buf] #[inline] #[must_use] + #[deprecated( + since = "3.2.0", + note = "Replaced with `Arg::value_parser(...)` with either `ValueParser::os_string()` or `ValueParser::path_buf()`" + )] pub fn allow_invalid_utf8(self, yes: bool) -> Self { if yes { self.setting(ArgSettings::AllowInvalidUtf8) @@ -4817,7 +4792,8 @@ impl<'help> Arg<'help> { self.is_set(ArgSettings::ForbidEmptyValues) } - /// Report whether [`Arg::is_allow_invalid_utf8_set`] is set + /// Deprecated, replaced with [`Arg::get_value_parser()` + #[deprecated(since = "3.2.0", note = "Replaced with `Arg::get_value_parser()`")] pub fn is_allow_invalid_utf8_set(&self) -> bool { self.is_set(ArgSettings::AllowInvalidUtf8) } diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs index ccfa2f8c682..3c2613c0ee1 100644 --- a/src/builder/debug_asserts.rs +++ b/src/builder/debug_asserts.rs @@ -732,7 +732,10 @@ fn assert_arg_flags(arg: &Arg) { checker!(is_hide_default_value_set requires is_takes_value_set); checker!(is_multiple_values_set requires is_takes_value_set); checker!(is_ignore_case_set requires is_takes_value_set); - checker!(is_allow_invalid_utf8_set requires is_takes_value_set); + { + #![allow(deprecated)] + checker!(is_allow_invalid_utf8_set requires is_takes_value_set); + } } fn assert_defaults<'d>( diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs index f1f4c0dda13..8ba8742f3d2 100644 --- a/src/builder/value_parser.rs +++ b/src/builder/value_parser.rs @@ -164,6 +164,31 @@ impl ValueParser { } /// [`OsString`][std::ffi::OsString] parser for argument values + /// + /// # Example + /// + #[cfg_attr(not(unix), doc = " ```ignore")] + #[cfg_attr(unix, doc = " ```rust")] + /// # use clap::{Command, Arg, builder::ValueParser}; + /// use std::ffi::OsString; + /// use std::os::unix::ffi::{OsStrExt,OsStringExt}; + /// let r = Command::new("myprog") + /// .arg( + /// Arg::new("arg") + /// .required(true) + /// .value_parser(ValueParser::os_string()) + /// ) + /// .try_get_matches_from(vec![ + /// OsString::from("myprog"), + /// OsString::from_vec(vec![0xe9]) + /// ]); + /// + /// assert!(r.is_ok()); + /// let m = r.unwrap(); + /// let arg: &OsString = m.get_one("arg") + /// .expect("required"); + /// assert_eq!(arg.as_bytes(), &[0xe9]); + /// ``` pub const fn os_string() -> Self { Self(ValueParserInner::OsString) } diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index f739f6bf10b..c2aa45ba74a 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -2138,14 +2138,14 @@ mod tests { crate::Arg::new("POTATO") .takes_value(true) .multiple_values(true) - .allow_invalid_utf8(true) + .value_parser(crate::builder::ValueParser::os_string()) .required(true), ) .try_get_matches_from(["test", "one"]) .unwrap() - .values_of_os("POTATO") + .get_many::("POTATO") .expect("present") - .len(); + .count(); assert_eq!(l, 1); } diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index c86ea38cf17..233b0bd6f41 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -539,14 +539,16 @@ fn multiple_defaults() { Arg::new("files") .long("files") .number_of_values(2) - .allow_invalid_utf8(true) .default_values(&["old", "new"]), ) .try_get_matches_from(vec![""]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("files")); - assert_eq!(m.values_of_lossy("files").unwrap(), vec!["old", "new"]); + assert_eq!( + m.get_many::("files").unwrap().collect::>(), + vec!["old", "new"] + ); } #[test] @@ -556,14 +558,16 @@ fn multiple_defaults_override() { Arg::new("files") .long("files") .number_of_values(2) - .allow_invalid_utf8(true) .default_values(&["old", "new"]), ) .try_get_matches_from(vec!["", "--files", "other", "mine"]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("files")); - assert_eq!(m.values_of_lossy("files").unwrap(), vec!["other", "mine"]); + assert_eq!( + m.get_many::("files").unwrap().collect::>(), + vec!["other", "mine"] + ); } #[test] diff --git a/tests/builder/utf8.rs b/tests/builder/utf8.rs index ece5614708b..795fbb0e0fe 100644 --- a/tests/builder/utf8.rs +++ b/tests/builder/utf8.rs @@ -1,6 +1,6 @@ #![cfg(not(windows))] -use clap::{arg, error::ErrorKind, Arg, Command}; +use clap::{arg, error::ErrorKind, value_parser, Arg, Command}; use std::ffi::OsString; use std::os::unix::ffi::OsStringExt; @@ -77,6 +77,7 @@ fn invalid_utf8_strict_option_long_equals() { #[test] fn invalid_utf8_lossy_positional() { + #![allow(deprecated)] let r = Command::new("bad_utf8") .arg(Arg::new("arg").allow_invalid_utf8(true)) .try_get_matches_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]); @@ -88,6 +89,7 @@ fn invalid_utf8_lossy_positional() { #[test] fn invalid_utf8_lossy_option_short_space() { + #![allow(deprecated)] let r = Command::new("bad_utf8") .arg( Arg::new("arg") @@ -109,6 +111,7 @@ fn invalid_utf8_lossy_option_short_space() { #[test] fn invalid_utf8_lossy_option_short_equals() { + #![allow(deprecated)] let r = Command::new("bad_utf8") .arg( Arg::new("arg") @@ -129,6 +132,7 @@ fn invalid_utf8_lossy_option_short_equals() { #[test] fn invalid_utf8_lossy_option_short_no_space() { + #![allow(deprecated)] let r = Command::new("bad_utf8") .arg( Arg::new("arg") @@ -149,6 +153,7 @@ fn invalid_utf8_lossy_option_short_no_space() { #[test] fn invalid_utf8_lossy_option_long_space() { + #![allow(deprecated)] let r = Command::new("bad_utf8") .arg( Arg::new("arg") @@ -170,6 +175,7 @@ fn invalid_utf8_lossy_option_long_space() { #[test] fn invalid_utf8_lossy_option_long_equals() { + #![allow(deprecated)] let r = Command::new("bad_utf8") .arg( Arg::new("arg") @@ -191,13 +197,13 @@ fn invalid_utf8_lossy_option_long_equals() { #[test] fn invalid_utf8_positional() { let r = Command::new("bad_utf8") - .arg(Arg::new("arg").allow_invalid_utf8(true)) + .arg(Arg::new("arg").value_parser(value_parser!(OsString))) .try_get_matches_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!( - &*m.value_of_os("arg").unwrap(), + &*m.get_one::("arg").unwrap(), &*OsString::from_vec(vec![0xe9]) ); } @@ -210,7 +216,7 @@ fn invalid_utf8_option_short_space() { .short('a') .long("arg") .takes_value(true) - .allow_invalid_utf8(true), + .value_parser(value_parser!(OsString)), ) .try_get_matches_from(vec![ OsString::from(""), @@ -221,7 +227,7 @@ fn invalid_utf8_option_short_space() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!( - &*m.value_of_os("arg").unwrap(), + &*m.get_one::("arg").unwrap(), &*OsString::from_vec(vec![0xe9]) ); } @@ -234,7 +240,7 @@ fn invalid_utf8_option_short_equals() { .short('a') .long("arg") .takes_value(true) - .allow_invalid_utf8(true), + .value_parser(value_parser!(OsString)), ) .try_get_matches_from(vec![ OsString::from(""), @@ -244,7 +250,7 @@ fn invalid_utf8_option_short_equals() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!( - &*m.value_of_os("arg").unwrap(), + &*m.get_one::("arg").unwrap(), &*OsString::from_vec(vec![0xe9]) ); } @@ -257,7 +263,7 @@ fn invalid_utf8_option_short_no_space() { .short('a') .long("arg") .takes_value(true) - .allow_invalid_utf8(true), + .value_parser(value_parser!(OsString)), ) .try_get_matches_from(vec![ OsString::from(""), @@ -267,7 +273,7 @@ fn invalid_utf8_option_short_no_space() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!( - &*m.value_of_os("arg").unwrap(), + &*m.get_one::("arg").unwrap(), &*OsString::from_vec(vec![0xe9]) ); } @@ -280,7 +286,7 @@ fn invalid_utf8_option_long_space() { .short('a') .long("arg") .takes_value(true) - .allow_invalid_utf8(true), + .value_parser(value_parser!(OsString)), ) .try_get_matches_from(vec![ OsString::from(""), @@ -291,7 +297,7 @@ fn invalid_utf8_option_long_space() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!( - &*m.value_of_os("arg").unwrap(), + &*m.get_one::("arg").unwrap(), &*OsString::from_vec(vec![0xe9]) ); } @@ -304,7 +310,7 @@ fn invalid_utf8_option_long_equals() { .short('a') .long("arg") .takes_value(true) - .allow_invalid_utf8(true), + .value_parser(value_parser!(OsString)), ) .try_get_matches_from(vec![ OsString::from(""), @@ -314,7 +320,7 @@ fn invalid_utf8_option_long_equals() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!( - &*m.value_of_os("arg").unwrap(), + &*m.get_one::("arg").unwrap(), &*OsString::from_vec(vec![0xe9]) ); } @@ -390,6 +396,7 @@ fn allow_invalid_utf8_subcommand_args_with_allow_external_subcommands() { #[test] fn allow_validated_utf8_value_of() { + #![allow(deprecated)] let a = Command::new("test").arg(arg!(--name )); let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap(); let _ = m.value_of("name"); @@ -398,6 +405,7 @@ fn allow_validated_utf8_value_of() { #[test] #[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups at `name`"] fn panic_validated_utf8_value_of_os() { + #![allow(deprecated)] let a = Command::new("test").arg(arg!(--name )); let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap(); let _ = m.value_of_os("name"); @@ -406,6 +414,7 @@ fn panic_validated_utf8_value_of_os() { #[test] #[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups at `value`"] fn panic_validated_utf8_with_defaults() { + #![allow(deprecated)] let a = Command::new("test").arg(arg!(--value ).required(false).default_value("foo")); let m = a.try_get_matches_from(["test"]).unwrap(); let _ = m.value_of("value"); @@ -414,6 +423,7 @@ fn panic_validated_utf8_with_defaults() { #[test] fn allow_invalid_utf8_value_of_os() { + #![allow(deprecated)] let a = Command::new("test").arg(arg!(--name ).allow_invalid_utf8(true)); let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap(); let _ = m.value_of_os("name"); @@ -422,6 +432,7 @@ fn allow_invalid_utf8_value_of_os() { #[test] #[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8` at `name`"] fn panic_invalid_utf8_value_of() { + #![allow(deprecated)] let a = Command::new("test").arg(arg!(--name ).allow_invalid_utf8(true)); let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap(); let _ = m.value_of("name"); @@ -430,6 +441,7 @@ fn panic_invalid_utf8_value_of() { #[test] #[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8` at `value`"] fn panic_invalid_utf8_with_defaults() { + #![allow(deprecated)] let a = Command::new("test").arg( arg!(--value ) .required(false) From 177511dab1c714fb1cf8f0517fcdc60a7922e527 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 23 May 2022 15:42:34 -0500 Subject: [PATCH 4/9] fix: Deprecate validator / validator_os `validator_regex` is being ignored for now as I await on a comment period for #3743 --- benches/05_ripgrep.rs | 20 ++---- clap_complete/examples/completion-derive.rs | 28 ++++---- examples/derive_ref/custom-bool.md | 4 +- examples/derive_ref/custom-bool.rs | 1 + src/builder/arg.rs | 71 ++------------------- src/builder/debug_asserts.rs | 23 +++++++ tests/builder/default_missing_vals.rs | 4 +- tests/builder/default_vals.rs | 10 +-- tests/builder/env.rs | 20 +++--- tests/builder/validators.rs | 2 + tests/derive/arguments.rs | 8 ++- tests/derive/basic.rs | 4 +- tests/derive/boxed.rs | 1 + tests/derive/custom_string_parsers.rs | 66 +++++-------------- tests/derive/default_value.rs | 8 +-- tests/derive/deny_warnings.rs | 4 +- tests/derive/doc_comments_help.rs | 9 ++- tests/derive/explicit_name_no_renaming.rs | 4 +- tests/derive/flags.rs | 2 + tests/derive/flatten.rs | 8 +++ tests/derive/generic.rs | 11 +++- tests/derive/help.rs | 41 +++++++----- tests/derive/issues.rs | 4 +- tests/derive/macros.rs | 2 +- tests/derive/naming.rs | 14 ++-- tests/derive/nested_subcommands.rs | 13 +++- tests/derive/non_literal_attributes.rs | 11 ++-- tests/derive/options.rs | 38 ++++++----- tests/derive/privacy.rs | 1 + tests/derive/raw_bool_literal.rs | 4 +- tests/derive/raw_idents.rs | 2 +- tests/derive/rename_all_env.rs | 8 +-- tests/derive/skip.rs | 12 ++-- tests/derive/subcommands.rs | 19 +++++- tests/derive/type_alias_regressions.rs | 5 +- tests/derive/utf8.rs | 3 +- 36 files changed, 246 insertions(+), 239 deletions(-) diff --git a/benches/05_ripgrep.rs b/benches/05_ripgrep.rs index 7d5cab69649..ddd7f3ea5cb 100644 --- a/benches/05_ripgrep.rs +++ b/benches/05_ripgrep.rs @@ -3,7 +3,7 @@ // // CLI used is adapted from ripgrep 48a8a3a691220f9e5b2b08f4051abe8655ea7e8a -use clap::{Arg, Command}; +use clap::{value_parser, Arg, Command}; use criterion::{criterion_group, criterion_main, Criterion}; use std::collections::HashMap; use std::io::Cursor; @@ -394,19 +394,19 @@ where flag("after-context") .short('A') .value_name("NUM") - .validator(validate_number), + .value_parser(value_parser!(usize)), ) .arg( flag("before-context") .short('B') .value_name("NUM") - .validator(validate_number), + .value_parser(value_parser!(usize)), ) .arg( flag("context") .short('C') .value_name("NUM") - .validator(validate_number), + .value_parser(value_parser!(usize)), ) .arg(flag("column")) .arg(flag("context-separator").value_name("SEPARATOR")) @@ -434,12 +434,12 @@ where flag("max-count") .short('m') .value_name("NUM") - .validator(validate_number), + .value_parser(value_parser!(usize)), ) .arg( flag("maxdepth") .value_name("NUM") - .validator(validate_number), + .value_parser(value_parser!(usize)), ) .arg(flag("mmap")) .arg(flag("no-messages")) @@ -458,7 +458,7 @@ where flag("threads") .short('j') .value_name("ARG") - .validator(validate_number), + .value_parser(value_parser!(usize)), ) .arg(flag("vimgrep")) .arg( @@ -933,12 +933,6 @@ lazy_static! { }; } -fn validate_number(s: &str) -> Result<(), String> { - s.parse::() - .map(|_| ()) - .map_err(|err| err.to_string()) -} - criterion_group!( benches, build_rg_with_short_help, diff --git a/clap_complete/examples/completion-derive.rs b/clap_complete/examples/completion-derive.rs index ed24e7ed77a..fb2e95dd78e 100644 --- a/clap_complete/examples/completion-derive.rs +++ b/clap_complete/examples/completion-derive.rs @@ -26,34 +26,34 @@ use std::path::PathBuf; )] struct Opt { /// If provided, outputs the completion file for given shell - #[clap(long = "generate", arg_enum)] + #[clap(long = "generate", arg_enum, value_parser)] generator: Option, // Showcasing all possible ValueHints: - #[clap(long, value_hint = ValueHint::Unknown)] + #[clap(long, value_hint = ValueHint::Unknown, value_parser)] unknown: Option, - #[clap(long, value_hint = ValueHint::Other)] + #[clap(long, value_hint = ValueHint::Other, value_parser)] other: Option, - #[clap(short, long, value_hint = ValueHint::AnyPath)] + #[clap(short, long, value_hint = ValueHint::AnyPath, value_parser)] path: Option, - #[clap(short, long, value_hint = ValueHint::FilePath)] + #[clap(short, long, value_hint = ValueHint::FilePath, value_parser)] file: Option, - #[clap(short, long, value_hint = ValueHint::DirPath)] + #[clap(short, long, value_hint = ValueHint::DirPath, value_parser)] dir: Option, - #[clap(short, long, value_hint = ValueHint::ExecutablePath)] + #[clap(short, long, value_hint = ValueHint::ExecutablePath, value_parser)] exe: Option, - #[clap(long, parse(from_os_str), value_hint = ValueHint::CommandName)] + #[clap(long, value_hint = ValueHint::CommandName, value_parser)] cmd_name: Option, - #[clap(short, long, value_hint = ValueHint::CommandString)] + #[clap(short, long, value_hint = ValueHint::CommandString, value_parser)] cmd: Option, - #[clap(value_hint = ValueHint::CommandWithArguments)] + #[clap(value_hint = ValueHint::CommandWithArguments, value_parser)] command_with_args: Vec, - #[clap(short, long, value_hint = ValueHint::Username)] + #[clap(short, long, value_hint = ValueHint::Username, value_parser)] user: Option, - #[clap(short, long, value_hint = ValueHint::Hostname)] + #[clap(short, long, value_hint = ValueHint::Hostname, value_parser)] host: Option, - #[clap(long, value_hint = ValueHint::Url)] + #[clap(long, value_hint = ValueHint::Url, value_parser)] url: Option, - #[clap(long, value_hint = ValueHint::EmailAddress)] + #[clap(long, value_hint = ValueHint::EmailAddress, value_parser)] email: Option, } diff --git a/examples/derive_ref/custom-bool.md b/examples/derive_ref/custom-bool.md index 2769f20e8f9..c2c9bb1d0dd 100644 --- a/examples/derive_ref/custom-bool.md +++ b/examples/derive_ref/custom-bool.md @@ -31,14 +31,14 @@ USAGE: For more information try --help $ custom-bool --foo true false -[examples/derive_ref/custom-bool.rs:31] opt = Opt { +[examples/derive_ref/custom-bool.rs:32] opt = Opt { foo: true, bar: false, boom: false, } $ custom-bool --foo true --bar true false -[examples/derive_ref/custom-bool.rs:31] opt = Opt { +[examples/derive_ref/custom-bool.rs:32] opt = Opt { foo: true, bar: true, boom: false, diff --git a/examples/derive_ref/custom-bool.rs b/examples/derive_ref/custom-bool.rs index 10f93f40ac6..b0e4c81c568 100644 --- a/examples/derive_ref/custom-bool.rs +++ b/examples/derive_ref/custom-bool.rs @@ -1,3 +1,4 @@ +#![allow(deprecated)] // Can't opt-out of implicit flags until #3405 use clap::Parser; #[derive(Parser, Debug, PartialEq)] diff --git a/src/builder/arg.rs b/src/builder/arg.rs index 29138998ac6..1a015c36f01 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -1557,43 +1557,10 @@ impl<'help> Arg<'help> { self.takes_value(true) } - /// Perform a custom validation on the argument value. - /// - /// You provide a closure - /// which accepts a [`&str`] value, and return a [`Result`] where the [`Err(String)`] is a - /// message displayed to the user. - /// - /// **NOTE:** The error message does *not* need to contain the `error:` portion, only the - /// message as all errors will appear as - /// `error: Invalid value for '': ` where `` is replaced by the actual - /// arg, and `` is the `String` you return as the error. - /// - /// **NOTE:** There is a small performance hit for using validators, as they are implemented - /// with [`Arc`] pointers. And the value to be checked will be allocated an extra time in order - /// to be passed to the closure. This performance hit is extremely minimal in the grand - /// scheme of things. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{Command, Arg}; - /// fn has_at(v: &str) -> Result<(), String> { - /// if v.contains("@") { return Ok(()); } - /// Err(String::from("The value did not contain the required @ sigil")) - /// } - /// let res = Command::new("prog") - /// .arg(Arg::new("file") - /// .validator(has_at)) - /// .try_get_matches_from(vec![ - /// "prog", "some@file" - /// ]); - /// assert!(res.is_ok()); - /// assert_eq!(res.unwrap().value_of("file"), Some("some@file")); - /// ``` - /// [`Result`]: std::result::Result - /// [`Err(String)`]: std::result::Result::Err - /// [`Arc`]: std::sync::Arc + /// Deprecated, replaced with [`Arg::value_parser(...)`] + #[inline] #[must_use] + #[deprecated(since = "3.2.0", note = "Replaced with `Arg::value_parser(...)`")] pub fn validator(mut self, mut f: F) -> Self where F: FnMut(&str) -> Result + Send + 'help, @@ -1605,37 +1572,9 @@ impl<'help> Arg<'help> { self } - /// Perform a custom validation on the argument value. - /// - /// See [validator][Arg::validator]. - /// - /// # Examples - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```rust")] - /// # use clap::{Command, Arg}; - /// # use std::ffi::{OsStr, OsString}; - /// # use std::os::unix::ffi::OsStrExt; - /// fn has_ampersand(v: &OsStr) -> Result<(), String> { - /// if v.as_bytes().iter().any(|b| *b == b'&') { return Ok(()); } - /// Err(String::from("The value did not contain the required & sigil")) - /// } - /// let res = Command::new("prog") - /// .arg(Arg::new("file") - /// .validator_os(has_ampersand)) - /// .try_get_matches_from(vec![ - /// "prog", "Fish & chips" - /// ]); - /// assert!(res.is_ok()); - /// assert_eq!(res.unwrap().value_of("file"), Some("Fish & chips")); - /// ``` - /// [`String`]: std::string::String - /// [`OsStr`]: std::ffi::OsStr - /// [`OsString`]: std::ffi::OsString - /// [`Result`]: std::result::Result - /// [`Err(String)`]: std::result::Result::Err - /// [`Rc`]: std::rc::Rc + /// Deprecated, replaced with [`Arg::value_parser(...)`] #[must_use] + #[deprecated(since = "3.2.0", note = "Replaced with `Arg::value_parser(...)`")] pub fn validator_os(mut self, mut f: F) -> Self where F: FnMut(&OsStr) -> Result + Send + 'help, diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs index 3c2613c0ee1..aba342fca24 100644 --- a/src/builder/debug_asserts.rs +++ b/src/builder/debug_asserts.rs @@ -810,5 +810,28 @@ fn assert_defaults<'d>( ); } } + + let value_parser = arg.get_value_parser(); + let assert_cmd = Command::new("assert"); + if let Some(delim) = arg.get_value_delimiter() { + let default_os = RawOsStr::new(default_os); + for part in default_os.split(delim) { + if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), &part.to_os_str()) + { + panic!( + "Argument `{}`'s {}={:?} failed validation: {}", + arg.name, + field, + part.to_str_lossy(), + err + ); + } + } + } else if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), default_os) { + panic!( + "Argument `{}`'s {}={:?} failed validation: {}", + arg.name, field, default_os, err + ); + } } } diff --git a/tests/builder/default_missing_vals.rs b/tests/builder/default_missing_vals.rs index 52ed95226fa..63bd6fa404c 100644 --- a/tests/builder/default_missing_vals.rs +++ b/tests/builder/default_missing_vals.rs @@ -173,14 +173,14 @@ fn default_missing_values_are_possible_values() { #[cfg(debug_assertions)] #[test] -#[should_panic = "Argument `arg`'s default_missing_value=value failed validation: invalid digit found in string"] +#[should_panic = "Argument `arg`'s default_missing_value=\"value\" failed validation: error: Invalid value \"value\" for '"] fn default_missing_values_are_valid() { use clap::{Arg, Command}; let _ = Command::new("test") .arg( Arg::new("arg") - .validator(|val| val.parse::().map_err(|e| e.to_string())) + .value_parser(clap::value_parser!(u32)) .default_missing_value("value"), ) .try_get_matches(); diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index 233b0bd6f41..ba03da58a4b 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -652,14 +652,14 @@ fn default_values_are_possible_values() { #[cfg(debug_assertions)] #[test] -#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"] +#[should_panic = "Argument `arg`'s default_value=\"one\" failed validation: error: Invalid value \"one\" for '"] fn invalid_default_values() { use clap::{Arg, Command}; let _ = Command::new("test") .arg( Arg::new("arg") - .validator(|val| val.parse::().map_err(|e| e.to_string())) + .value_parser(clap::value_parser!(u32)) .default_value("one"), ) .try_get_matches(); @@ -672,7 +672,7 @@ fn valid_delimited_default_values() { let _ = Command::new("test") .arg( Arg::new("arg") - .validator(|val| val.parse::().map_err(|e| e.to_string())) + .value_parser(clap::value_parser!(u32)) .use_value_delimiter(true) .require_value_delimiter(true) .default_value("1,2,3"), @@ -682,14 +682,14 @@ fn valid_delimited_default_values() { #[cfg(debug_assertions)] #[test] -#[should_panic = "Argument `arg`'s default_value=one failed validation: invalid digit found in string"] +#[should_panic = "Argument `arg`'s default_value=\"one\" failed validation: error: Invalid value \"one\" for '"] fn invalid_delimited_default_values() { use clap::{Arg, Command}; let _ = Command::new("test") .arg( Arg::new("arg") - .validator(|val| val.parse::().map_err(|e| e.to_string())) + .value_parser(clap::value_parser!(u32)) .use_value_delimiter(true) .require_value_delimiter(true) .default_value("one,two"), diff --git a/tests/builder/env.rs b/tests/builder/env.rs index e5416eef470..8bc94e3bc6d 100644 --- a/tests/builder/env.rs +++ b/tests/builder/env.rs @@ -287,7 +287,7 @@ fn not_possible_value() { } #[test] -fn validator() { +fn value_parser() { env::set_var("CLP_TEST_ENV_VDOR", "env"); let r = Command::new("df") @@ -295,11 +295,11 @@ fn validator() { arg!([arg] "some opt") .env("CLP_TEST_ENV_VDOR") .takes_value(true) - .validator(|s| { + .value_parser(|s: &str| -> Result { if s == "env" { - Ok(()) + Ok(s.to_owned()) } else { - Err("not equal".to_string()) + Err("not equal".to_owned()) } }), ) @@ -313,7 +313,7 @@ fn validator() { } #[test] -fn validator_output() { +fn value_parser_output() { env::set_var("CLP_TEST_ENV_VO", "42"); let m = Command::new("df") @@ -321,16 +321,16 @@ fn validator_output() { arg!([arg] "some opt") .env("CLP_TEST_ENV_VO") .takes_value(true) - .validator(|s| s.parse::()), + .value_parser(clap::value_parser!(i32)), ) .try_get_matches_from(vec![""]) .unwrap(); - assert_eq!(m.value_of("arg").unwrap().parse(), Ok(42)); + assert_eq!(*m.get_one::("arg").unwrap(), 42); } #[test] -fn validator_invalid() { +fn value_parser_invalid() { env::set_var("CLP_TEST_ENV_IV", "env"); let r = Command::new("df") @@ -338,9 +338,9 @@ fn validator_invalid() { arg!([arg] "some opt") .env("CLP_TEST_ENV_IV") .takes_value(true) - .validator(|s| { + .value_parser(|s: &str| -> Result { if s != "env" { - Ok(()) + Ok(s.to_owned()) } else { Err("is equal".to_string()) } diff --git a/tests/builder/validators.rs b/tests/builder/validators.rs index 8d05a784017..2701e352b42 100644 --- a/tests/builder/validators.rs +++ b/tests/builder/validators.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use clap::{Arg, Command}; #[cfg(debug_assertions)] diff --git a/tests/derive/arguments.rs b/tests/derive/arguments.rs index 57c5866d4ee..0d3f0b1e262 100644 --- a/tests/derive/arguments.rs +++ b/tests/derive/arguments.rs @@ -19,6 +19,7 @@ use clap::Parser; fn required_argument() { #[derive(Parser, PartialEq, Debug)] struct Opt { + #[clap(value_parser)] arg: i32, } assert_eq!( @@ -33,7 +34,7 @@ fn required_argument() { fn argument_with_default() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(default_value = "42")] + #[clap(value_parser, default_value = "42")] arg: i32, } assert_eq!( @@ -48,6 +49,7 @@ fn argument_with_default() { fn auto_value_name() { #[derive(Parser, PartialEq, Debug)] struct Opt { + #[clap(value_parser)] my_special_arg: i32, } @@ -67,7 +69,7 @@ fn auto_value_name() { fn explicit_value_name() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(value_name = "BROWNIE_POINTS")] + #[clap(value_parser, value_name = "BROWNIE_POINTS")] my_special_arg: i32, } @@ -88,6 +90,7 @@ fn explicit_value_name() { fn option_type_is_optional() { #[derive(Parser, PartialEq, Debug)] struct Opt { + #[clap(value_parser)] arg: Option, } assert_eq!( @@ -102,6 +105,7 @@ fn option_type_is_optional() { fn vec_type_is_multiple_values() { #[derive(Parser, PartialEq, Debug)] struct Opt { + #[clap(value_parser)] arg: Vec, } assert_eq!( diff --git a/tests/derive/basic.rs b/tests/derive/basic.rs index d2e1ca9001a..f32d17791ae 100644 --- a/tests/derive/basic.rs +++ b/tests/derive/basic.rs @@ -18,7 +18,7 @@ use clap::Parser; fn basic() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short = 'a', long = "arg")] + #[clap(short = 'a', long = "arg", value_parser)] arg: i32, } assert_eq!( @@ -31,7 +31,7 @@ fn basic() { fn update_basic() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short = 'a', long = "arg")] + #[clap(short = 'a', long = "arg", value_parser)] single_value: i32, } diff --git a/tests/derive/boxed.rs b/tests/derive/boxed.rs index 03efbe9c551..0af81f6fcfd 100644 --- a/tests/derive/boxed.rs +++ b/tests/derive/boxed.rs @@ -16,6 +16,7 @@ enum Sub { #[derive(Args, PartialEq, Debug)] struct Ext { + #[clap(value_parser)] arg: u32, } diff --git a/tests/derive/custom_string_parsers.rs b/tests/derive/custom_string_parsers.rs index 84279df35ea..ef7f0e88a6b 100644 --- a/tests/derive/custom_string_parsers.rs +++ b/tests/derive/custom_string_parsers.rs @@ -12,27 +12,29 @@ // commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the // MIT/Apache 2.0 license. +#![allow(deprecated)] + use clap::Parser; -use std::ffi::{CString, OsStr}; +use std::ffi::CString; use std::num::ParseIntError; use std::path::PathBuf; #[derive(Parser, PartialEq, Debug)] struct PathOpt { - #[clap(short, long, parse(from_os_str))] + #[clap(short, long, value_parser)] path: PathBuf, - #[clap(short, default_value = "../", parse(from_os_str))] + #[clap(short, default_value = "../", value_parser)] default_path: PathBuf, - #[clap(short, parse(from_os_str), multiple_occurrences(true))] + #[clap(short, value_parser, multiple_occurrences(true))] vector_path: Vec, - #[clap(short, parse(from_os_str))] + #[clap(short, value_parser)] option_path_1: Option, - #[clap(short = 'q', parse(from_os_str))] + #[clap(short = 'q', value_parser)] option_path_2: Option, } @@ -64,7 +66,7 @@ fn parse_hex(input: &str) -> Result { #[derive(Parser, PartialEq, Debug)] struct HexOpt { - #[clap(short, parse(try_from_str = parse_hex))] + #[clap(short, value_parser = parse_hex)] number: u64, } @@ -89,9 +91,6 @@ fn test_parse_hex() { ); } -fn custom_parser_1(_: &str) -> &'static str { - "A" -} #[derive(Debug)] struct ErrCode(u32); impl std::error::Error for ErrCode {} @@ -103,59 +102,28 @@ impl std::fmt::Display for ErrCode { fn custom_parser_2(_: &str) -> Result<&'static str, ErrCode> { Ok("B") } -fn custom_parser_3(_: &OsStr) -> &'static str { - "C" -} -fn custom_parser_4(_: &OsStr) -> Result<&'static str, String> { - Ok("D") -} #[derive(Parser, PartialEq, Debug)] struct NoOpOpt { - #[clap(short, parse(from_str = custom_parser_1))] - a: &'static str, - #[clap(short, parse(try_from_str = custom_parser_2))] + #[clap(short, value_parser = custom_parser_2)] b: &'static str, - #[clap(short, parse(from_os_str = custom_parser_3))] - c: &'static str, - #[clap(short, parse(try_from_os_str = custom_parser_4))] - d: &'static str, } #[test] fn test_every_custom_parser() { assert_eq!( - NoOpOpt { - a: "A", - b: "B", - c: "C", - d: "D" - }, - NoOpOpt::try_parse_from(&["test", "-a=?", "-b=?", "-c=?", "-d=?"]).unwrap() + NoOpOpt { b: "B" }, + NoOpOpt::try_parse_from(&["test", "-b=?"]).unwrap() ); } #[test] fn update_every_custom_parser() { - let mut opt = NoOpOpt { - a: "0", - b: "0", - c: "0", - d: "D", - }; + let mut opt = NoOpOpt { b: "0" }; - opt.try_update_from(&["test", "-a=?", "-b=?", "-d=?"]) - .unwrap(); + opt.try_update_from(&["test", "-b=?"]).unwrap(); - assert_eq!( - NoOpOpt { - a: "A", - b: "B", - c: "0", - d: "D" - }, - opt - ); + assert_eq!(NoOpOpt { b: "B" }, opt); } // Note: can't use `Vec` directly, as clap would instead look for @@ -167,10 +135,10 @@ struct DefaultedOpt { #[clap(short, parse(from_str))] bytes: Bytes, - #[clap(short, parse(try_from_str))] + #[clap(short, value_parser)] integer: u64, - #[clap(short, parse(from_os_str))] + #[clap(short, value_parser)] path: PathBuf, } diff --git a/tests/derive/default_value.rs b/tests/derive/default_value.rs index db2b7838014..fc07e4c1128 100644 --- a/tests/derive/default_value.rs +++ b/tests/derive/default_value.rs @@ -6,7 +6,7 @@ use crate::utils; fn default_value() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(default_value = "3")] + #[clap(value_parser, default_value = "3")] arg: i32, } assert_eq!(Opt { arg: 3 }, Opt::try_parse_from(&["test"]).unwrap()); @@ -20,7 +20,7 @@ fn default_value() { fn default_value_t() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(default_value_t = 3)] + #[clap(value_parser, default_value_t = 3)] arg: i32, } assert_eq!(Opt { arg: 3 }, Opt::try_parse_from(&["test"]).unwrap()); @@ -34,7 +34,7 @@ fn default_value_t() { fn auto_default_value_t() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(default_value_t)] + #[clap(value_parser, default_value_t)] arg: i32, } assert_eq!(Opt { arg: 0 }, Opt::try_parse_from(&["test"]).unwrap()); @@ -50,7 +50,7 @@ fn detect_os_variant() { #[derive(clap::Parser)] pub struct Options { - #[clap(default_value_os = ("123".as_ref()))] + #[clap(value_parser, default_value_os = ("123".as_ref()))] x: String, } Options::command().debug_assert(); diff --git a/tests/derive/deny_warnings.rs b/tests/derive/deny_warnings.rs index ab642b641e2..6e05b9277cc 100644 --- a/tests/derive/deny_warnings.rs +++ b/tests/derive/deny_warnings.rs @@ -24,7 +24,7 @@ fn try_str(s: &str) -> Result { fn warning_never_struct() { #[derive(Parser, Debug, PartialEq)] struct Opt { - #[clap(parse(try_from_str = try_str), default_value_t)] + #[clap(value_parser = try_str, default_value_t)] s: String, } assert_eq!( @@ -40,7 +40,7 @@ fn warning_never_enum() { #[derive(Parser, Debug, PartialEq)] enum Opt { Foo { - #[clap(parse(try_from_str = try_str), default_value_t)] + #[clap(value_parser = try_str, default_value_t)] s: String, }, } diff --git a/tests/derive/doc_comments_help.rs b/tests/derive/doc_comments_help.rs index d5836c25440..697672ce4da 100644 --- a/tests/derive/doc_comments_help.rs +++ b/tests/derive/doc_comments_help.rs @@ -106,7 +106,7 @@ fn top_long_doc_comment_both_help_long_help() { /// /// Or something else Foo { - #[clap(help = "foo")] + #[clap(value_parser, help = "foo")] bars: String, }, } @@ -191,7 +191,7 @@ fn multiline_separates_default() { /// Multiline /// /// Doc comment - #[clap(long, default_value = "x")] + #[clap(long, default_value = "x", value_parser)] x: String, } @@ -229,7 +229,10 @@ fn doc_comment_about_handles_both_abouts() { /// Sub doc comment body #[derive(Parser, PartialEq, Eq, Debug)] pub enum Sub { - Compress { output: String }, + Compress { + #[clap(value_parser)] + output: String, + }, } let cmd = Opts::command(); diff --git a/tests/derive/explicit_name_no_renaming.rs b/tests/derive/explicit_name_no_renaming.rs index dcdbc3820c7..15402e85ab4 100644 --- a/tests/derive/explicit_name_no_renaming.rs +++ b/tests/derive/explicit_name_no_renaming.rs @@ -6,7 +6,7 @@ use clap::Parser; fn explicit_short_long_no_rename() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short = '.', long = ".foo")] + #[clap(short = '.', long = ".foo", value_parser)] foo: String, } @@ -27,7 +27,7 @@ fn explicit_short_long_no_rename() { fn explicit_name_no_rename() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(name = ".options")] + #[clap(name = ".options", value_parser)] foo: String, } diff --git a/tests/derive/flags.rs b/tests/derive/flags.rs index ea770e68900..9c5d9d9b7dd 100644 --- a/tests/derive/flags.rs +++ b/tests/derive/flags.rs @@ -12,6 +12,8 @@ // commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the // MIT/Apache 2.0 license. +#![allow(deprecated)] + use clap::Parser; #[test] diff --git a/tests/derive/flatten.rs b/tests/derive/flatten.rs index 40d77a77156..15bef4db103 100644 --- a/tests/derive/flatten.rs +++ b/tests/derive/flatten.rs @@ -20,6 +20,7 @@ use clap::{Args, Parser, Subcommand}; fn flatten() { #[derive(Args, PartialEq, Debug)] struct Common { + #[clap(value_parser)] arg: i32, } @@ -44,6 +45,7 @@ fn flatten() { fn flatten_twice() { #[derive(Args, PartialEq, Debug)] struct Common { + #[clap(value_parser)] arg: i32, } @@ -62,6 +64,7 @@ fn flatten_twice() { fn flatten_in_subcommand() { #[derive(Args, PartialEq, Debug)] struct Common { + #[clap(value_parser)] arg: i32, } @@ -105,6 +108,7 @@ fn flatten_in_subcommand() { fn update_args_with_flatten() { #[derive(Args, PartialEq, Debug)] struct Common { + #[clap(value_parser)] arg: i32, } @@ -134,12 +138,15 @@ enum BaseCli { #[derive(Args, PartialEq, Debug)] struct Command1 { + #[clap(value_parser)] arg1: i32, + #[clap(value_parser)] arg2: i32, } #[derive(Args, PartialEq, Debug)] struct Command2 { + #[clap(value_parser)] arg2: i32, } @@ -192,6 +199,7 @@ fn flatten_with_doc_comment() { #[derive(Args, PartialEq, Debug)] struct Common { /// This is an arg. Arg means "argument". Command line argument. + #[clap(value_parser)] arg: i32, } diff --git a/tests/derive/generic.rs b/tests/derive/generic.rs index 76cccd334ff..cea94729083 100644 --- a/tests/derive/generic.rs +++ b/tests/derive/generic.rs @@ -4,6 +4,7 @@ use clap::{Args, Parser}; fn generic_struct_flatten() { #[derive(Args, PartialEq, Debug)] struct Inner { + #[clap(value_parser)] pub answer: isize, } @@ -25,6 +26,7 @@ fn generic_struct_flatten() { fn generic_struct_flatten_w_where_clause() { #[derive(Args, PartialEq, Debug)] struct Inner { + #[clap(value_parser)] pub answer: isize, } @@ -49,6 +51,7 @@ fn generic_struct_flatten_w_where_clause() { fn generic_enum() { #[derive(Args, PartialEq, Debug)] struct Inner { + #[clap(value_parser)] pub answer: isize, } @@ -68,6 +71,7 @@ fn generic_enum() { fn generic_enum_w_where_clause() { #[derive(Args, PartialEq, Debug)] struct Inner { + #[clap(value_parser)] pub answer: isize, } @@ -93,9 +97,10 @@ fn generic_w_fromstr_trait_bound() { #[derive(Parser, PartialEq, Debug)] struct Opt where - T: FromStr, + T: FromStr + Send + Sync + Clone + 'static, ::Err: std::error::Error + Sync + Send + 'static, { + #[clap(value_parser)] answer: T, } @@ -111,6 +116,7 @@ fn generic_wo_trait_bound() { #[derive(Parser, PartialEq, Debug)] struct Opt { + #[clap(value_parser)] answer: isize, #[clap(skip)] took: Option, @@ -132,9 +138,10 @@ fn generic_where_clause_w_trailing_comma() { #[derive(Parser, PartialEq, Debug)] struct Opt where - T: FromStr, + T: FromStr + Send + Sync + Clone + 'static, ::Err: std::error::Error + Sync + Send + 'static, { + #[clap(value_parser)] pub answer: T, } diff --git a/tests/derive/help.rs b/tests/derive/help.rs index 1362ac866c8..1edf42d9193 100644 --- a/tests/derive/help.rs +++ b/tests/derive/help.rs @@ -4,11 +4,11 @@ use clap::{AppSettings, Args, CommandFactory, Parser, Subcommand}; fn arg_help_heading_applied() { #[derive(Debug, Clone, Parser)] struct CliOptions { - #[clap(long)] + #[clap(long, value_parser)] #[clap(help_heading = Some("HEADING A"))] should_be_in_section_a: u32, - #[clap(long)] + #[clap(long, value_parser)] no_section: u32, } @@ -42,11 +42,11 @@ fn app_help_heading_applied() { #[derive(Debug, Clone, Parser)] #[clap(next_help_heading = "DEFAULT")] struct CliOptions { - #[clap(long)] + #[clap(long, value_parser)] #[clap(help_heading = Some("HEADING A"))] should_be_in_section_a: u32, - #[clap(long)] + #[clap(long, value_parser)] should_be_in_default_section: u32, } @@ -94,21 +94,21 @@ fn app_help_heading_flattened() { #[clap(subcommand)] sub_a: SubA, - #[clap(long)] + #[clap(long, value_parser)] should_be_in_default_section: u32, } #[derive(Debug, Clone, Args)] #[clap(next_help_heading = "HEADING A")] struct OptionsA { - #[clap(long)] + #[clap(long, value_parser)] should_be_in_section_a: u32, } #[derive(Debug, Clone, Args)] #[clap(next_help_heading = "HEADING B")] struct OptionsB { - #[clap(long)] + #[clap(long, value_parser)] should_be_in_section_b: u32, } @@ -121,6 +121,7 @@ fn app_help_heading_flattened() { SubAOne, #[clap(next_help_heading = "SUB A")] SubATwo { + #[clap(value_parser)] should_be_in_sub_a: u32, }, } @@ -128,13 +129,19 @@ fn app_help_heading_flattened() { #[derive(Debug, Clone, Subcommand)] enum SubB { #[clap(next_help_heading = "SUB B")] - SubBOne { should_be_in_sub_b: u32 }, + SubBOne { + #[clap(value_parser)] + should_be_in_sub_b: u32, + }, } #[derive(Debug, Clone, Subcommand)] enum SubC { #[clap(next_help_heading = "SUB C")] - SubCOne { should_be_in_sub_c: u32 }, + SubCOne { + #[clap(value_parser)] + should_be_in_sub_c: u32, + }, } let cmd = CliOptions::command(); @@ -230,7 +237,7 @@ fn flatten_field_with_help_heading() { #[derive(Debug, Clone, Args)] struct OptionsA { - #[clap(long)] + #[clap(long, value_parser)] should_be_in_section_a: u32, } @@ -257,7 +264,7 @@ fn derive_generated_error_has_full_context() { #[derive(Debug, Parser)] #[clap(subcommand_negates_reqs = true)] struct Opts { - #[clap(long)] + #[clap(long, value_parser)] req_str: String, #[clap(subcommand)] @@ -335,7 +342,7 @@ OPTIONS: #[clap(long)] flag_a: bool, /// second option - #[clap(long)] + #[clap(long, value_parser)] option_a: Option, } @@ -346,7 +353,7 @@ OPTIONS: #[clap(long)] flag_b: bool, /// first option - #[clap(long)] + #[clap(long, value_parser)] option_b: Option, } @@ -393,7 +400,7 @@ OPTIONS: #[clap(long)] flag_a: bool, /// second option - #[clap(long)] + #[clap(long, value_parser)] option_a: Option, } @@ -403,7 +410,7 @@ OPTIONS: #[clap(long)] flag_b: bool, /// first option - #[clap(long)] + #[clap(long, value_parser)] option_b: Option, } @@ -449,7 +456,7 @@ OPTIONS: #[clap(long)] flag_a: bool, /// first option - #[clap(long)] + #[clap(long, value_parser)] option_a: Option, } @@ -459,7 +466,7 @@ OPTIONS: #[clap(long)] flag_b: bool, /// second option - #[clap(long)] + #[clap(long, value_parser)] option_b: Option, } diff --git a/tests/derive/issues.rs b/tests/derive/issues.rs index 44e900575bd..ee3ff1ba6fc 100644 --- a/tests/derive/issues.rs +++ b/tests/derive/issues.rs @@ -89,6 +89,7 @@ fn issue_418() { #[clap(visible_alias = "ret")] Reticulate { /// How many splines + #[clap(value_parser)] num_splines: u8, }, /// Frobnicate the rest @@ -121,8 +122,9 @@ fn issue_490() { #[derive(Parser, Debug)] struct Opt { + #[clap(value_parser)] opt_vec: Vec, - #[clap(long)] + #[clap(long, value_parser)] opt_opt_vec: Option>, } diff --git a/tests/derive/macros.rs b/tests/derive/macros.rs index a2e671b4abc..5dbec71a39c 100644 --- a/tests/derive/macros.rs +++ b/tests/derive/macros.rs @@ -22,7 +22,7 @@ fn use_option() { ($name:ident: $ty:ty) => { #[derive(Parser)] struct Outer { - #[clap(short, long)] + #[clap(short, long, value_parser)] #[allow(dead_code)] $name: $ty, } diff --git a/tests/derive/naming.rs b/tests/derive/naming.rs index e3018a02f7c..b7889921f15 100644 --- a/tests/derive/naming.rs +++ b/tests/derive/naming.rs @@ -241,7 +241,10 @@ fn test_upper_is_renamed() { fn test_single_word_enum_variant_is_default_renamed_into_kebab_case() { #[derive(Parser, Debug, PartialEq)] enum Opt { - Command { foo: u32 }, + Command { + #[clap(value_parser)] + foo: u32, + }, } assert_eq!( @@ -254,7 +257,10 @@ fn test_single_word_enum_variant_is_default_renamed_into_kebab_case() { fn test_multi_word_enum_variant_is_renamed() { #[derive(Parser, Debug, PartialEq)] enum Opt { - FirstCommand { foo: u32 }, + FirstCommand { + #[clap(value_parser)] + foo: u32, + }, } assert_eq!( @@ -295,7 +301,7 @@ fn test_rename_all_is_propagated_from_enum_to_variants() { enum Opt { FirstVariant, SecondVariant { - #[clap(long)] + #[clap(long, value_parser)] foo: String, }, } @@ -313,7 +319,7 @@ fn test_rename_all_is_propagated_from_enum_to_variant_fields() { enum Opt { FirstVariant, SecondVariant { - #[clap(long)] + #[clap(long, value_parser)] foo: String, }, } diff --git a/tests/derive/nested_subcommands.rs b/tests/derive/nested_subcommands.rs index bf9344a65ad..98fec9676a1 100644 --- a/tests/derive/nested_subcommands.rs +++ b/tests/derive/nested_subcommands.rs @@ -118,6 +118,7 @@ struct Opt3 { #[derive(Subcommand, PartialEq, Debug)] enum Sub2 { Foo { + #[clap(value_parser)] file: String, #[clap(subcommand)] cmd: Sub3, @@ -158,8 +159,16 @@ enum SubSubCmdWithOption { } #[derive(Subcommand, PartialEq, Debug)] enum Remote { - Add { name: String, url: String }, - Remove { name: String }, + Add { + #[clap(value_parser)] + name: String, + #[clap(value_parser)] + url: String, + }, + Remove { + #[clap(value_parser)] + name: String, + }, } #[derive(Subcommand, PartialEq, Debug)] diff --git a/tests/derive/non_literal_attributes.rs b/tests/derive/non_literal_attributes.rs index 4fde20572f7..bf950fb7baa 100644 --- a/tests/derive/non_literal_attributes.rs +++ b/tests/derive/non_literal_attributes.rs @@ -26,17 +26,18 @@ struct Opt { display_order = DISPLAY_ORDER, next_line_help = true, default_value = "0", - require_equals = true + require_equals = true, + value_parser )] x: i32, - #[clap(short = 'l', long = "level", aliases = &["set-level", "lvl"])] + #[clap(short = 'l', long = "level", value_parser, aliases = &["set-level", "lvl"])] level: String, - #[clap(long("values"))] + #[clap(long("values"), value_parser)] values: Vec, - #[clap(name = "FILE", requires_if("FILE", "values"))] + #[clap(name = "FILE", value_parser, requires_if("FILE", "values"))] files: Vec, } @@ -130,7 +131,7 @@ fn parse_hex(input: &str) -> Result { #[derive(Parser, PartialEq, Debug)] struct HexOpt { - #[clap(short, parse(try_from_str = parse_hex))] + #[clap(short, value_parser = parse_hex)] number: u64, } diff --git a/tests/derive/options.rs b/tests/derive/options.rs index a2c80494283..fb23e2452f3 100644 --- a/tests/derive/options.rs +++ b/tests/derive/options.rs @@ -22,7 +22,7 @@ use clap::{Parser, Subcommand}; fn required_option() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, long)] + #[clap(short, long, value_parser)] arg: i32, } assert_eq!( @@ -45,7 +45,7 @@ fn required_option() { fn option_with_default() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, default_value = "42")] + #[clap(short, value_parser, default_value = "42")] arg: i32, } assert_eq!( @@ -60,7 +60,7 @@ fn option_with_default() { fn option_with_raw_default() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, default_value = "42")] + #[clap(short, value_parser, default_value = "42")] arg: i32, } assert_eq!( @@ -150,7 +150,7 @@ fn option_vec_from_str() { fn option_type_is_optional() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] arg: Option, } assert_eq!( @@ -166,7 +166,7 @@ fn required_with_option_type() { #[derive(Debug, PartialEq, Eq, Parser)] #[clap(subcommand_negates_reqs = true)] struct Opt { - #[clap(required = true)] + #[clap(value_parser, required = true)] req_str: Option, #[clap(subcommand)] @@ -224,7 +224,7 @@ fn ignore_qualified_option_type() { fn option_option_type_is_optional_value() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, multiple_occurrences(true))] + #[clap(short, value_parser, multiple_occurrences(true))] #[allow(clippy::option_option)] arg: Option>, } @@ -246,7 +246,7 @@ fn option_option_type_is_optional_value() { fn option_option_type_help() { #[derive(Parser, Debug)] struct Opt { - #[clap(long, value_name = "val")] + #[clap(long, value_name = "val", value_parser)] arg: Option>, } let help = utils::get_help::(); @@ -258,10 +258,10 @@ fn option_option_type_help() { fn two_option_option_types() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] arg: Option>, - #[clap(long)] + #[clap(long, value_parser)] field: Option>, } assert_eq!( @@ -312,7 +312,7 @@ fn two_option_option_types() { fn vec_type_is_multiple_occurrences() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, long)] + #[clap(short, long, value_parser)] arg: Vec, } assert_eq!( @@ -330,7 +330,7 @@ fn vec_type_is_multiple_occurrences() { fn vec_type_with_required() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, long, required = true)] + #[clap(short, long, required = true, value_parser)] arg: Vec, } assert_eq!( @@ -348,7 +348,13 @@ fn vec_type_with_required() { fn vec_type_with_multiple_values_only() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, long, multiple_values(true), multiple_occurrences(false))] + #[clap( + short, + long, + multiple_values(true), + multiple_occurrences(false), + value_parser + )] arg: Vec, } assert_eq!( @@ -386,7 +392,7 @@ fn ignore_qualified_vec_type() { fn option_vec_type() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] arg: Option>, } assert_eq!( @@ -408,7 +414,7 @@ fn option_vec_type() { fn option_vec_type_structopt_behavior() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, long, multiple_values(true), min_values(0))] + #[clap(short, long, multiple_values(true), min_values(0), value_parser)] arg: Option>, } assert_eq!( @@ -435,10 +441,10 @@ fn option_vec_type_structopt_behavior() { fn two_option_vec_types() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] arg: Option>, - #[clap(short)] + #[clap(short, value_parser)] b: Option>, } diff --git a/tests/derive/privacy.rs b/tests/derive/privacy.rs index c8f66127b2d..224a23a4cc1 100644 --- a/tests/derive/privacy.rs +++ b/tests/derive/privacy.rs @@ -30,6 +30,7 @@ mod subcommands { /// foo Foo { /// foo + #[clap(value_parser)] bars: String, }, } diff --git a/tests/derive/raw_bool_literal.rs b/tests/derive/raw_bool_literal.rs index 0e572aa8c67..7dd3618a7d0 100644 --- a/tests/derive/raw_bool_literal.rs +++ b/tests/derive/raw_bool_literal.rs @@ -13,9 +13,9 @@ fn raw_bool_literal() { #[derive(Parser, Debug, PartialEq)] #[clap(name = "raw_bool")] struct Opt { - #[clap(raw(false))] + #[clap(raw(false), value_parser)] a: String, - #[clap(raw(true))] + #[clap(raw(true), value_parser)] b: String, } diff --git a/tests/derive/raw_idents.rs b/tests/derive/raw_idents.rs index 12c5d1658f0..25762c0e6bb 100644 --- a/tests/derive/raw_idents.rs +++ b/tests/derive/raw_idents.rs @@ -4,7 +4,7 @@ use clap::Parser; fn raw_idents() { #[derive(Parser, Debug, PartialEq)] struct Opt { - #[clap(short, long)] + #[clap(short, long, value_parser)] r#type: String, } diff --git a/tests/derive/rename_all_env.rs b/tests/derive/rename_all_env.rs index 20d4f40c728..46327c12ff0 100644 --- a/tests/derive/rename_all_env.rs +++ b/tests/derive/rename_all_env.rs @@ -9,7 +9,7 @@ fn it_works() { #[derive(Debug, PartialEq, Parser)] #[clap(rename_all_env = "kebab")] struct BehaviorModel { - #[clap(env)] + #[clap(env, value_parser)] be_nice: String, } @@ -21,7 +21,7 @@ fn it_works() { fn default_is_screaming() { #[derive(Debug, PartialEq, Parser)] struct BehaviorModel { - #[clap(env)] + #[clap(env, value_parser)] be_nice: String, } @@ -34,10 +34,10 @@ fn overridable() { #[derive(Debug, PartialEq, Parser)] #[clap(rename_all_env = "kebab")] struct BehaviorModel { - #[clap(env)] + #[clap(env, value_parser)] be_nice: String, - #[clap(rename_all_env = "pascal", env)] + #[clap(rename_all_env = "pascal", env, value_parser)] be_aggressive: String, } diff --git a/tests/derive/skip.rs b/tests/derive/skip.rs index 8553134344e..d2e3b7ec086 100644 --- a/tests/derive/skip.rs +++ b/tests/derive/skip.rs @@ -12,7 +12,7 @@ use clap::Parser; fn skip_1() { #[derive(Parser, Debug, PartialEq)] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] x: u32, #[clap(skip)] s: u32, @@ -39,15 +39,17 @@ fn skip_1() { fn skip_2() { #[derive(Parser, Debug, PartialEq)] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] x: u32, #[clap(skip)] ss: String, #[clap(skip)] sn: u8, + #[clap(value_parser)] y: u32, #[clap(skip)] sz: u16, + #[clap(value_parser)] t: u32, } @@ -81,7 +83,7 @@ fn skip_enum() { #[derive(Parser, Debug, PartialEq)] pub struct Opt { - #[clap(long, short)] + #[clap(long, short, value_parser)] number: u32, #[clap(skip)] k: Kind, @@ -115,7 +117,7 @@ fn skip_help_doc_comments() { #[clap(skip)] c: u32, - #[clap(short, parse(try_from_str))] + #[clap(short, value_parser)] n: u32, } @@ -134,7 +136,7 @@ fn skip_help_doc_comments() { fn skip_val() { #[derive(Parser, Debug, PartialEq)] pub struct Opt { - #[clap(long, short)] + #[clap(long, short, value_parser)] number: u32, #[clap(skip = "key")] diff --git a/tests/derive/subcommands.rs b/tests/derive/subcommands.rs index 7dad15f210b..4f3ea1df45f 100644 --- a/tests/derive/subcommands.rs +++ b/tests/derive/subcommands.rs @@ -25,6 +25,7 @@ enum Opt { #[clap(short, long)] /// Overwrite local branches. force: bool, + #[clap(value_parser)] repo: String, }, @@ -88,7 +89,10 @@ fn test_no_parse() { #[derive(Parser, PartialEq, Debug)] enum Opt2 { - DoSomething { arg: String }, + DoSomething { + #[clap(value_parser)] + arg: String, + }, } #[test] @@ -123,11 +127,13 @@ fn test_null_commands() { #[derive(Parser, PartialEq, Debug)] #[clap(about = "Not shown")] struct Add { + #[clap(value_parser)] file: String, } /// Not shown #[derive(Parser, PartialEq, Debug)] struct Fetch { + #[clap(value_parser)] remote: String, } #[derive(Parser, PartialEq, Debug)] @@ -337,12 +343,15 @@ fn update_subcommands() { #[derive(Parser, PartialEq, Debug)] struct Command1 { + #[clap(value_parser)] arg1: i32, + #[clap(value_parser)] arg2: i32, } #[derive(Parser, PartialEq, Debug)] struct Command2 { + #[clap(value_parser)] arg2: i32, } @@ -396,12 +405,15 @@ fn update_sub_subcommands() { #[derive(Args, PartialEq, Debug)] struct Command1 { + #[clap(value_parser)] arg1: i32, + #[clap(value_parser)] arg2: i32, } #[derive(Args, PartialEq, Debug)] struct Command2 { + #[clap(value_parser)] arg2: i32, } @@ -454,12 +466,15 @@ fn update_ext_subcommand() { #[derive(Args, PartialEq, Debug)] struct Command1 { + #[clap(value_parser)] arg1: i32, + #[clap(value_parser)] arg2: i32, } #[derive(Args, PartialEq, Debug)] struct Command2 { + #[clap(value_parser)] arg2: i32, } @@ -554,6 +569,7 @@ fn built_in_subcommand_escaped() { #[derive(Debug, PartialEq, Parser)] enum Command { Install { + #[clap(value_parser)] arg: Option, }, #[clap(external_subcommand)] @@ -582,6 +598,7 @@ fn built_in_subcommand_escaped() { #[derive(Debug, PartialEq, Parser)] enum Command { Install { + #[clap(value_parser)] arg: Option, }, #[clap(external_subcommand)] diff --git a/tests/derive/type_alias_regressions.rs b/tests/derive/type_alias_regressions.rs index 1c70936bcdb..a792ccb1315 100644 --- a/tests/derive/type_alias_regressions.rs +++ b/tests/derive/type_alias_regressions.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + /// Regression test to ensure that type aliases do not cause compilation failures. use std::str::FromStr; @@ -23,10 +25,11 @@ type Option = std::option::Option>; #[derive(Parser)] pub struct Opts { + #[clap(value_parser)] another_string: String, #[clap(subcommand)] command: Command, - #[clap(short, long, arg_enum)] + #[clap(short, long, arg_enum, value_parser)] choice: ArgChoice, } diff --git a/tests/derive/utf8.rs b/tests/derive/utf8.rs index 0f9fd15dc3d..3aa91ac91ec 100644 --- a/tests/derive/utf8.rs +++ b/tests/derive/utf8.rs @@ -6,12 +6,13 @@ use std::os::unix::ffi::OsStringExt; #[derive(Parser, Debug, PartialEq, Eq)] struct Positional { + #[clap(value_parser)] arg: String, } #[derive(Parser, Debug, PartialEq, Eq)] struct Named { - #[clap(short, long)] + #[clap(short, long, value_parser)] arg: String, } From 573d496bc6bacc757aedf98d50a2cfd4ea391fd5 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 23 May 2022 16:58:07 -0500 Subject: [PATCH 5/9] fix: Deprecate forbid_empty_values --- src/builder/arg.rs | 53 +++++------------------------------ src/builder/debug_asserts.rs | 2 +- src/parser/validator.rs | 25 +++++++++-------- tests/builder/default_vals.rs | 2 +- tests/builder/empty_values.rs | 14 ++++----- tests/builder/opts.rs | 4 +-- 6 files changed, 32 insertions(+), 68 deletions(-) diff --git a/src/builder/arg.rs b/src/builder/arg.rs index 1a015c36f01..8195b9a0f74 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -1945,53 +1945,13 @@ impl<'help> Arg<'help> { } } - /// Don't allow an argument to accept explicitly empty values. - /// - /// An empty value must be specified at the command line with an explicit `""`, `''`, or - /// `--option=` - /// - /// **NOTE:** By default empty values are allowed. - /// - /// **NOTE:** Setting this requires [`Arg::takes_value`]. - /// - /// # Examples - /// - /// The default is allowing empty values. - /// - /// ```rust - /// # use clap::{Command, Arg, ErrorKind}; - /// let res = Command::new("prog") - /// .arg(Arg::new("cfg") - /// .long("config") - /// .short('v') - /// .takes_value(true)) - /// .try_get_matches_from(vec![ - /// "prog", "--config=" - /// ]); - /// - /// assert!(res.is_ok()); - /// assert_eq!(res.unwrap().value_of("cfg"), Some("")); - /// ``` - /// - /// By adding this setting, we can forbid empty values. - /// - /// ```rust - /// # use clap::{Command, Arg, ErrorKind}; - /// let res = Command::new("prog") - /// .arg(Arg::new("cfg") - /// .long("config") - /// .short('v') - /// .takes_value(true) - /// .forbid_empty_values(true)) - /// .try_get_matches_from(vec![ - /// "prog", "--config=" - /// ]); - /// - /// assert!(res.is_err()); - /// assert_eq!(res.unwrap_err().kind(), ErrorKind::EmptyValue); - /// ``` + /// Deprecated, replaced with [`Arg::value_parser(NonEmptyStringValueParser::new())`] #[inline] #[must_use] + #[deprecated( + since = "3.2.0", + note = "Replaced with `Arg::value_parser(NonEmptyStringValueParser::new())`" + )] pub fn forbid_empty_values(self, yes: bool) -> Self { if yes { self.setting(ArgSettings::ForbidEmptyValues) @@ -4726,7 +4686,8 @@ impl<'help> Arg<'help> { self.is_set(ArgSettings::AllowHyphenValues) } - /// Report whether [`Arg::forbid_empty_values`] is set + /// Deprecated, replaced with [`Arg::get_value_parser()`] + #[deprecated(since = "3.2.0", note = "Replaced with `Arg::get_value_parser()`")] pub fn is_forbid_empty_values_set(&self) -> bool { self.is_set(ArgSettings::ForbidEmptyValues) } diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs index aba342fca24..9ffb4e9dfa6 100644 --- a/src/builder/debug_asserts.rs +++ b/src/builder/debug_asserts.rs @@ -722,7 +722,6 @@ fn assert_arg_flags(arg: &Arg) { } } - checker!(is_forbid_empty_values_set requires is_takes_value_set); checker!(is_require_value_delimiter_set requires is_takes_value_set); checker!(is_require_value_delimiter_set requires is_use_value_delimiter_set); checker!(is_hide_possible_values_set requires is_takes_value_set); @@ -734,6 +733,7 @@ fn assert_arg_flags(arg: &Arg) { checker!(is_ignore_case_set requires is_takes_value_set); { #![allow(deprecated)] + checker!(is_forbid_empty_values_set requires is_takes_value_set); checker!(is_allow_invalid_utf8_set requires is_takes_value_set); } } diff --git a/src/parser/validator.rs b/src/parser/validator.rs index f98a922b0c5..dca9789e572 100644 --- a/src/parser/validator.rs +++ b/src/parser/validator.rs @@ -119,17 +119,20 @@ impl<'help, 'cmd> Validator<'help, 'cmd> { )); } } - if arg.is_forbid_empty_values_set() && val.is_empty() && matcher.contains(&arg.id) { - debug!("Validator::validate_arg_values: illegal empty val found"); - return Err(Error::empty_value( - self.cmd, - &get_possible_values(arg) - .iter() - .filter(|pv| !pv.is_hide_set()) - .map(PossibleValue::get_name) - .collect::>(), - arg.to_string(), - )); + { + #![allow(deprecated)] + if arg.is_forbid_empty_values_set() && val.is_empty() && matcher.contains(&arg.id) { + debug!("Validator::validate_arg_values: illegal empty val found"); + return Err(Error::empty_value( + self.cmd, + &get_possible_values(arg) + .iter() + .filter(|pv| !pv.is_hide_set()) + .map(PossibleValue::get_name) + .collect::>(), + arg.to_string(), + )); + } } if let Some(ref vtor) = arg.validator { diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index ba03da58a4b..f85a0abc650 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -23,7 +23,7 @@ fn opt_without_value_fail() { arg!(o: -o "some opt") .required(false) .default_value("default") - .forbid_empty_values(true), + .value_parser(clap::builder::NonEmptyStringValueParser::new()), ) .try_get_matches_from(vec!["", "-o"]); assert!(r.is_err()); diff --git a/tests/builder/empty_values.rs b/tests/builder/empty_values.rs index c537f0c310a..91ae6eaedca 100644 --- a/tests/builder/empty_values.rs +++ b/tests/builder/empty_values.rs @@ -33,7 +33,7 @@ fn no_empty_values() { Arg::new("config") .long("config") .takes_value(true) - .forbid_empty_values(true), + .value_parser(clap::builder::NonEmptyStringValueParser::new()), ) .try_get_matches_from(&["config", "--config", ""]); assert!(m.is_err()); @@ -44,7 +44,7 @@ fn no_empty_values() { Arg::new("config") .short('c') .takes_value(true) - .forbid_empty_values(true), + .value_parser(clap::builder::NonEmptyStringValueParser::new()), ) .try_get_matches_from(&["config", "-c", ""]); assert!(m.is_err()); @@ -58,7 +58,7 @@ fn no_empty_values_with_equals() { Arg::new("config") .long("config") .takes_value(true) - .forbid_empty_values(true), + .value_parser(clap::builder::NonEmptyStringValueParser::new()), ) .try_get_matches_from(&["config", "--config="]); assert!(m.is_err()); @@ -69,7 +69,7 @@ fn no_empty_values_with_equals() { Arg::new("config") .short('c') .takes_value(true) - .forbid_empty_values(true), + .value_parser(clap::builder::NonEmptyStringValueParser::new()), ) .try_get_matches_from(&["config", "-c="]); assert!(m.is_err()); @@ -83,7 +83,7 @@ fn no_empty_values_without_equals() { Arg::new("config") .long("config") .takes_value(true) - .forbid_empty_values(true), + .value_parser(clap::builder::NonEmptyStringValueParser::new()), ) .try_get_matches_from(&["config", "--config"]); assert!(m.is_err()); @@ -94,7 +94,7 @@ fn no_empty_values_without_equals() { Arg::new("config") .short('c') .takes_value(true) - .forbid_empty_values(true), + .value_parser(clap::builder::NonEmptyStringValueParser::new()), ) .try_get_matches_from(&["config", "-c"]); assert!(m.is_err()); @@ -107,7 +107,7 @@ fn no_empty_values_without_equals_but_requires_equals() { Arg::new("config") .long("config") .takes_value(true) - .forbid_empty_values(true) + .value_parser(clap::builder::NonEmptyStringValueParser::new()) .require_equals(true), ); let m = cmd.clone().try_get_matches_from(&["config", "--config"]); diff --git a/tests/builder/opts.rs b/tests/builder/opts.rs index f0b927ba6c8..9500952cb70 100644 --- a/tests/builder/opts.rs +++ b/tests/builder/opts.rs @@ -36,7 +36,7 @@ fn require_equals_fail() { .arg( Arg::new("cfg") .require_equals(true) - .forbid_empty_values(true) + .value_parser(clap::builder::NonEmptyStringValueParser::new()) .takes_value(true) .long("config"), ) @@ -103,7 +103,7 @@ fn require_equals_no_empty_values_fail() { Arg::new("cfg") .takes_value(true) .require_equals(true) - .forbid_empty_values(true) + .value_parser(clap::builder::NonEmptyStringValueParser::new()) .long("config"), ) .arg(Arg::new("some")) From 256643f8d3bc67e7c0ff85f33323d68efa03b994 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 23 May 2022 20:16:02 -0500 Subject: [PATCH 6/9] fix: Deprecate possible_values --- benches/03_complex.rs | 8 +- benches/05_ripgrep.rs | 2 +- clap_complete/examples/completion.rs | 4 +- clap_complete/examples/dynamic.rs | 2 +- clap_complete/src/generator/utils.rs | 1 + clap_complete/src/lib.rs | 4 +- clap_complete/src/shells/bash.rs | 2 +- clap_complete/src/shells/shell.rs | 3 +- clap_complete/tests/common.rs | 7 +- clap_complete_fig/tests/common.rs | 7 +- clap_mangen/tests/common.rs | 7 +- src/builder/arg.rs | 164 ++++---------------------- src/builder/command.rs | 2 +- src/builder/possible_value.rs | 14 ++- src/error/kind.rs | 3 +- tests/builder/app_settings.rs | 4 +- tests/builder/default_missing_vals.rs | 4 +- tests/builder/default_vals.rs | 4 +- tests/builder/env.rs | 4 +- tests/builder/help.rs | 48 ++++---- tests/builder/positionals.rs | 2 +- tests/builder/possible_values.rs | 101 ++++++++-------- tests/builder/require.rs | 6 +- tests/builder/unicode.rs | 2 +- tests/builder/utils.rs | 4 +- tests/derive/arg_enum.rs | 31 ++--- 26 files changed, 167 insertions(+), 273 deletions(-) diff --git a/benches/03_complex.rs b/benches/03_complex.rs index 3ac81bb15dc..b4e76020f73 100644 --- a/benches/03_complex.rs +++ b/benches/03_complex.rs @@ -24,9 +24,9 @@ macro_rules! create_app { arg!([positional2] "tests positionals with exclusions"), arg!(-O --Option "tests options with specific value sets") .required(false) - .possible_values(OPT3_VALS), + .value_parser(OPT3_VALS), arg!([positional3] ... "tests positionals with specific values") - .possible_values(POS3_VALS), + .value_parser(POS3_VALS), arg!(--multvals "Tests multiple values not mult occs").required(false).value_names(&["one", "two"]), arg!( --multvalsmo "Tests multiple values, not mult occs" @@ -96,7 +96,7 @@ pub fn build_from_builder(c: &mut Criterion) { .long("Option") .takes_value(true) .help("tests options with specific value sets") - .possible_values(OPT3_VALS), + .value_parser(OPT3_VALS), ) .arg( Arg::new("positional3") @@ -105,7 +105,7 @@ pub fn build_from_builder(c: &mut Criterion) { .multiple_occurrences(true) .help("tests positionals with specific values") .index(4) - .possible_values(POS3_VALS), + .value_parser(POS3_VALS), ) .arg( Arg::new("multvals") diff --git a/benches/05_ripgrep.rs b/benches/05_ripgrep.rs index ddd7f3ea5cb..6ed8448d339 100644 --- a/benches/05_ripgrep.rs +++ b/benches/05_ripgrep.rs @@ -352,7 +352,7 @@ where .value_name("WHEN") .takes_value(true) .hide_possible_values(true) - .possible_values(["never", "auto", "always", "ansi"]), + .value_parser(["never", "auto", "always", "ansi"]), ) .arg( flag("colors") diff --git a/clap_complete/examples/completion.rs b/clap_complete/examples/completion.rs index 4b061f746e5..14d803788bd 100644 --- a/clap_complete/examples/completion.rs +++ b/clap_complete/examples/completion.rs @@ -12,7 +12,7 @@ //! . ./value_hints.fish //! ./target/debug/examples/value_hints -- //! ``` -use clap::{Arg, Command, ValueHint}; +use clap::{value_parser, Arg, Command, ValueHint}; use clap_complete::{generate, Generator, Shell}; use std::io; @@ -23,7 +23,7 @@ fn build_cli() -> Command<'static> { .arg( Arg::new("generator") .long("generate") - .possible_values(Shell::possible_values()), + .value_parser(value_parser!(Shell)), ) .arg( Arg::new("unknown") diff --git a/clap_complete/examples/dynamic.rs b/clap_complete/examples/dynamic.rs index 5b945cf0058..58c60be969c 100644 --- a/clap_complete/examples/dynamic.rs +++ b/clap_complete/examples/dynamic.rs @@ -13,7 +13,7 @@ fn command() -> clap::Command<'static> { clap::Arg::new("format") .long("--format") .short('F') - .possible_values(["json", "yaml", "toml"]), + .value_parser(["json", "yaml", "toml"]), ) .args_conflicts_with_subcommands(true); let cmd = clap_complete::dynamic::bash::CompleteCommand::augment_subcommands(cmd); diff --git a/clap_complete/src/generator/utils.rs b/clap_complete/src/generator/utils.rs index 251f1416897..da07b353ca4 100644 --- a/clap_complete/src/generator/utils.rs +++ b/clap_complete/src/generator/utils.rs @@ -128,6 +128,7 @@ pub fn flags<'help>(p: &Command<'help>) -> Vec> { /// Get the possible values for completion pub fn possible_values<'help>(a: &Arg<'help>) -> Option>> { + #![allow(deprecated)] if !a.is_takes_value_set() { None } else if let Some(pvs) = a.get_possible_values() { diff --git a/clap_complete/src/lib.rs b/clap_complete/src/lib.rs index 3da01ac8527..3c2f1def637 100644 --- a/clap_complete/src/lib.rs +++ b/clap_complete/src/lib.rs @@ -22,7 +22,7 @@ //! ## Example //! //! ```rust,no_run -//! use clap::{Command, AppSettings, Arg, ValueHint}; +//! use clap::{Command, AppSettings, Arg, ValueHint, value_parser}; //! use clap_complete::{generate, Generator, Shell}; //! use std::io; //! @@ -35,7 +35,7 @@ //! .arg( //! Arg::new("generator") //! .long("generate") -//! .possible_values(Shell::possible_values()), +//! .value_parser(value_parser!(Shell)), //! ) //! } //! diff --git a/clap_complete/src/shells/bash.rs b/clap_complete/src/shells/bash.rs index d017d0ec9f5..f1a44b40e1e 100644 --- a/clap_complete/src/shells/bash.rs +++ b/clap_complete/src/shells/bash.rs @@ -201,7 +201,7 @@ fn all_options_for_path(cmd: &Command, path: &str) -> String { write!(&mut opts, "--{} ", long).unwrap(); } for pos in p.get_positionals() { - if let Some(vals) = pos.get_possible_values() { + if let Some(vals) = utils::possible_values(pos) { for value in vals { write!(&mut opts, "{} ", value.get_name()).unwrap(); } diff --git a/clap_complete/src/shells/shell.rs b/clap_complete/src/shells/shell.rs index 63063bb7c8b..b8268639383 100644 --- a/clap_complete/src/shells/shell.rs +++ b/clap_complete/src/shells/shell.rs @@ -23,7 +23,8 @@ pub enum Shell { } impl Shell { - /// Report all `possible_values` + /// Deprecated, replaced with [`ArgEnumValueParser`][clap::builder::ArgEnumValueParser] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgEnumValueParser`")] pub fn possible_values() -> impl Iterator> { Shell::value_variants() .iter() diff --git a/clap_complete/tests/common.rs b/clap_complete/tests/common.rs index f68e3de1a75..838ed381e52 100644 --- a/clap_complete/tests/common.rs +++ b/clap_complete/tests/common.rs @@ -30,7 +30,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> { .long("config") .visible_alias("conf"), ) - .arg(clap::Arg::new("choice").possible_values(["first", "second"])) + .arg(clap::Arg::new("choice").value_parser(["first", "second"])) .subcommand( clap::Command::new("test").about("tests things").arg( clap::Arg::new("case") @@ -141,7 +141,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> { clap::Arg::new("config") .long("config") .takes_value(true) - .possible_values([clap::PossibleValue::new("Lest quotes aren't escaped.")]) + .value_parser([clap::PossibleValue::new("Lest quotes aren't escaped.")]) .help("the other case to test"), ), ), @@ -154,7 +154,8 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> { .arg( clap::Arg::new("choice") .long("choice") - .possible_values(["bash", "fish", "zsh"]), + .takes_value(true) + .value_parser(["bash", "fish", "zsh"]), ) .arg( clap::Arg::new("unknown") diff --git a/clap_complete_fig/tests/common.rs b/clap_complete_fig/tests/common.rs index f68e3de1a75..838ed381e52 100644 --- a/clap_complete_fig/tests/common.rs +++ b/clap_complete_fig/tests/common.rs @@ -30,7 +30,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> { .long("config") .visible_alias("conf"), ) - .arg(clap::Arg::new("choice").possible_values(["first", "second"])) + .arg(clap::Arg::new("choice").value_parser(["first", "second"])) .subcommand( clap::Command::new("test").about("tests things").arg( clap::Arg::new("case") @@ -141,7 +141,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> { clap::Arg::new("config") .long("config") .takes_value(true) - .possible_values([clap::PossibleValue::new("Lest quotes aren't escaped.")]) + .value_parser([clap::PossibleValue::new("Lest quotes aren't escaped.")]) .help("the other case to test"), ), ), @@ -154,7 +154,8 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> { .arg( clap::Arg::new("choice") .long("choice") - .possible_values(["bash", "fish", "zsh"]), + .takes_value(true) + .value_parser(["bash", "fish", "zsh"]), ) .arg( clap::Arg::new("unknown") diff --git a/clap_mangen/tests/common.rs b/clap_mangen/tests/common.rs index 9d8ee45b166..3b8bcdc3cfb 100644 --- a/clap_mangen/tests/common.rs +++ b/clap_mangen/tests/common.rs @@ -27,7 +27,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> { .long("config") .visible_alias("conf"), ) - .arg(clap::Arg::new("choice").possible_values(["first", "second"])) + .arg(clap::Arg::new("choice").value_parser(["first", "second"])) .subcommand( clap::Command::new("test").about("tests things").arg( clap::Arg::new("case") @@ -130,7 +130,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> { clap::Arg::new("config") .long("config") .takes_value(true) - .possible_values([clap::PossibleValue::new("Lest quotes aren't escaped.")]) + .value_parser([clap::PossibleValue::new("Lest quotes aren't escaped.")]) .help("the other case to test"), ), ), @@ -143,7 +143,8 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> { .arg( clap::Arg::new("choice") .long("choice") - .possible_values(["bash", "fish", "zsh"]), + .takes_value(true) + .value_parser(["bash", "fish", "zsh"]), ) .arg( clap::Arg::new("unknown") diff --git a/src/builder/arg.rs b/src/builder/arg.rs index 8195b9a0f74..4ee03e118a5 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -1654,76 +1654,11 @@ impl<'help> Arg<'help> { }) } - /// Add a possible value for this argument. - /// - /// At runtime, `clap` verifies that only one of the specified values was used, or fails with - /// error message. - /// - /// **NOTE:** This setting only applies to [options] and [positional arguments] - /// - /// **NOTE:** You can use both strings directly or use [`PossibleValue`] if you want more control - /// over single possible values. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{Command, Arg}; - /// Arg::new("mode") - /// .takes_value(true) - /// .possible_value("fast") - /// .possible_value("slow") - /// .possible_value("medium") - /// # ; - /// ``` - /// The same using [`PossibleValue`]: - /// - /// ```rust - /// # use clap::{Command, Arg, PossibleValue}; - /// Arg::new("mode").takes_value(true) - /// .possible_value(PossibleValue::new("fast")) - /// // value with a help text - /// .possible_value(PossibleValue::new("slow").help("not that fast")) - /// // value that is hidden from completion and help text - /// .possible_value(PossibleValue::new("medium").hide(true)) - /// # ; - /// ``` - /// - /// ```rust - /// # use clap::{Command, Arg}; - /// let m = Command::new("prog") - /// .arg(Arg::new("mode") - /// .long("mode") - /// .takes_value(true) - /// .possible_value("fast") - /// .possible_value("slow") - /// .possible_value("medium")) - /// .get_matches_from(vec![ - /// "prog", "--mode", "fast" - /// ]); - /// assert!(m.is_present("mode")); - /// assert_eq!(m.value_of("mode"), Some("fast")); - /// ``` - /// - /// The next example shows a failed parse from using a value which wasn't defined as one of the - /// possible values. - /// - /// ```rust - /// # use clap::{Command, Arg, ErrorKind}; - /// let res = Command::new("prog") - /// .arg(Arg::new("mode") - /// .long("mode") - /// .takes_value(true) - /// .possible_value("fast") - /// .possible_value("slow") - /// .possible_value("medium")) - /// .try_get_matches_from(vec![ - /// "prog", "--mode", "wrong" - /// ]); - /// assert!(res.is_err()); - /// assert_eq!(res.unwrap_err().kind(), ErrorKind::InvalidValue); - /// ``` - /// [options]: Arg::takes_value() - /// [positional arguments]: Arg::index() + /// Deprecated, replaced with [`Arg::value_parser(PossibleValuesParser::new(...))`] + #[deprecated( + since = "3.2.0", + note = "Replaced with `Arg::value_parser(PossibleValuesParser::new(...)).takes_value(true)`" + )] #[must_use] pub fn possible_value(mut self, value: T) -> Self where @@ -1733,73 +1668,11 @@ impl<'help> Arg<'help> { self.takes_value(true) } - /// Possible values for this argument. - /// - /// At runtime, `clap` verifies that - /// only one of the specified values was used, or fails with an error message. - /// - /// **NOTE:** This setting only applies to [options] and [positional arguments] - /// - /// **NOTE:** You can use both strings directly or use [`PossibleValue`] if you want more control - /// over single possible values. - /// - /// See also [hide_possible_values][Arg::hide_possible_values]. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{Command, Arg}; - /// Arg::new("mode") - /// .takes_value(true) - /// .possible_values(["fast", "slow", "medium"]) - /// # ; - /// ``` - /// The same using [`PossibleValue`]: - /// - /// ```rust - /// # use clap::{Command, Arg, PossibleValue}; - /// Arg::new("mode").takes_value(true).possible_values([ - /// PossibleValue::new("fast"), - /// // value with a help text - /// PossibleValue::new("slow").help("not that fast"), - /// // value that is hidden from completion and help text - /// PossibleValue::new("medium").hide(true), - /// ]) - /// # ; - /// ``` - /// - /// ```rust - /// # use clap::{Command, Arg}; - /// let m = Command::new("prog") - /// .arg(Arg::new("mode") - /// .long("mode") - /// .takes_value(true) - /// .possible_values(["fast", "slow", "medium"])) - /// .get_matches_from(vec![ - /// "prog", "--mode", "fast" - /// ]); - /// assert!(m.is_present("mode")); - /// assert_eq!(m.value_of("mode"), Some("fast")); - /// ``` - /// - /// The next example shows a failed parse from using a value which wasn't defined as one of the - /// possible values. - /// - /// ```rust - /// # use clap::{Command, Arg, ErrorKind}; - /// let res = Command::new("prog") - /// .arg(Arg::new("mode") - /// .long("mode") - /// .takes_value(true) - /// .possible_values(["fast", "slow", "medium"])) - /// .try_get_matches_from(vec![ - /// "prog", "--mode", "wrong" - /// ]); - /// assert!(res.is_err()); - /// assert_eq!(res.unwrap_err().kind(), ErrorKind::InvalidValue); - /// ``` - /// [options]: Arg::takes_value() - /// [positional arguments]: Arg::index() + /// Deprecated, replaced with [`Arg::value_parser(PossibleValuesParser::new(...))`] + #[deprecated( + since = "3.2.0", + note = "Replaced with `Arg::value_parser(PossibleValuesParser::new(...)).takes_value(true)`" + )] #[must_use] pub fn possible_values(mut self, values: I) -> Self where @@ -1832,7 +1705,7 @@ impl<'help> Arg<'help> { /// .long("option") /// .takes_value(true) /// .ignore_case(true) - /// .possible_value("test123")) + /// .value_parser(["test123"])) /// .get_matches_from(vec![ /// "pv", "--option", "TeSt123", /// ]); @@ -1851,7 +1724,7 @@ impl<'help> Arg<'help> { /// .takes_value(true) /// .ignore_case(true) /// .multiple_values(true) - /// .possible_values(&["test123", "test321"])) + /// .value_parser(["test123", "test321"])) /// .get_matches_from(vec![ /// "pv", "--option", "TeSt123", "teST123", "tESt321" /// ]); @@ -2421,7 +2294,7 @@ impl<'help> Arg<'help> { /// Command::new("prog") /// .arg(Arg::new("color").long("color") /// .value_name("WHEN") - /// .possible_values(["always", "auto", "never"]) + /// .value_parser(["always", "auto", "never"]) /// .default_value("auto") /// .overrides_with("color") /// .min_values(0) @@ -2950,7 +2823,7 @@ impl<'help> Arg<'help> { } } - /// Do not display the [possible values][Arg::possible_values] in the help message. + /// Do not display the [possible values][crate::builder::ValueParser::possible_values] in the help message. /// /// This is useful for args with many values, or ones which are explained elsewhere in the /// help text. @@ -2967,7 +2840,7 @@ impl<'help> Arg<'help> { /// let m = Command::new("prog") /// .arg(Arg::new("mode") /// .long("mode") - /// .possible_values(["fast", "slow"]) + /// .value_parser(["fast", "slow"]) /// .takes_value(true) /// .hide_possible_values(true)); /// ``` @@ -4541,8 +4414,11 @@ impl<'help> Arg<'help> { Some(longs) } - /// Get the list of the possible values for this argument, if any - #[inline] + /// Deprecated, replaced with [`Arg::get_value_parser().possible_values()`] + #[deprecated( + since = "3.2.0", + note = "Replaced with `Arg::get_value_parser().possible_values()`" + )] pub fn get_possible_values(&self) -> Option<&[PossibleValue<'help>]> { if self.possible_vals.is_empty() { None diff --git a/src/builder/command.rs b/src/builder/command.rs index dbc3f4c4e01..b54012bd3dc 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -1948,7 +1948,7 @@ impl<'help> App<'help> { /// .arg(Arg::new("format") /// .long("format") /// .takes_value(true) - /// .possible_values(["txt", "json"])) + /// .value_parser(["txt", "json"])) /// .replace("--save-all", &["--save-context", "--save-runtime", "--format=json"]) /// .get_matches_from(vec!["cmd", "--save-all"]); /// diff --git a/src/builder/possible_value.rs b/src/builder/possible_value.rs index e56fb858ce6..019878ee32b 100644 --- a/src/builder/possible_value.rs +++ b/src/builder/possible_value.rs @@ -14,14 +14,16 @@ use crate::util::eq_ignore_case; /// ```rust /// # use clap::{Arg, PossibleValue}; /// let cfg = Arg::new("config") -/// .takes_value(true) -/// .value_name("FILE") -/// .possible_value(PossibleValue::new("fast")) -/// .possible_value(PossibleValue::new("slow").help("slower than fast")) -/// .possible_value(PossibleValue::new("secret speed").hide(true)); +/// .takes_value(true) +/// .value_name("FILE") +/// .value_parser([ +/// PossibleValue::new("fast"), +/// PossibleValue::new("slow").help("slower than fast"), +/// PossibleValue::new("secret speed").hide(true) +/// ]); /// ``` /// [Args]: crate::Arg -/// [possible values]: crate::Arg::possible_value() +/// [possible values]: crate::builder::ValueParser::possible_values /// [hide]: PossibleValue::hide() /// [help]: PossibleValue::help() #[derive(Debug, Default, Clone, PartialEq, Eq)] diff --git a/src/error/kind.rs b/src/error/kind.rs index 2c7c422a634..21256609a8c 100644 --- a/src/error/kind.rs +++ b/src/error/kind.rs @@ -11,8 +11,7 @@ pub enum ErrorKind { /// # use clap::{Command, Arg, ErrorKind}; /// let result = Command::new("prog") /// .arg(Arg::new("speed") - /// .possible_value("fast") - /// .possible_value("slow")) + /// .value_parser(["fast", "slow"])) /// .try_get_matches_from(vec!["prog", "other"]); /// assert!(result.is_err()); /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); diff --git a/tests/builder/app_settings.rs b/tests/builder/app_settings.rs index 20c5109b140..46f584ae642 100644 --- a/tests/builder/app_settings.rs +++ b/tests/builder/app_settings.rs @@ -415,8 +415,8 @@ fn skip_possible_values() { .args(&[ arg!(-o --opt "some option") .required(false) - .possible_values(["one", "two"]), - arg!([arg1] "some pos arg").possible_values(["three", "four"]), + .value_parser(["one", "two"]), + arg!([arg1] "some pos arg").value_parser(["three", "four"]), ]); utils::assert_output(cmd, "test --help", SKIP_POS_VALS, false); diff --git a/tests/builder/default_missing_vals.rs b/tests/builder/default_missing_vals.rs index 63bd6fa404c..68d0a7db818 100644 --- a/tests/builder/default_missing_vals.rs +++ b/tests/builder/default_missing_vals.rs @@ -158,14 +158,14 @@ fn default_missing_value_flag_value() { #[cfg(debug_assertions)] #[test] -#[should_panic = "Argument `arg`'s default_missing_value=value doesn't match possible values"] +#[should_panic = "Argument `arg`'s default_missing_value=\"value\" failed validation: error: \"value\" isn't a valid value for ''"] fn default_missing_values_are_possible_values() { use clap::{Arg, Command}; let _ = Command::new("test") .arg( Arg::new("arg") - .possible_values(["one", "two"]) + .value_parser(["one", "two"]) .default_missing_value("value"), ) .try_get_matches(); diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index f85a0abc650..30d3cea6006 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -637,14 +637,14 @@ fn required_args_with_default_values() { #[cfg(debug_assertions)] #[test] -#[should_panic = "Argument `arg`'s default_value=value doesn't match possible values"] +#[should_panic = "Argument `arg`'s default_value=\"value\" failed validation: error: \"value\" isn't a valid value for ''"] fn default_values_are_possible_values() { use clap::{Arg, Command}; let _ = Command::new("test") .arg( Arg::new("arg") - .possible_values(["one", "two"]) + .value_parser(["one", "two"]) .default_value("value"), ) .try_get_matches(); diff --git a/tests/builder/env.rs b/tests/builder/env.rs index 8bc94e3bc6d..df4ca24628e 100644 --- a/tests/builder/env.rs +++ b/tests/builder/env.rs @@ -259,7 +259,7 @@ fn possible_value() { arg!([arg] "some opt") .env("CLP_TEST_ENV_PV") .takes_value(true) - .possible_value("env"), + .value_parser(["env"]), ) .try_get_matches_from(vec![""]); @@ -279,7 +279,7 @@ fn not_possible_value() { arg!([arg] "some opt") .env("CLP_TEST_ENV_NPV") .takes_value(true) - .possible_value("never"), + .value_parser(["never"]), ) .try_get_matches_from(vec![""]); diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 880a3376539..68cb2811c8d 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -988,31 +988,32 @@ OPTIONS: .arg( Arg::new("possible_values") .long("possible-values") - .possible_value( + .takes_value(true) + .value_parser([ PossibleValue::new("short_name") .help("Long enough help message, barely warrant wrapping"), - ) - .possible_value( PossibleValue::new("second").help("Short help gets handled the same"), - ), + ]), ) .arg( Arg::new("possible_values_with_new_line") .long("possible-values-with-new-line") - .possible_value( + .takes_value(true) + .value_parser([ PossibleValue::new("long enough name to trigger new line").help( "Really long enough help message to clearly warrant wrapping believe me", ), - ) - .possible_value("second"), + PossibleValue::new("second"), + ]), ) .arg( Arg::new("possible_values_without_new_line") .long("possible-values-without-new-line") - .possible_value( + .takes_value(true) + .value_parser([ PossibleValue::new("name").help("Short enough help message with no wrapping"), - ) - .possible_value(PossibleValue::new("second").help("short help")), + PossibleValue::new("second").help("short help"), + ]), ); utils::assert_output(cmd, "test --help", WRAPPED_HELP, false); } @@ -1052,7 +1053,7 @@ fn hide_possible_vals() { .short('p') .long("pos") .value_name("VAL") - .possible_values(["fast", "slow"]) + .value_parser(["fast", "slow"]) .help("Some vals") .takes_value(true), ) @@ -1062,7 +1063,7 @@ fn hide_possible_vals() { .long("cafe") .value_name("FILE") .hide_possible_values(true) - .possible_values(["fast", "slow"]) + .value_parser(["fast", "slow"]) .help("A coffeehouse, coffee shop, or café.") .takes_value(true), ); @@ -1078,8 +1079,11 @@ fn hide_single_possible_val() { .short('p') .long("pos") .value_name("VAL") - .possible_values(["fast", "slow"]) - .possible_value(PossibleValue::new("secret speed").hide(true)) + .value_parser([ + "fast".into(), + "slow".into(), + PossibleValue::new("secret speed").hide(true), + ]) .help("Some vals") .takes_value(true), ) @@ -1138,9 +1142,11 @@ OPTIONS: .short('p') .long("pos") .value_name("VAL") - .possible_value("fast") - .possible_value(PossibleValue::new("slow").help("not as fast")) - .possible_value(PossibleValue::new("secret speed").hide(true)) + .value_parser([ + PossibleValue::new("fast"), + PossibleValue::new("slow").help("not as fast"), + PossibleValue::new("secret speed").hide(true), + ]) .help("Some vals") .takes_value(true), ) @@ -1284,7 +1290,7 @@ fn issue_688_hide_pos_vals() { .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \ images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]") .long("filter") - .possible_values(filter_values) + .value_parser(filter_values) .takes_value(true)); utils::assert_output(app1, "ctest --help", ISSUE_688, false); @@ -1295,7 +1301,7 @@ fn issue_688_hide_pos_vals() { .help("Sets the filter, or sampling method, to use for interpolation when resizing the particle \ images. The default is Linear (Bilinear).") .long("filter") - .possible_values(filter_values) + .value_parser(filter_values) .takes_value(true)); utils::assert_output(app2, "ctest --help", ISSUE_688, false); @@ -1674,7 +1680,7 @@ fn escaped_whitespace_values() { .help("Pass an argument to the program.") .long("arg") .default_value("\n") - .possible_values(["normal", " ", "\n", "\t", "other"]), + .value_parser(["normal", " ", "\n", "\t", "other"]), ); utils::assert_output(app1, "default --help", ESCAPED_DEFAULT_VAL, false); } @@ -1847,7 +1853,7 @@ fn multiple_custom_help_headers() { .long("speed") .short('s') .value_name("SPEED") - .possible_values(["fast", "slow"]) + .value_parser(["fast", "slow"]) .help("How fast?") .takes_value(true), ); diff --git a/tests/builder/positionals.rs b/tests/builder/positionals.rs index 4ad3856e9d0..2e3a4fd890b 100644 --- a/tests/builder/positionals.rs +++ b/tests/builder/positionals.rs @@ -148,7 +148,7 @@ fn positional_possible_values() { let r = Command::new("positional_possible_values") .args(&[ arg!(-f --flag "some flag"), - Arg::new("positional").index(1).possible_value("test123"), + Arg::new("positional").index(1).value_parser(["test123"]), ]) .try_get_matches_from(vec!["", "-f", "test123"]); assert!(r.is_ok(), "{:#?}", r); diff --git a/tests/builder/possible_values.rs b/tests/builder/possible_values.rs index 4c128816f7c..062436e78f3 100644 --- a/tests/builder/possible_values.rs +++ b/tests/builder/possible_values.rs @@ -37,7 +37,7 @@ For more information try --help #[test] fn possible_values_of_positional() { let m = Command::new("possible_values") - .arg(Arg::new("positional").index(1).possible_value("test123")) + .arg(Arg::new("positional").index(1).value_parser(["test123"])) .try_get_matches_from(vec!["myprog", "test123"]); assert!(m.is_ok(), "{}", m.unwrap_err()); @@ -51,11 +51,11 @@ fn possible_values_of_positional() { fn possible_value_arg_value() { let m = Command::new("possible_values") .arg( - Arg::new("arg_value").index(1).possible_value( - PossibleValue::new("test123") + Arg::new("arg_value") + .index(1) + .value_parser([PossibleValue::new("test123") .hide(false) - .help("It's just a test"), - ), + .help("It's just a test")]), ) .try_get_matches_from(vec!["myprog", "test123"]); @@ -69,7 +69,7 @@ fn possible_value_arg_value() { #[test] fn possible_values_of_positional_fail() { let m = Command::new("possible_values") - .arg(Arg::new("positional").index(1).possible_value("test123")) + .arg(Arg::new("positional").index(1).value_parser(["test123"])) .try_get_matches_from(vec!["myprog", "notest"]); assert!(m.is_err()); @@ -83,8 +83,7 @@ fn possible_values_of_positional_multiple() { Arg::new("positional") .index(1) .takes_value(true) - .possible_value("test123") - .possible_value("test321") + .value_parser(["test123", "test321"]) .multiple_values(true), ) .try_get_matches_from(vec!["myprog", "test123", "test321"]); @@ -106,8 +105,7 @@ fn possible_values_of_positional_multiple_fail() { Arg::new("positional") .index(1) .takes_value(true) - .possible_value("test123") - .possible_value("test321") + .value_parser(["test123", "test321"]) .multiple_values(true), ) .try_get_matches_from(vec!["myprog", "test123", "notest"]); @@ -124,7 +122,7 @@ fn possible_values_of_option() { .short('o') .long("option") .takes_value(true) - .possible_value("test123"), + .value_parser(["test123"]), ) .try_get_matches_from(vec!["myprog", "--option", "test123"]); @@ -143,7 +141,7 @@ fn possible_values_of_option_fail() { .short('o') .long("option") .takes_value(true) - .possible_value("test123"), + .value_parser(["test123"]), ) .try_get_matches_from(vec!["myprog", "--option", "notest"]); @@ -159,8 +157,7 @@ fn possible_values_of_option_multiple() { .short('o') .long("option") .takes_value(true) - .possible_value("test123") - .possible_value("test321") + .value_parser(["test123", "test321"]) .multiple_occurrences(true), ) .try_get_matches_from(vec!["", "--option", "test123", "--option", "test321"]); @@ -183,8 +180,7 @@ fn possible_values_of_option_multiple_fail() { .short('o') .long("option") .takes_value(true) - .possible_value("test123") - .possible_value("test321") + .value_parser(["test123", "test321"]) .multiple_occurrences(true), ) .try_get_matches_from(vec!["", "--option", "test123", "--option", "notest"]); @@ -196,11 +192,12 @@ fn possible_values_of_option_multiple_fail() { #[test] fn possible_values_output() { utils::assert_output( - Command::new("test").arg(Arg::new("option").short('O').possible_values([ - "slow", - "fast", - "ludicrous speed", - ])), + Command::new("test").arg( + Arg::new("option") + .short('O') + .takes_value(true) + .value_parser(["slow", "fast", "ludicrous speed"]), + ), "clap-test -O slo", PV_ERROR, true, @@ -213,9 +210,12 @@ fn possible_values_alias_output() { Command::new("test").arg( Arg::new("option") .short('O') - .possible_value("slow") - .possible_value(PossibleValue::new("fast").alias("fost")) - .possible_value(PossibleValue::new("ludicrous speed").aliases(["ls", "lcs"])), + .takes_value(true) + .value_parser([ + "slow".into(), + PossibleValue::new("fast").alias("fost"), + PossibleValue::new("ludicrous speed").aliases(["ls", "lcs"]), + ]), ), "clap-test -O slo", PV_ERROR, @@ -229,9 +229,13 @@ fn possible_values_hidden_output() { Command::new("test").arg( Arg::new("option") .short('O') - .possible_values(["slow", "fast"]) - .possible_value(PossibleValue::new("ludicrous speed")) - .possible_value(PossibleValue::new("forbidden speed").hide(true)), + .takes_value(true) + .value_parser([ + "slow".into(), + "fast".into(), + PossibleValue::new("ludicrous speed"), + PossibleValue::new("forbidden speed").hide(true), + ]), ), "clap-test -O slo", PV_ERROR, @@ -242,11 +246,12 @@ fn possible_values_hidden_output() { #[test] fn escaped_possible_values_output() { utils::assert_output( - Command::new("test").arg(Arg::new("option").short('O').possible_values([ - "slow", - "fast", - "ludicrous speed", - ])), + Command::new("test").arg( + Arg::new("option") + .short('O') + .takes_value(true) + .value_parser(["slow", "fast", "ludicrous speed"]), + ), "clap-test -O ludicrous", PV_ERROR_ESCAPED, true, @@ -259,10 +264,13 @@ fn missing_possible_value_error() { Command::new("test").arg( Arg::new("option") .short('O') - .possible_value("slow") - .possible_value(PossibleValue::new("fast").alias("fost")) - .possible_value(PossibleValue::new("ludicrous speed")) - .possible_value(PossibleValue::new("forbidden speed").hide(true)), + .takes_value(true) + .value_parser([ + "slow".into(), + PossibleValue::new("fast").alias("fost"), + PossibleValue::new("ludicrous speed"), + PossibleValue::new("forbidden speed").hide(true), + ]), ), "clap-test -O", MISSING_PV_ERROR, @@ -285,8 +293,7 @@ fn alias() { .short('o') .long("option") .takes_value(true) - .possible_value(PossibleValue::new("test123").alias("123")) - .possible_value("test321") + .value_parser([PossibleValue::new("test123").alias("123"), "test321".into()]) .ignore_case(true), ) .try_get_matches_from(vec!["pv", "--option", "123"]); @@ -303,8 +310,10 @@ fn aliases() { .short('o') .long("option") .takes_value(true) - .possible_value(PossibleValue::new("test123").aliases(["1", "2", "3"])) - .possible_value("test321") + .value_parser([ + PossibleValue::new("test123").aliases(["1", "2", "3"]), + "test321".into(), + ]) .ignore_case(true), ) .try_get_matches_from(vec!["pv", "--option", "2"]); @@ -321,8 +330,7 @@ fn ignore_case() { .short('o') .long("option") .takes_value(true) - .possible_value("test123") - .possible_value("test321") + .value_parser(["test123", "test321"]) .ignore_case(true), ) .try_get_matches_from(vec!["pv", "--option", "TeSt123"]); @@ -343,8 +351,7 @@ fn ignore_case_fail() { .short('o') .long("option") .takes_value(true) - .possible_value("test123") - .possible_value("test321"), + .value_parser(["test123", "test321"]), ) .try_get_matches_from(vec!["pv", "--option", "TeSt123"]); @@ -360,8 +367,7 @@ fn ignore_case_multiple() { .short('o') .long("option") .takes_value(true) - .possible_value("test123") - .possible_value("test321") + .value_parser(["test123", "test321"]) .multiple_values(true) .ignore_case(true), ) @@ -382,8 +388,7 @@ fn ignore_case_multiple_fail() { .short('o') .long("option") .takes_value(true) - .possible_value("test123") - .possible_value("test321") + .value_parser(["test123", "test321"]) .multiple_values(true), ) .try_get_matches_from(vec!["pv", "--option", "test123", "teST123", "test321"]); diff --git a/tests/builder/require.rs b/tests/builder/require.rs index f10609df857..aadae20f1ce 100644 --- a/tests/builder/require.rs +++ b/tests/builder/require.rs @@ -758,7 +758,7 @@ fn list_correct_required_args() { Arg::new("target") .takes_value(true) .required(true) - .possible_values(["file", "stdout"]) + .value_parser(["file", "stdout"]) .long("target"), ) .arg( @@ -792,7 +792,7 @@ fn required_if_val_present_fail_error_output() { Arg::new("target") .takes_value(true) .required(true) - .possible_values(&["file", "stdout"]) + .value_parser(["file", "stdout"]) .long("target"), ) .arg( @@ -1122,7 +1122,7 @@ fn issue_2624() { .long("check") .require_equals(true) .min_values(0) - .possible_values(["silent", "quiet", "diagnose-first"]), + .value_parser(["silent", "quiet", "diagnose-first"]), ) .arg(Arg::new("unique").short('u').long("unique")) .try_get_matches_from(&["foo", "-cu"]) diff --git a/tests/builder/unicode.rs b/tests/builder/unicode.rs index dc97787b246..35c0ae054c4 100644 --- a/tests/builder/unicode.rs +++ b/tests/builder/unicode.rs @@ -8,7 +8,7 @@ fn possible_values_ignore_case() { .short('o') .long("option") .takes_value(true) - .possible_value("ä") + .value_parser(["ä"]) .ignore_case(true), ) .try_get_matches_from(vec!["pv", "--option", "Ä"]); diff --git a/tests/builder/utils.rs b/tests/builder/utils.rs index 4385f796cd6..16e738179cf 100644 --- a/tests/builder/utils.rs +++ b/tests/builder/utils.rs @@ -67,8 +67,8 @@ pub fn complex_app() -> Command<'static> { arg!([positional2] "tests positionals with exclusions"), arg!(-O --option3 "specific vals") .required(false) - .possible_values(opt3_vals), - arg!([positional3] ... "tests specific values").possible_values(pos3_vals), + .value_parser(opt3_vals), + arg!([positional3] ... "tests specific values").value_parser(pos3_vals), arg!(--multvals "Tests multiple values, not mult occs") .value_names(&["one", "two"]) .required(false), diff --git a/tests/derive/arg_enum.rs b/tests/derive/arg_enum.rs index 1cd8ee0d6b6..2c9ec78195d 100644 --- a/tests/derive/arg_enum.rs +++ b/tests/derive/arg_enum.rs @@ -19,7 +19,7 @@ fn basic() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum)] + #[clap(arg_enum, value_parser)] arg: ArgChoice, } @@ -54,7 +54,7 @@ fn default_value() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, default_value_t)] + #[clap(arg_enum, value_parser, default_value_t)] arg: ArgChoice, } @@ -89,7 +89,7 @@ fn multi_word_is_renamed_kebab() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum)] + #[clap(arg_enum, value_parser)] arg: ArgChoice, } @@ -118,7 +118,7 @@ fn variant_with_defined_casing() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum)] + #[clap(arg_enum, value_parser)] arg: ArgChoice, } @@ -141,7 +141,7 @@ fn casing_is_propagated_from_parent() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum)] + #[clap(arg_enum, value_parser)] arg: ArgChoice, } @@ -165,7 +165,7 @@ fn casing_propagation_is_overridden() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum)] + #[clap(arg_enum, value_parser)] arg: ArgChoice, } @@ -188,7 +188,7 @@ fn ignore_case() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, ignore_case(true))] + #[clap(arg_enum, value_parser, ignore_case(true))] arg: ArgChoice, } @@ -215,7 +215,7 @@ fn ignore_case_set_to_false() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, ignore_case(false))] + #[clap(arg_enum, ignore_case(false), value_parser)] arg: ArgChoice, } @@ -238,7 +238,7 @@ fn alias() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, ignore_case(false))] + #[clap(arg_enum, ignore_case(false), value_parser)] arg: ArgChoice, } @@ -266,7 +266,7 @@ fn multiple_alias() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, ignore_case(false))] + #[clap(arg_enum, ignore_case(false), value_parser)] arg: ArgChoice, } @@ -375,7 +375,7 @@ fn option_type() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum)] + #[clap(arg_enum, value_parser)] arg: Option, } @@ -405,7 +405,7 @@ fn option_option_type() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, long)] + #[clap(arg_enum, long, value_parser)] arg: Option>, } @@ -439,7 +439,7 @@ fn vec_type() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, short, long)] + #[clap(arg_enum, short, long, value_parser)] arg: Vec, } @@ -469,7 +469,7 @@ fn option_vec_type() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(arg_enum, short, long)] + #[clap(arg_enum, short, long, value_parser)] arg: Option>, } @@ -505,7 +505,8 @@ fn vec_type_default_value() { short, long, default_value = "foo,bar", - value_delimiter = ',' + value_delimiter = ',', + value_parser )] arg: Vec, } From a712adefcd83d279d99abb51af9540a0d040afc8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 24 May 2022 10:16:50 -0500 Subject: [PATCH 7/9] fix(parser): Deprecate `value_of` and friends --- clap_complete/examples/completion.rs | 4 +- src/derive.rs | 6 +- src/lib.rs | 1 + src/parser/matches/arg_matches.rs | 469 +++--------------------- src/parser/matches/mod.rs | 5 +- src/parser/mod.rs | 5 +- tests/builder/app_settings.rs | 234 +++++++++--- tests/builder/arg_aliases.rs | 38 +- tests/builder/arg_aliases_short.rs | 38 +- tests/builder/arg_matcher_assertions.rs | 6 +- tests/builder/conflicts.rs | 25 +- tests/builder/default_missing_vals.rs | 32 +- tests/builder/default_vals.rs | 168 +++++++-- tests/builder/delimiters.rs | 35 +- tests/builder/empty_values.rs | 6 +- tests/builder/env.rs | 76 +++- tests/builder/error.rs | 33 +- tests/builder/flags.rs | 10 +- tests/builder/global_args.rs | 8 +- tests/builder/grouped_values.rs | 10 +- tests/builder/groups.rs | 22 +- tests/builder/help.rs | 11 +- tests/builder/ignore_errors.rs | 21 +- tests/builder/multiple_occurrences.rs | 15 +- tests/builder/multiple_values.rs | 310 ++++++++++++---- tests/builder/opts.rs | 203 +++++++--- tests/builder/positionals.rs | 54 ++- tests/builder/posix_compatible.rs | 76 +++- tests/builder/possible_values.rs | 48 ++- tests/builder/propagate_globals.rs | 12 +- tests/builder/require.rs | 37 +- tests/builder/subcommands.rs | 39 +- tests/builder/tests.rs | 53 ++- tests/builder/unicode.rs | 6 +- tests/builder/utf8.rs | 30 +- tests/macros.rs | 6 +- 36 files changed, 1353 insertions(+), 799 deletions(-) diff --git a/clap_complete/examples/completion.rs b/clap_complete/examples/completion.rs index 14d803788bd..7fd5350b183 100644 --- a/clap_complete/examples/completion.rs +++ b/clap_complete/examples/completion.rs @@ -99,9 +99,9 @@ fn print_completions(gen: G, cmd: &mut Command) { fn main() { let matches = build_cli().get_matches(); - if let Ok(generator) = matches.value_of_t::("generator") { + if let Some(generator) = matches.get_one::("generator") { let mut cmd = build_cli(); eprintln!("Generating completion file for {}...", generator); - print_completions(generator, &mut cmd); + print_completions(*generator, &mut cmd); } } diff --git a/src/derive.rs b/src/derive.rs index 55be23bb13e..19d1e917ab7 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -70,7 +70,7 @@ use std::ffi::OsString; /// fn from(m: ArgMatches) -> Self { /// Context { /// verbose: m.is_present("verbose"), -/// name: m.value_of("name").map(|n| n.to_owned()), +/// name: m.get_one::("name").map(|n| n.clone()), /// } /// } /// } @@ -286,7 +286,7 @@ pub trait FromArgMatches: Sized { /// impl From for Context { /// fn from(m: ArgMatches) -> Self { /// Context { - /// name: m.value_of("name").unwrap().to_string(), + /// name: m.get_one::("name").unwrap().clone(), /// debug: m.is_present("debug"), /// } /// } @@ -320,7 +320,7 @@ pub trait FromArgMatches: Sized { /// impl From for Context { /// fn from(m: ArgMatches) -> Self { /// Context { - /// name: m.value_of("name").unwrap().to_string(), + /// name: m.get_one::("name").unwrap().to_string(), /// debug: m.is_present("debug"), /// } /// } diff --git a/src/lib.rs b/src/lib.rs index 18b1e2d34c0..435539b14a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ pub use crate::derive::{ArgEnum, Args, CommandFactory, FromArgMatches, Parser, S pub use crate::builder::App; pub use crate::builder::{AppFlags, AppSettings, ArgFlags, ArgSettings, PossibleValue, ValueHint}; pub use crate::error::{ErrorKind, Result}; +#[allow(deprecated)] pub use crate::parser::{Indices, OsValues, ValueSource, Values}; #[cfg(feature = "yaml")] diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index c2aa45ba74a..f6d478e0346 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -44,16 +44,16 @@ use crate::INTERNAL_ERROR_MSG; /// .get_matches(); // builds the instance of ArgMatches /// /// // to get information about the "cfg" argument we created, such as the value supplied we use -/// // various ArgMatches methods, such as ArgMatches::value_of -/// if let Some(c) = matches.value_of("cfg") { +/// // various ArgMatches methods, such as [ArgMatches::get_one] +/// if let Some(c) = matches.get_one::("cfg") { /// println!("Value for -c: {}", c); /// } /// -/// // The ArgMatches::value_of method returns an Option because the user may not have supplied +/// // The ArgMatches::get_one method returns an Option because the user may not have supplied /// // that argument at runtime. But if we specified that the argument was "required" as we did /// // with the "out" argument, we can safely unwrap because `clap` verifies that was actually /// // used at runtime. -/// println!("Value for --output: {}", matches.value_of("out").unwrap()); +/// println!("Value for --output: {}", matches.get_one::("out").unwrap()); /// /// // You can check the presence of an argument /// if matches.is_present("out") { @@ -117,7 +117,6 @@ impl ArgMatches { /// ``` /// [option]: crate::Arg::takes_value() /// [positional]: crate::Arg::index() - /// [`ArgMatches::values_of`]: ArgMatches::values_of() /// [`default_value`]: crate::Arg::default_value() /// [`occurrences_of`]: crate::ArgMatches::occurrences_of() #[track_caller] @@ -248,7 +247,6 @@ impl ArgMatches { /// ``` /// [option]: crate::Arg::takes_value() /// [positional]: crate::Arg::index() - /// [`ArgMatches::values_of`]: ArgMatches::values_of() /// [`default_value`]: crate::Arg::default_value() /// [`occurrences_of`]: crate::ArgMatches::occurrences_of() #[track_caller] @@ -319,42 +317,8 @@ impl ArgMatches { !self.args.is_empty() } - /// Gets the value of a specific option or positional argument. - /// - /// i.e. an argument that [takes an additional value][crate::Arg::takes_value] at runtime. - /// - /// Returns `None` if the option wasn't present. - /// - /// *NOTE:* Prefer [`ArgMatches::values_of`] if getting a value for an option or positional - /// argument that allows multiples as `ArgMatches::value_of` will only return the *first* - /// value. - /// - /// *NOTE:* This will always return `Some(value)` if [`default_value`] has been set. - /// [`occurrences_of`] can be used to check if a value is present at runtime. - /// - /// # Panics - /// - /// If the value is invalid UTF-8. See - /// [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{Command, Arg}; - /// let m = Command::new("myapp") - /// .arg(Arg::new("output") - /// .takes_value(true)) - /// .get_matches_from(vec!["myapp", "something"]); - /// - /// assert_eq!(m.value_of("output"), Some("something")); - /// ``` - /// [option]: crate::Arg::takes_value() - /// [positional]: crate::Arg::index() - /// [`ArgMatches::values_of`]: ArgMatches::values_of() - /// [`default_value`]: crate::Arg::default_value() - /// [`occurrences_of`]: crate::ArgMatches::occurrences_of() + /// Deprecated, replaced with [`ArgMatches::get_one()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")] #[cfg_attr(debug_assertions, track_caller)] pub fn value_of(&self, id: T) -> Option<&str> { let id = Id::from(id); @@ -363,47 +327,8 @@ impl ArgMatches { Some(v) } - /// Gets the lossy value of a specific option or positional argument. - /// - /// i.e. an argument that [takes an additional value][crate::Arg::takes_value] at runtime. - /// - /// A lossy value is one which contains invalid UTF-8, those invalid points will be replaced - /// with `\u{FFFD}` - /// - /// Returns `None` if the option wasn't present. - /// - /// *NOTE:* Recommend having set [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// *NOTE:* Prefer [`ArgMatches::values_of_lossy`] if getting a value for an option or positional - /// argument that allows multiples as `ArgMatches::value_of_lossy` will only return the *first* - /// value. - /// - /// *NOTE:* This will always return `Some(value)` if [`default_value`] has been set. - /// [`occurrences_of`] can be used to check if a value is present at runtime. - /// - /// # Panics - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```")] - /// # use clap::{Command, arg}; - /// use std::ffi::OsString; - /// use std::os::unix::ffi::{OsStrExt,OsStringExt}; - /// - /// let m = Command::new("utf8") - /// .arg(arg!( "some arg") - /// .allow_invalid_utf8(true)) - /// .get_matches_from(vec![OsString::from("myprog"), - /// // "Hi {0xe9}!" - /// OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]); - /// assert_eq!(&*m.value_of_lossy("arg").unwrap(), "Hi \u{FFFD}!"); - /// ``` - /// [`default_value`]: crate::Arg::default_value() - /// [`occurrences_of`]: ArgMatches::occurrences_of() - /// [`Arg::values_of_lossy`]: ArgMatches::values_of_lossy() + /// Deprecated, replaced with [`ArgMatches::get_one()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")] #[cfg_attr(debug_assertions, track_caller)] pub fn value_of_lossy(&self, id: T) -> Option> { let id = Id::from(id); @@ -412,48 +337,8 @@ impl ArgMatches { Some(v.to_string_lossy()) } - /// Get the `OsStr` value of a specific option or positional argument. - /// - /// i.e. an argument that [takes an additional value][crate::Arg::takes_value] at runtime. - /// - /// An `OsStr` on Unix-like systems is any series of bytes, regardless of whether or not they - /// contain valid UTF-8. Since [`String`]s in Rust are guaranteed to be valid UTF-8, a valid - /// filename on a Unix system as an argument value may contain invalid UTF-8. - /// - /// Returns `None` if the option wasn't present. - /// - /// *NOTE:* Recommend having set [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// *NOTE:* Prefer [`ArgMatches::values_of_os`] if getting a value for an option or positional - /// argument that allows multiples as `ArgMatches::value_of_os` will only return the *first* - /// value. - /// - /// *NOTE:* This will always return `Some(value)` if [`default_value`] has been set. - /// [`occurrences_of`] can be used to check if a value is present at runtime. - /// - /// # Panics - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```")] - /// # use clap::{Command, arg}; - /// use std::ffi::OsString; - /// use std::os::unix::ffi::{OsStrExt,OsStringExt}; - /// - /// let m = Command::new("utf8") - /// .arg(arg!( "some arg") - /// .allow_invalid_utf8(true)) - /// .get_matches_from(vec![OsString::from("myprog"), - /// // "Hi {0xe9}!" - /// OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]); - /// assert_eq!(&*m.value_of_os("arg").unwrap().as_bytes(), [b'H', b'i', b' ', 0xe9, b'!']); - /// ``` - /// [`default_value`]: crate::Arg::default_value() - /// [`occurrences_of`]: ArgMatches::occurrences_of() - /// [`ArgMatches::values_of_os`]: ArgMatches::values_of_os() + /// Deprecated, replaced with [`ArgMatches::get_one()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")] #[cfg_attr(debug_assertions, track_caller)] pub fn value_of_os(&self, id: T) -> Option<&OsStr> { let id = Id::from(id); @@ -462,38 +347,11 @@ impl ArgMatches { Some(v) } - /// Get an [`Iterator`] over [values] of a specific option or positional argument. - /// - /// i.e. an argument that takes multiple values at runtime. - /// - /// Returns `None` if the option wasn't present. - /// - /// # Panics - /// - /// If the value is invalid UTF-8. See - /// [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - /// ```rust - /// # use clap::{Command, Arg}; - /// let m = Command::new("myprog") - /// .arg(Arg::new("output") - /// .multiple_occurrences(true) - /// .short('o') - /// .takes_value(true)) - /// .get_matches_from(vec![ - /// "myprog", "-o", "val1", "-o", "val2", "-o", "val3" - /// ]); - /// let vals: Vec<&str> = m.values_of("output").unwrap().collect(); - /// assert_eq!(vals, ["val1", "val2", "val3"]); - /// ``` - /// [values]: Values - /// [`Iterator`]: std::iter::Iterator + /// Deprecated, replaced with [`ArgMatches::get_many()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")] #[cfg_attr(debug_assertions, track_caller)] pub fn values_of(&self, id: T) -> Option { + #![allow(deprecated)] let id = Id::from(id); let arg = self.get_arg(&id)?; let v = Values { @@ -548,42 +406,8 @@ impl ArgMatches { Some(v) } - /// Get the lossy values of a specific option or positional argument. - /// - /// i.e. an argument that takes multiple values at runtime. - /// - /// A lossy value is one which contains invalid UTF-8, those invalid points will be replaced - /// with `\u{FFFD}` - /// - /// Returns `None` if the option wasn't present. - /// - /// *NOTE:* Recommend having set [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// # Panics - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```")] - /// # use clap::{Command, arg}; - /// use std::ffi::OsString; - /// use std::os::unix::ffi::OsStringExt; - /// - /// let m = Command::new("utf8") - /// .arg(arg!( ... "some arg") - /// .allow_invalid_utf8(true)) - /// .get_matches_from(vec![OsString::from("myprog"), - /// // "Hi" - /// OsString::from_vec(vec![b'H', b'i']), - /// // "{0xe9}!" - /// OsString::from_vec(vec![0xe9, b'!'])]); - /// let mut itr = m.values_of_lossy("arg").unwrap().into_iter(); - /// assert_eq!(&itr.next().unwrap()[..], "Hi"); - /// assert_eq!(&itr.next().unwrap()[..], "\u{FFFD}!"); - /// assert_eq!(itr.next(), None); - /// ``` + /// Deprecated, replaced with [`ArgMatches::get_many()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")] #[cfg_attr(debug_assertions, track_caller)] pub fn values_of_lossy(&self, id: T) -> Option> { let id = Id::from(id); @@ -595,50 +419,11 @@ impl ArgMatches { Some(v) } - /// Get an [`Iterator`] over [`OsStr`] [values] of a specific option or positional argument. - /// - /// i.e. an argument that takes multiple values at runtime. - /// - /// An `OsStr` on Unix-like systems is any series of bytes, regardless of whether or not they - /// contain valid UTF-8. Since [`String`]s in Rust are guaranteed to be valid UTF-8, a valid - /// filename on a Unix system as an argument value may contain invalid UTF-8. - /// - /// Returns `None` if the option wasn't present. - /// - /// *NOTE:* Recommend having set [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// # Panics - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```")] - /// # use clap::{Command, arg}; - /// use std::ffi::{OsStr,OsString}; - /// use std::os::unix::ffi::{OsStrExt,OsStringExt}; - /// - /// let m = Command::new("utf8") - /// .arg(arg!( ... "some arg") - /// .allow_invalid_utf8(true)) - /// .get_matches_from(vec![OsString::from("myprog"), - /// // "Hi" - /// OsString::from_vec(vec![b'H', b'i']), - /// // "{0xe9}!" - /// OsString::from_vec(vec![0xe9, b'!'])]); - /// - /// let mut itr = m.values_of_os("arg").unwrap().into_iter(); - /// assert_eq!(itr.next(), Some(OsStr::new("Hi"))); - /// assert_eq!(itr.next(), Some(OsStr::from_bytes(&[0xe9, b'!']))); - /// assert_eq!(itr.next(), None); - /// ``` - /// [`Iterator`]: std::iter::Iterator - /// [`OsSt`]: std::ffi::OsStr - /// [values]: OsValues - /// [`String`]: std::string::String + /// Deprecated, replaced with [`ArgMatches::get_many()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")] #[cfg_attr(debug_assertions, track_caller)] pub fn values_of_os(&self, id: T) -> Option { + #![allow(deprecated)] let id = Id::from(id); let arg = self.get_arg(&id)?; let v = OsValues { @@ -648,48 +433,14 @@ impl ArgMatches { Some(v) } - /// Parse the value (with [`FromStr`]) of a specific option or positional argument. - /// - /// There are two types of errors, parse failures and those where the argument wasn't present - /// (such as a non-required argument). Check [`ErrorKind`] to distinguish them. - /// - /// *NOTE:* If getting a value for an option or positional argument that allows multiples, - /// prefer [`ArgMatches::values_of_t`] as this method will only return the *first* - /// value. - /// - /// # Panics - /// - /// If the value is invalid UTF-8. See - /// [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - /// ``` - /// # use clap::{Command, arg}; - /// let matches = Command::new("myapp") - /// .arg(arg!([length] "Set the length to use as a pos whole num i.e. 20")) - /// .get_matches_from(&["test", "12"]); - /// - /// // Specify the type explicitly (or use turbofish) - /// let len: u32 = matches.value_of_t("length").unwrap_or_else(|e| e.exit()); - /// assert_eq!(len, 12); - /// - /// // You can often leave the type for rustc to figure out - /// let also_len = matches.value_of_t("length").unwrap_or_else(|e| e.exit()); - /// // Something that expects u32 - /// let _: u32 = also_len; - /// ``` - /// - /// [`FromStr]: std::str::FromStr - /// [`ArgMatches::values_of_t`]: ArgMatches::values_of_t() - /// [`ErrorKind`]: crate::ErrorKind + /// Deprecated, replaced with [`ArgMatches::get_one()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")] pub fn value_of_t(&self, name: &str) -> Result where R: FromStr, ::Err: Display, { + #![allow(deprecated)] let v = self .value_of(name) .ok_or_else(|| Error::argument_not_found_auto(name.to_string()))?; @@ -703,83 +454,25 @@ impl ArgMatches { }) } - /// Parse the value (with [`FromStr`]) of a specific option or positional argument. - /// - /// If either the value is not present or parsing failed, exits the program. - /// - /// # Panics - /// - /// If the value is invalid UTF-8. See - /// [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - /// ``` - /// # use clap::{Command, arg}; - /// let matches = Command::new("myapp") - /// .arg(arg!([length] "Set the length to use as a pos whole num i.e. 20")) - /// .get_matches_from(&["test", "12"]); - /// - /// // Specify the type explicitly (or use turbofish) - /// let len: u32 = matches.value_of_t_or_exit("length"); - /// assert_eq!(len, 12); - /// - /// // You can often leave the type for rustc to figure out - /// let also_len = matches.value_of_t_or_exit("length"); - /// // Something that expects u32 - /// let _: u32 = also_len; - /// ``` - /// - /// [`FromStr][std::str::FromStr] + /// Deprecated, replaced with [`ArgMatches::get_one()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_one()`")] pub fn value_of_t_or_exit(&self, name: &str) -> R where R: FromStr, ::Err: Display, { + #![allow(deprecated)] self.value_of_t(name).unwrap_or_else(|e| e.exit()) } - /// Parse the values (with [`FromStr`]) of a specific option or positional argument. - /// - /// There are two types of errors, parse failures and those where the argument wasn't present - /// (such as a non-required argument). Check [`ErrorKind`] to distinguish them. - /// - /// *NOTE:* If getting a value for an option or positional argument that allows multiples, - /// prefer [`ArgMatches::values_of_t`] as this method will only return the *first* - /// value. - /// - /// # Panics - /// - /// If the value is invalid UTF-8. See - /// [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - /// ``` - /// # use clap::{Command, arg}; - /// let matches = Command::new("myapp") - /// .arg(arg!([length] ... "A sequence of integers because integers are neat!")) - /// .get_matches_from(&["test", "12", "77", "40"]); - /// - /// // Specify the type explicitly (or use turbofish) - /// let len: Vec = matches.values_of_t("length").unwrap_or_else(|e| e.exit()); - /// assert_eq!(len, vec![12, 77, 40]); - /// - /// // You can often leave the type for rustc to figure out - /// let also_len = matches.values_of_t("length").unwrap_or_else(|e| e.exit()); - /// // Something that expects Vec - /// let _: Vec = also_len; - /// ``` - /// [`ErrorKind`]: crate::ErrorKind + /// Deprecated, replaced with [`ArgMatches::get_many()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")] pub fn values_of_t(&self, name: &str) -> Result, Error> where R: FromStr, ::Err: Display, { + #![allow(deprecated)] let v = self .values_of(name) .ok_or_else(|| Error::argument_not_found_auto(name.to_string()))?; @@ -793,39 +486,14 @@ impl ArgMatches { .collect() } - /// Parse the values (with [`FromStr`]) of a specific option or positional argument. - /// - /// If parsing (of any value) has failed, exits the program. - /// - /// # Panics - /// - /// If the value is invalid UTF-8. See - /// [`Arg::allow_invalid_utf8`][crate::Arg::allow_invalid_utf8]. - /// - /// If `id` is is not a valid argument or group name. - /// - /// # Examples - /// - /// ``` - /// # use clap::{Command, arg}; - /// let matches = Command::new("myapp") - /// .arg(arg!([length] ... "A sequence of integers because integers are neat!")) - /// .get_matches_from(&["test", "12", "77", "40"]); - /// - /// // Specify the type explicitly (or use turbofish) - /// let len: Vec = matches.values_of_t_or_exit("length"); - /// assert_eq!(len, vec![12, 77, 40]); - /// - /// // You can often leave the type for rustc to figure out - /// let also_len = matches.values_of_t_or_exit("length"); - /// // Something that expects Vec - /// let _: Vec = also_len; - /// ``` + /// Deprecated, replaced with [`ArgMatches::get_many()`] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")] pub fn values_of_t_or_exit(&self, name: &str) -> Vec where R: FromStr, ::Err: Display, { + #![allow(deprecated)] self.values_of_t(name).unwrap_or_else(|e| e.exit()) } @@ -1230,7 +898,8 @@ impl ArgMatches { /// // string argument name /// match app_m.subcommand() { /// Some((external, sub_m)) => { - /// let ext_args: Vec<&str> = sub_m.values_of("").unwrap().collect(); + /// let ext_args: Vec<&str> = sub_m.get_many::("") + /// .unwrap().map(|s| s.as_str()).collect(); /// assert_eq!(external, "subcmd"); /// assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]); /// }, @@ -1331,7 +1000,7 @@ impl ArgMatches { /// // Get the subcommand's ArgMatches instance /// if let Some(sub_m) = app_m.subcommand_matches("test") { /// // Use the struct like normal - /// assert_eq!(sub_m.value_of("opt"), Some("val")); + /// assert_eq!(sub_m.get_one::("opt").map(|s| s.as_str()), Some("val")); /// } /// ``` /// @@ -1807,26 +1476,8 @@ impl Default for RawValues<'_> { // commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33 // license: MIT - Copyright (c) 2015 The Rust Project Developers -/// Iterate over multiple values for an argument via [`ArgMatches::values_of`]. -/// -/// # Examples -/// -/// ```rust -/// # use clap::{Command, Arg}; -/// let m = Command::new("myapp") -/// .arg(Arg::new("output") -/// .short('o') -/// .multiple_occurrences(true) -/// .takes_value(true)) -/// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]); -/// -/// let mut values = m.values_of("output").unwrap(); -/// -/// assert_eq!(values.next(), Some("val1")); -/// assert_eq!(values.next(), Some("val2")); -/// assert_eq!(values.next(), None); -/// ``` -/// [`ArgMatches::values_of`]: ArgMatches::values_of() +/// Deprecated, replaced with [`ArgMatches::get_many()`] +#[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")] #[derive(Clone, Debug)] pub struct Values<'a> { #[allow(clippy::type_complexity)] @@ -1834,6 +1485,7 @@ pub struct Values<'a> { len: usize, } +#[allow(deprecated)] impl<'a> Iterator for Values<'a> { type Item = &'a str; @@ -1845,15 +1497,18 @@ impl<'a> Iterator for Values<'a> { } } +#[allow(deprecated)] impl<'a> DoubleEndedIterator for Values<'a> { fn next_back(&mut self) -> Option<&'a str> { self.iter.next_back() } } +#[allow(deprecated)] impl<'a> ExactSizeIterator for Values<'a> {} /// Creates an empty iterator. +#[allow(deprecated)] impl<'a> Default for Values<'a> { fn default() -> Self { static EMPTY: [Vec; 0] = []; @@ -1894,6 +1549,7 @@ impl<'a> ExactSizeIterator for GroupedValues<'a> {} /// Creates an empty iterator. Used for `unwrap_or_default()`. impl<'a> Default for GroupedValues<'a> { fn default() -> Self { + #![allow(deprecated)] static EMPTY: [Vec; 0] = []; GroupedValues { iter: EMPTY[..].iter().map(|_| unreachable!()), @@ -1902,25 +1558,8 @@ impl<'a> Default for GroupedValues<'a> { } } -/// Iterate over multiple values for an argument via [`ArgMatches::values_of_os`]. -/// -/// # Examples -/// -#[cfg_attr(not(unix), doc = " ```ignore")] -#[cfg_attr(unix, doc = " ```")] -/// # use clap::{Command, arg}; -/// use std::ffi::OsString; -/// use std::os::unix::ffi::{OsStrExt,OsStringExt}; -/// -/// let m = Command::new("utf8") -/// .arg(arg!( "some arg") -/// .allow_invalid_utf8(true)) -/// .get_matches_from(vec![OsString::from("myprog"), -/// // "Hi {0xe9}!" -/// OsString::from_vec(vec![b'H', b'i', b' ', 0xe9, b'!'])]); -/// assert_eq!(&*m.value_of_os("arg").unwrap().as_bytes(), [b'H', b'i', b' ', 0xe9, b'!']); -/// ``` -/// [`ArgMatches::values_of_os`]: ArgMatches::values_of_os() +/// Deprecated, replaced with [`ArgMatches::get_many()`] +#[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::get_many()`")] #[derive(Clone, Debug)] pub struct OsValues<'a> { #[allow(clippy::type_complexity)] @@ -1928,6 +1567,7 @@ pub struct OsValues<'a> { len: usize, } +#[allow(deprecated)] impl<'a> Iterator for OsValues<'a> { type Item = &'a OsStr; @@ -1939,15 +1579,18 @@ impl<'a> Iterator for OsValues<'a> { } } +#[allow(deprecated)] impl<'a> DoubleEndedIterator for OsValues<'a> { fn next_back(&mut self) -> Option<&'a OsStr> { self.iter.next_back() } } +#[allow(deprecated)] impl<'a> ExactSizeIterator for OsValues<'a> {} /// Creates an empty iterator. +#[allow(deprecated)] impl Default for OsValues<'_> { fn default() -> Self { static EMPTY: [Vec; 0] = []; @@ -2071,19 +1714,14 @@ mod tests { #[test] fn test_default_values() { + #![allow(deprecated)] let mut values: Values = Values::default(); assert_eq!(values.next(), None); } - #[test] - fn test_default_values_with_shorter_lifetime() { - let matches = ArgMatches::default(); - let mut values = matches.values_of("").unwrap_or_default(); - assert_eq!(values.next(), None); - } - #[test] fn test_default_osvalues() { + #![allow(deprecated)] let mut values: OsValues = OsValues::default(); assert_eq!(values.next(), None); } @@ -2094,13 +1732,6 @@ mod tests { assert_eq!(values.next(), None); } - #[test] - fn test_default_osvalues_with_shorter_lifetime() { - let matches = ArgMatches::default(); - let mut values = matches.values_of_os("").unwrap_or_default(); - assert_eq!(values.next(), None); - } - #[test] fn test_default_indices() { let mut indices: Indices = Indices::default(); @@ -2125,9 +1756,9 @@ mod tests { ) .try_get_matches_from(["test", "one"]) .unwrap() - .values_of("POTATO") + .get_many::("POTATO") .expect("present") - .len(); + .count(); assert_eq!(l, 1); } diff --git a/src/parser/matches/mod.rs b/src/parser/matches/mod.rs index 9fd7d50cafe..d99ea20ac2a 100644 --- a/src/parser/matches/mod.rs +++ b/src/parser/matches/mod.rs @@ -5,10 +5,13 @@ mod value_source; pub use arg_matches::RawValues; pub use arg_matches::ValuesRef; -pub use arg_matches::{ArgMatches, Indices, OsValues, Values}; +pub use arg_matches::{ArgMatches, Indices}; pub use value_source::ValueSource; pub(crate) use any_value::AnyValue; pub(crate) use any_value::AnyValueId; pub(crate) use arg_matches::SubCommand; pub(crate) use matched_arg::MatchedArg; + +#[allow(deprecated)] +pub use arg_matches::{OsValues, Values}; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 8dd1f276159..e53f9ecfde3 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -18,5 +18,8 @@ pub(crate) use self::validator::Validator; pub use self::matches::RawValues; pub use self::matches::ValuesRef; -pub use self::matches::{ArgMatches, Indices, OsValues, ValueSource, Values}; +pub use self::matches::{ArgMatches, Indices, ValueSource}; pub use error::MatchesError; + +#[allow(deprecated)] +pub use self::matches::{OsValues, Values}; diff --git a/tests/builder/app_settings.rs b/tests/builder/app_settings.rs index 46f584ae642..bc4d53271f1 100644 --- a/tests/builder/app_settings.rs +++ b/tests/builder/app_settings.rs @@ -1,3 +1,5 @@ +use std::ffi::OsString; + use crate::utils; use clap::{arg, error::ErrorKind, AppSettings, Arg, Command}; @@ -322,7 +324,10 @@ fn infer_subcommands_fail_with_args() { .subcommand(Command::new("temp")) .try_get_matches_from(vec!["prog", "t"]); assert!(m.is_ok(), "{:?}", m.unwrap_err().kind()); - assert_eq!(m.unwrap().value_of("some"), Some("t")); + assert_eq!( + m.unwrap().get_one::("some").map(|v| v.as_str()), + Some("t") + ); } #[test] @@ -334,7 +339,10 @@ fn infer_subcommands_fail_with_args2() { .subcommand(Command::new("temp")) .try_get_matches_from(vec!["prog", "te"]); assert!(m.is_ok(), "{:?}", m.unwrap_err().kind()); - assert_eq!(m.unwrap().value_of("some"), Some("te")); + assert_eq!( + m.unwrap().get_one::("some").map(|v| v.as_str()), + Some("te") + ); } #[test] @@ -402,7 +410,13 @@ fn no_bin_name() { .try_get_matches_from(vec!["testing"]); assert!(result.is_ok(), "{}", result.unwrap_err()); let matches = result.unwrap(); - assert_eq!(matches.value_of("test").unwrap(), "testing"); + assert_eq!( + matches + .get_one::("test") + .map(|v| v.as_str()) + .unwrap(), + "testing" + ); } #[test] @@ -436,7 +450,10 @@ fn stop_delim_values_only_pos_follows() { assert!(m.is_present("arg")); assert!(!m.is_present("f")); assert_eq!( - m.values_of("arg").unwrap().collect::>(), + m.get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["-f", "-g,x"] ); } @@ -451,7 +468,10 @@ fn dont_delim_values_trailingvararg() { .unwrap(); assert!(m.is_present("opt")); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["test", "--foo", "-Wl,-bar"] ); } @@ -466,7 +486,10 @@ fn delim_values_only_pos_follows() { assert!(m.is_present("arg")); assert!(!m.is_present("f")); assert_eq!( - m.values_of("arg").unwrap().collect::>(), + m.get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["-f", "-g,x"] ); } @@ -480,7 +503,10 @@ fn delim_values_trailingvararg() { .unwrap(); assert!(m.is_present("opt")); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["test", "--foo", "-Wl,-bar"] ); } @@ -498,7 +524,10 @@ fn delim_values_only_pos_follows_with_delim() { assert!(m.is_present("arg")); assert!(!m.is_present("f")); assert_eq!( - m.values_of("arg").unwrap().collect::>(), + m.get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["-f", "-g", "x"] ); } @@ -512,7 +541,10 @@ fn delim_values_trailingvararg_with_delim() { .unwrap(); assert!(m.is_present("opt")); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["test", "--foo", "-Wl", "-bar"] ); } @@ -528,7 +560,10 @@ fn leading_hyphen_short() { let m = res.unwrap(); assert!(m.is_present("some")); assert!(m.is_present("other")); - assert_eq!(m.value_of("some").unwrap(), "-bar"); + assert_eq!( + m.get_one::("some").map(|v| v.as_str()).unwrap(), + "-bar" + ); } #[test] @@ -542,7 +577,10 @@ fn leading_hyphen_long() { let m = res.unwrap(); assert!(m.is_present("some")); assert!(m.is_present("other")); - assert_eq!(m.value_of("some").unwrap(), "--bar"); + assert_eq!( + m.get_one::("some").map(|v| v.as_str()).unwrap(), + "--bar" + ); } #[test] @@ -556,7 +594,10 @@ fn leading_hyphen_opt() { let m = res.unwrap(); assert!(m.is_present("some")); assert!(m.is_present("other")); - assert_eq!(m.value_of("some").unwrap(), "--bar"); + assert_eq!( + m.get_one::("some").map(|v| v.as_str()).unwrap(), + "--bar" + ); } #[test] @@ -568,8 +609,14 @@ fn allow_negative_numbers() { .try_get_matches_from(vec!["negnum", "-20", "-o", "-1.2"]); assert!(res.is_ok(), "Error: {:?}", res.unwrap_err().kind()); let m = res.unwrap(); - assert_eq!(m.value_of("panum").unwrap(), "-20"); - assert_eq!(m.value_of("onum").unwrap(), "-1.2"); + assert_eq!( + m.get_one::("panum").map(|v| v.as_str()).unwrap(), + "-20" + ); + assert_eq!( + m.get_one::("onum").map(|v| v.as_str()).unwrap(), + "-1.2" + ); } #[test] @@ -593,7 +640,10 @@ fn leading_double_hyphen_trailingvararg() { .unwrap(); assert!(m.is_present("opt")); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["--foo", "-Wl", "bar"] ); } @@ -649,7 +699,10 @@ fn args_negate_subcommands_one_level() { .try_get_matches_from(vec!["", "pickles", "sub1"]); assert!(res.is_ok(), "error: {:?}", res.unwrap_err().kind()); let m = res.unwrap(); - assert_eq!(m.value_of("arg2"), Some("sub1")); + assert_eq!( + m.get_one::("arg2").map(|v| v.as_str()), + Some("sub1") + ); } #[test] @@ -671,7 +724,10 @@ fn args_negate_subcommands_two_levels() { assert!(res.is_ok(), "error: {:?}", res.unwrap_err().kind()); let m = res.unwrap(); assert_eq!( - m.subcommand_matches("sub1").unwrap().value_of("arg2"), + m.subcommand_matches("sub1") + .unwrap() + .get_one::("arg2") + .map(|v| v.as_str()), Some("sub2") ); } @@ -684,9 +740,12 @@ fn propagate_vals_down() { .try_get_matches_from(vec!["myprog", "set", "foo"]); assert!(m.is_ok(), "{:?}", m.unwrap_err().kind()); let m = m.unwrap(); - assert_eq!(m.value_of("cmd"), Some("set")); + assert_eq!(m.get_one::("cmd").map(|v| v.as_str()), Some("set")); let sub_m = m.subcommand_matches("foo").unwrap(); - assert_eq!(sub_m.value_of("cmd"), Some("set")); + assert_eq!( + sub_m.get_one::("cmd").map(|v| v.as_str()), + Some("set") + ); } #[test] @@ -698,8 +757,11 @@ fn allow_missing_positional() { .try_get_matches_from(vec!["test", "file"]); assert!(m.is_ok(), "{:?}", m.unwrap_err().kind()); let m = m.unwrap(); - assert_eq!(m.value_of("src"), Some("src")); - assert_eq!(m.value_of("dest"), Some("file")); + assert_eq!(m.get_one::("src").map(|v| v.as_str()), Some("src")); + assert_eq!( + m.get_one::("dest").map(|v| v.as_str()), + Some("file") + ); } #[test] @@ -711,8 +773,11 @@ fn allow_missing_positional_no_default() { .try_get_matches_from(vec!["test", "file"]); assert!(m.is_ok(), "{:?}", m.unwrap_err().kind()); let m = m.unwrap(); - assert_eq!(m.value_of("src"), None); - assert_eq!(m.value_of("dest"), Some("file")); + assert_eq!(m.get_one::("src").map(|v| v.as_str()), None); + assert_eq!( + m.get_one::("dest").map(|v| v.as_str()), + Some("file") + ); } #[test] @@ -729,9 +794,15 @@ fn missing_positional_no_hyphen() { let expected_bench = Some("foo"); let expected_args = vec!["arg1", "arg2", "arg3"]; - assert_eq!(m.value_of("BENCH"), expected_bench); assert_eq!( - m.values_of("ARGS").unwrap().collect::>(), + m.get_one::("BENCH").map(|v| v.as_str()), + expected_bench + ); + assert_eq!( + m.get_many::("ARGS") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &*expected_args ); } @@ -750,9 +821,15 @@ fn missing_positional_hyphen() { let expected_bench = None; let expected_args = vec!["arg1", "arg2", "arg3"]; - assert_eq!(m.value_of("BENCH"), expected_bench); assert_eq!( - m.values_of("ARGS").unwrap().collect::>(), + m.get_one::("BENCH").map(|v| v.as_str()), + expected_bench + ); + assert_eq!( + m.get_many::("ARGS") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &*expected_args ); } @@ -775,11 +852,23 @@ fn missing_positional_hyphen_far_back() { let expected_bench3 = None; let expected_args = vec!["arg1", "arg2", "arg3"]; - assert_eq!(m.value_of("BENCH1"), expected_bench1); - assert_eq!(m.value_of("BENCH2"), expected_bench2); - assert_eq!(m.value_of("BENCH3"), expected_bench3); assert_eq!( - m.values_of("ARGS").unwrap().collect::>(), + m.get_one::("BENCH1").map(|v| v.as_str()), + expected_bench1 + ); + assert_eq!( + m.get_one::("BENCH2").map(|v| v.as_str()), + expected_bench2 + ); + assert_eq!( + m.get_one::("BENCH3").map(|v| v.as_str()), + expected_bench3 + ); + assert_eq!( + m.get_many::("ARGS") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &*expected_args ); } @@ -840,7 +929,10 @@ fn issue_1437_allow_hyphen_values_for_positional_arg() { ) .try_get_matches_from(["tmp", "-file"]) .unwrap(); - assert_eq!(m.value_of("pat"), Some("-file")); + assert_eq!( + m.get_one::("pat").map(|v| v.as_str()), + Some("-file") + ); } #[test] @@ -865,7 +957,7 @@ fn allow_ext_sc_empty_args() { match res.unwrap().subcommand() { Some((name, args)) => { assert_eq!(name, "external-cmd"); - assert_eq!(args.values_of_lossy(""), None); + assert!(args.get_many::("").is_none()); } _ => unreachable!(), } @@ -905,7 +997,13 @@ fn allow_ext_sc_when_sc_required() { match res.unwrap().subcommand() { Some((name, args)) => { assert_eq!(name, "external-cmd"); - assert_eq!(args.values_of_lossy(""), Some(vec!["foo".to_string()])); + assert_eq!( + args.get_many::("") + .unwrap() + .cloned() + .collect::>(), + vec![OsString::from("foo")] + ); } _ => unreachable!(), } @@ -924,7 +1022,13 @@ fn external_subcommand_looks_like_built_in() { match m.subcommand() { Some((name, args)) => { assert_eq!(name, "install-update"); - assert_eq!(args.values_of_lossy(""), Some(vec!["foo".to_string()])); + assert_eq!( + args.get_many::("") + .unwrap() + .cloned() + .collect::>(), + vec![OsString::from("foo")] + ); } _ => panic!("external_subcommand didn't work"), } @@ -943,7 +1047,13 @@ fn built_in_subcommand_escaped() { match m.subcommand() { Some((name, args)) => { assert_eq!(name, "install"); - assert_eq!(args.values_of_lossy(""), Some(vec!["foo".to_string()])); + assert_eq!( + args.get_many::("") + .unwrap() + .cloned() + .collect::>(), + vec![OsString::from("foo")] + ); } _ => panic!("external_subcommand didn't work"), } @@ -986,7 +1096,10 @@ fn aaos_opts() { let m = res.unwrap(); assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 1); - assert_eq!(m.value_of("opt"), Some("other")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("other") + ); } #[test] @@ -1006,7 +1119,10 @@ fn aaos_opts_w_other_overrides() { assert!(m.is_present("opt")); assert!(!m.is_present("other")); assert_eq!(m.occurrences_of("opt"), 1); - assert_eq!(m.value_of("opt"), Some("other")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("other") + ); } #[test] @@ -1025,7 +1141,10 @@ fn aaos_opts_w_other_overrides_rev() { let m = res.unwrap(); assert!(!m.is_present("opt")); assert!(m.is_present("other")); - assert_eq!(m.value_of("other"), Some("val")); + assert_eq!( + m.get_one::("other").map(|v| v.as_str()), + Some("val") + ); } #[test] @@ -1045,7 +1164,10 @@ fn aaos_opts_w_other_overrides_2() { assert!(m.is_present("opt")); assert!(!m.is_present("other")); assert_eq!(m.occurrences_of("opt"), 1); - assert_eq!(m.value_of("opt"), Some("other")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("other") + ); } #[test] @@ -1064,7 +1186,10 @@ fn aaos_opts_w_other_overrides_rev_2() { let m = res.unwrap(); assert!(!m.is_present("opt")); assert!(m.is_present("other")); - assert_eq!(m.value_of("other"), Some("val")); + assert_eq!( + m.get_one::("other").map(|v| v.as_str()), + Some("val") + ); } #[test] @@ -1083,7 +1208,7 @@ fn aaos_opts_w_override_as_conflict_1() { let m = res.unwrap(); assert!(m.is_present("opt")); assert!(!m.is_present("other")); - assert_eq!(m.value_of("opt"), Some("some")); + assert_eq!(m.get_one::("opt").map(|v| v.as_str()), Some("some")); } #[test] @@ -1102,7 +1227,10 @@ fn aaos_opts_w_override_as_conflict_2() { let m = res.unwrap(); assert!(!m.is_present("opt")); assert!(m.is_present("other")); - assert_eq!(m.value_of("other"), Some("some")); + assert_eq!( + m.get_one::("other").map(|v| v.as_str()), + Some("some") + ); } #[test] @@ -1123,7 +1251,10 @@ fn aaos_opts_mult() { assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 3); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["some", "other", "one", "two"] ); } @@ -1149,7 +1280,10 @@ fn aaos_opts_mult_req_delims() { assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 2); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["first", "overrides", "some", "other", "val"] ); } @@ -1166,7 +1300,10 @@ fn aaos_pos_mult() { assert!(m.is_present("val")); assert_eq!(m.occurrences_of("val"), 3); assert_eq!( - m.values_of("val").unwrap().collect::>(), + m.get_many::("val") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["some", "other", "value"] ); } @@ -1181,7 +1318,10 @@ fn aaos_option_use_delim_false() { assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 1); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["one,two"] ); } diff --git a/tests/builder/arg_aliases.rs b/tests/builder/arg_aliases.rs index e0df5825df4..71ccb18f89a 100644 --- a/tests/builder/arg_aliases.rs +++ b/tests/builder/arg_aliases.rs @@ -42,7 +42,10 @@ fn single_alias_of_option() { assert!(a.is_ok(), "{}", a.unwrap_err()); let a = a.unwrap(); assert!(a.is_present("alias")); - assert_eq!(a.value_of("alias").unwrap(), "cool"); + assert_eq!( + a.get_one::("alias").map(|v| v.as_str()).unwrap(), + "cool" + ); } #[test] @@ -82,10 +85,30 @@ fn multiple_aliases_of_option() { assert!(als1.is_present("aliases")); assert!(als2.is_present("aliases")); assert!(als3.is_present("aliases")); - assert_eq!(long.value_of("aliases").unwrap(), "value"); - assert_eq!(als1.value_of("aliases").unwrap(), "value"); - assert_eq!(als2.value_of("aliases").unwrap(), "value"); - assert_eq!(als3.value_of("aliases").unwrap(), "value"); + assert_eq!( + long.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); + assert_eq!( + als1.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); + assert_eq!( + als2.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); + assert_eq!( + als3.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); } #[test] @@ -150,7 +173,10 @@ fn alias_on_a_subcommand_option() { assert!(m.subcommand_matches("some").is_some()); let sub_m = m.subcommand_matches("some").unwrap(); assert!(sub_m.is_present("test")); - assert_eq!(sub_m.value_of("test").unwrap(), "awesome"); + assert_eq!( + sub_m.get_one::("test").map(|v| v.as_str()).unwrap(), + "awesome" + ); } #[test] diff --git a/tests/builder/arg_aliases_short.rs b/tests/builder/arg_aliases_short.rs index d939c49db73..6d70910a0d0 100644 --- a/tests/builder/arg_aliases_short.rs +++ b/tests/builder/arg_aliases_short.rs @@ -42,7 +42,10 @@ fn single_short_alias_of_option() { assert!(a.is_ok(), "{}", a.unwrap_err()); let a = a.unwrap(); assert!(a.is_present("alias")); - assert_eq!(a.value_of("alias").unwrap(), "cool"); + assert_eq!( + a.get_one::("alias").map(|v| v.as_str()).unwrap(), + "cool" + ); } #[test] @@ -76,10 +79,30 @@ fn multiple_short_aliases_of_option() { assert!(als1.is_present("aliases")); assert!(als2.is_present("aliases")); assert!(als3.is_present("aliases")); - assert_eq!(long.value_of("aliases").unwrap(), "value"); - assert_eq!(als1.value_of("aliases").unwrap(), "value"); - assert_eq!(als2.value_of("aliases").unwrap(), "value"); - assert_eq!(als3.value_of("aliases").unwrap(), "value"); + assert_eq!( + long.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); + assert_eq!( + als1.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); + assert_eq!( + als2.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); + assert_eq!( + als3.get_one::("aliases") + .map(|v| v.as_str()) + .unwrap(), + "value" + ); } #[test] @@ -146,7 +169,10 @@ fn short_alias_on_a_subcommand_option() { assert!(m.subcommand_matches("some").is_some()); let sub_m = m.subcommand_matches("some").unwrap(); assert!(sub_m.is_present("test")); - assert_eq!(sub_m.value_of("test").unwrap(), "awesome"); + assert_eq!( + sub_m.get_one::("test").map(|v| v.as_str()).unwrap(), + "awesome" + ); } #[test] diff --git a/tests/builder/arg_matcher_assertions.rs b/tests/builder/arg_matcher_assertions.rs index e2c2378e8f0..e54f735e80a 100644 --- a/tests/builder/arg_matcher_assertions.rs +++ b/tests/builder/arg_matcher_assertions.rs @@ -16,15 +16,15 @@ fn arg_matches_if_present_wrong_arg() { #[test] #[cfg(debug_assertions)] -#[should_panic = "`o` is not a name of an argument or a group."] +#[should_panic = "Mismatch between definition and access of `o`. Unknown argument or group id. Make sure you are using the argument id and not the short or long flags"] fn arg_matches_value_of_wrong_arg() { let m = Command::new("test") .arg(Arg::new("opt").short('o').takes_value(true)) .try_get_matches_from(&["test", "-o", "val"]) .unwrap(); - assert_eq!(m.value_of("opt"), Some("val")); - m.value_of("o"); + assert_eq!(m.get_one::("opt").map(|v| v.as_str()), Some("val")); + m.get_one::("o").map(|v| v.as_str()); } #[test] diff --git a/tests/builder/conflicts.rs b/tests/builder/conflicts.rs index bc244ab1c73..80d2d31f727 100644 --- a/tests/builder/conflicts.rs +++ b/tests/builder/conflicts.rs @@ -399,7 +399,10 @@ fn conflict_with_unused_default() { assert!(result.is_ok(), "{}", result.unwrap_err()); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(m.is_present("flag")); } @@ -422,7 +425,10 @@ fn conflicts_with_alongside_default() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(m.is_present("flag")); } @@ -445,7 +451,10 @@ fn group_in_conflicts_with() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(m.is_present("flag")); } @@ -468,7 +477,10 @@ fn group_conflicts_with_default_value() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(m.is_present("flag")); } @@ -487,7 +499,10 @@ fn group_conflicts_with_default_arg() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(m.is_present("flag")); } diff --git a/tests/builder/default_missing_vals.rs b/tests/builder/default_missing_vals.rs index 68d0a7db818..0700df6712f 100644 --- a/tests/builder/default_missing_vals.rs +++ b/tests/builder/default_missing_vals.rs @@ -15,7 +15,10 @@ fn opt_missing() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "auto"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "auto" + ); assert_eq!(m.occurrences_of("color"), 0); } @@ -34,7 +37,10 @@ fn opt_present_with_missing_value() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "always"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "always" + ); assert_eq!(m.occurrences_of("color"), 1); } @@ -53,7 +59,10 @@ fn opt_present_with_value() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "never"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "never" + ); assert_eq!(m.occurrences_of("color"), 1); } @@ -71,7 +80,10 @@ fn opt_present_with_empty_value() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), ""); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "" + ); assert_eq!(m.occurrences_of("color"), 1); } @@ -90,7 +102,10 @@ fn opt_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.value_of("o").unwrap(), "default"); + assert_eq!( + m.get_one::("o").map(|v| v.as_str()).unwrap(), + "default" + ); } #[test] @@ -106,7 +121,10 @@ fn opt_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.value_of("o").unwrap(), "value"); + assert_eq!( + m.get_one::("o").map(|v| v.as_str()).unwrap(), + "value" + ); } #[test] @@ -120,7 +138,7 @@ fn default_missing_value_flag_value() { ); fn flag_value(m: ArgMatches) -> bool { - match m.value_of("flag") { + match m.get_one::("flag").map(|v| v.as_str()) { None => false, Some(x) => x.parse().expect("non boolean value"), } diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index 30d3cea6006..678484737d0 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -13,7 +13,10 @@ fn opts() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.value_of("o").unwrap(), "default"); + assert_eq!( + m.get_one::("o").map(|v| v.as_str()).unwrap(), + "default" + ); } #[test] @@ -46,7 +49,10 @@ fn opt_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("opt")); - assert_eq!(m.value_of("opt").unwrap(), "value"); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()).unwrap(), + "value" + ); } #[test] @@ -57,7 +63,10 @@ fn positionals() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "default"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "default" + ); } #[test] @@ -68,7 +77,10 @@ fn positional_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "value"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "value" + ); } // OsStr Default Values @@ -88,7 +100,10 @@ fn osstr_opts() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.value_of("o").unwrap(), expected); + assert_eq!( + m.get_one::("o").map(|v| v.as_str()).unwrap(), + expected + ); } #[test] @@ -106,7 +121,10 @@ fn osstr_opt_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("opt")); - assert_eq!(m.value_of("opt").unwrap(), "value"); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()).unwrap(), + "value" + ); } #[test] @@ -120,7 +138,10 @@ fn osstr_positionals() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), expected); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + expected + ); } #[test] @@ -134,7 +155,10 @@ fn osstr_positional_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "value"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "value" + ); } // --- Default if arg is present @@ -148,7 +172,10 @@ fn default_if_arg_present_no_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "default"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "default" + ); } #[test] @@ -160,7 +187,10 @@ fn default_if_arg_present_no_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -176,7 +206,10 @@ fn default_if_arg_present_no_arg_with_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "first"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "first" + ); } #[test] @@ -192,7 +225,10 @@ fn default_if_arg_present_with_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "default"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "default" + ); } #[test] @@ -208,7 +244,10 @@ fn default_if_arg_present_with_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -224,7 +263,10 @@ fn default_if_arg_present_no_arg_with_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } // Conditional Default Values @@ -238,7 +280,10 @@ fn default_if_arg_present_with_value_no_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "default"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "default" + ); } #[test] @@ -250,7 +295,7 @@ fn default_if_arg_present_with_value_no_default_fail() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(!m.is_present("arg")); - assert!(m.value_of("arg").is_none()); + assert!(m.get_one::("arg").map(|v| v.as_str()).is_none()); } #[test] @@ -262,7 +307,10 @@ fn default_if_arg_present_with_value_no_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -278,7 +326,10 @@ fn default_if_arg_present_with_value_no_arg_with_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "first"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "first" + ); } #[test] @@ -294,7 +345,10 @@ fn default_if_arg_present_with_value_no_arg_with_default_fail() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "first"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "first" + ); } #[test] @@ -310,7 +364,10 @@ fn default_if_arg_present_with_value_with_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "default"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "default" + ); } #[test] @@ -326,7 +383,10 @@ fn default_if_arg_present_with_value_with_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -342,7 +402,10 @@ fn default_if_arg_present_no_arg_with_value_with_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -358,7 +421,10 @@ fn default_if_arg_present_no_arg_with_value_with_default_user_override_fail() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } // Unsetting the default @@ -387,7 +453,7 @@ fn no_default_if_arg_present_with_value_with_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(!m.is_present("arg")); - assert!(m.value_of("arg").is_none()); + assert!(m.get_one::("arg").map(|v| v.as_str()).is_none()); } #[test] @@ -403,7 +469,10 @@ fn no_default_if_arg_present_with_value_with_default_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "other"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -419,7 +488,10 @@ fn no_default_if_arg_present_no_arg_with_value_with_default() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "default"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "default" + ); } // Multiple conditions @@ -441,7 +513,10 @@ fn default_ifs_arg_present() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "flg"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "flg" + ); } #[test] @@ -458,7 +533,7 @@ fn no_default_ifs_arg_present() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(!m.is_present("arg")); - assert!(m.value_of("arg").is_none()); + assert!(m.get_one::("arg").map(|v| v.as_str()).is_none()); } #[test] @@ -478,7 +553,10 @@ fn default_ifs_arg_present_user_override() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "value"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "value" + ); } #[test] @@ -498,7 +576,10 @@ fn default_ifs_arg_present_order() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "default"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "default" + ); } // Interaction with requires @@ -528,8 +609,14 @@ fn conditional_reqs_pass() { assert!(m.is_ok(), "{}", m.unwrap_err()); let m = m.unwrap(); - assert_eq!(m.value_of("output"), Some("other")); - assert_eq!(m.value_of("input"), Some("some")); + assert_eq!( + m.get_one::("output").map(|v| v.as_str()), + Some("other") + ); + assert_eq!( + m.get_one::("input").map(|v| v.as_str()), + Some("some") + ); } #[test] @@ -609,7 +696,10 @@ fn issue_1050_num_vals_and_defaults() { .try_get_matches_from(vec!["hello", "--exit-code=1"]); assert!(res.is_ok(), "{}", res.unwrap_err()); let m = res.unwrap(); - assert_eq!(m.value_of("exit-code"), Some("1")); + assert_eq!( + m.get_one::("exit-code").map(|v| v.as_str()), + Some("1") + ); } #[cfg(debug_assertions)] @@ -710,7 +800,11 @@ fn with_value_delimiter() { let matches = cmd.try_get_matches_from(vec![""]).unwrap(); assert_eq!( - matches.values_of("option").unwrap().collect::>(), + matches + .get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["first", "second"] ); } @@ -729,7 +823,11 @@ fn missing_with_value_delimiter() { .unwrap(); assert_eq!( - matches.values_of("option").unwrap().collect::>(), + matches + .get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["value1", "value2", "value3", "value4", "value5"] ); } diff --git a/tests/builder/delimiters.rs b/tests/builder/delimiters.rs index 2ead7a3d333..81f5dac8d87 100644 --- a/tests/builder/delimiters.rs +++ b/tests/builder/delimiters.rs @@ -11,7 +11,10 @@ fn opt_default_no_delim() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -25,7 +28,10 @@ fn opt_eq_no_delim() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -39,7 +45,10 @@ fn opt_s_eq_no_delim() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -53,7 +62,10 @@ fn opt_s_default_no_delim() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -67,7 +79,10 @@ fn opt_s_no_space_no_delim() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -86,7 +101,10 @@ fn opt_s_no_space_mult_no_delim() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -107,7 +125,10 @@ fn opt_eq_mult_def_delim() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val1", "val2", "val3"] ); } diff --git a/tests/builder/empty_values.rs b/tests/builder/empty_values.rs index 91ae6eaedca..34102be29a1 100644 --- a/tests/builder/empty_values.rs +++ b/tests/builder/empty_values.rs @@ -8,7 +8,7 @@ fn empty_values() { .arg(Arg::new("config").long("config").takes_value(true)) .try_get_matches_from(&["config", "--config", ""]) .unwrap(); - assert_eq!(m.value_of("config"), Some("")); + assert_eq!(m.get_one::("config").map(|v| v.as_str()), Some("")); } #[test] @@ -17,13 +17,13 @@ fn empty_values_with_equals() { .arg(Arg::new("config").long("config").takes_value(true)) .try_get_matches_from(&["config", "--config="]) .unwrap(); - assert_eq!(m.value_of("config"), Some("")); + assert_eq!(m.get_one::("config").map(|v| v.as_str()), Some("")); let m = Command::new("config") .arg(Arg::new("config").short('c').takes_value(true)) .try_get_matches_from(&["config", "-c="]) .unwrap(); - assert_eq!(m.value_of("config"), Some("")) + assert_eq!(m.get_one::("config").map(|v| v.as_str()), Some("")) } #[test] diff --git a/tests/builder/env.rs b/tests/builder/env.rs index df4ca24628e..28129df32dc 100644 --- a/tests/builder/env.rs +++ b/tests/builder/env.rs @@ -17,7 +17,10 @@ fn env() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg").unwrap(), "env"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "env" + ); } #[test] @@ -35,7 +38,7 @@ fn env_bool_literal() { let m = r.unwrap(); assert!(m.is_present("present")); assert_eq!(m.occurrences_of("present"), 0); - assert_eq!(m.value_of("present"), None); + assert_eq!(m.get_one::("present").map(|v| v.as_str()), None); assert!(!m.is_present("negated")); assert!(!m.is_present("absent")); } @@ -56,7 +59,10 @@ fn env_os() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg").unwrap(), "env"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "env" + ); } #[test] @@ -77,7 +83,7 @@ fn no_env() { let m = r.unwrap(); assert!(!m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg"), None); + assert_eq!(m.get_one::("arg").map(|v| v.as_str()), None); } #[test] @@ -94,7 +100,7 @@ fn no_env_no_takes_value() { let m = r.unwrap(); assert!(!m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg"), None); + assert_eq!(m.get_one::("arg").map(|v| v.as_str()), None); } #[test] @@ -114,7 +120,10 @@ fn with_default() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg").unwrap(), "env"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "env" + ); } #[test] @@ -133,10 +142,17 @@ fn opt_user_override() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 1); - assert_eq!(m.value_of("arg").unwrap(), "opt"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "opt" + ); // see https://github.com/clap-rs/clap/issues/1835 - let values: Vec<_> = m.values_of("arg").unwrap().collect(); + let values: Vec<_> = m + .get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect(); assert_eq!(values, vec!["opt"]); } @@ -156,7 +172,10 @@ fn positionals() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg").unwrap(), "env"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "env" + ); } #[test] @@ -175,10 +194,17 @@ fn positionals_user_override() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 1); - assert_eq!(m.value_of("arg").unwrap(), "opt"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "opt" + ); // see https://github.com/clap-rs/clap/issues/1835 - let values: Vec<_> = m.values_of("arg").unwrap().collect(); + let values: Vec<_> = m + .get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect(); assert_eq!(values, vec!["opt"]); } @@ -200,7 +226,13 @@ fn multiple_one() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.values_of("arg").unwrap().collect::>(), vec!["env"]); + assert_eq!( + m.get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + vec!["env"] + ); } #[test] @@ -222,7 +254,10 @@ fn multiple_three() { assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); assert_eq!( - m.values_of("arg").unwrap().collect::>(), + m.get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), vec!["env1", "env2", "env3"] ); } @@ -245,7 +280,10 @@ fn multiple_no_delimiter() { assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); assert_eq!( - m.values_of("arg").unwrap().collect::>(), + m.get_many::("arg") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), vec!["env1 env2 env3"] ); } @@ -267,7 +305,10 @@ fn possible_value() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg").unwrap(), "env"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "env" + ); } #[test] @@ -309,7 +350,10 @@ fn value_parser() { let m = r.unwrap(); assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("arg"), 0); - assert_eq!(m.value_of("arg").unwrap(), "env"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "env" + ); } #[test] diff --git a/tests/builder/error.rs b/tests/builder/error.rs index 15cdefd1e3b..317d7251b71 100644 --- a/tests/builder/error.rs +++ b/tests/builder/error.rs @@ -1,6 +1,6 @@ use crate::utils; -use clap::{arg, error::ErrorKind, Arg, Command, Error}; +use clap::{arg, error::ErrorKind, value_parser, Arg, Command, Error}; fn assert_error(err: Error, expected_kind: ErrorKind, expected_output: &str, stderr: bool) { let actual_output = err.to_string(); @@ -55,30 +55,13 @@ For more information try --help #[test] fn value_validation_has_newline() { - let m = Command::new("test") - .arg(arg!().help("Network port to use")) - .try_get_matches_from(["test", "foo"]) - .unwrap(); - - let res = m.value_of_t::("PORT"); - - assert!(res.is_err()); - let err = res.unwrap_err(); - assert!( - err.to_string().ends_with('\n'), - "Errors should have a trailing newline, got {:?}", - err.to_string() - ); -} - -#[test] -fn argument_not_found_auto_has_newline() { - let m = Command::new("test") - .arg(arg!([PORT]).help("Network port to use")) - .try_get_matches_from(["test"]) - .unwrap(); - - let res = m.value_of_t::("PORT"); + let res = Command::new("test") + .arg( + arg!() + .value_parser(value_parser!(usize)) + .help("Network port to use"), + ) + .try_get_matches_from(["test", "foo"]); assert!(res.is_err()); let err = res.unwrap_err(); diff --git a/tests/builder/flags.rs b/tests/builder/flags.rs index fd8a4301b44..eb14a6e5ec2 100644 --- a/tests/builder/flags.rs +++ b/tests/builder/flags.rs @@ -146,7 +146,10 @@ fn issue_1284_argument_in_flag_style() { .clone() .try_get_matches_from(vec!["", "--", "--another-flag"]) .unwrap(); - assert_eq!(m.value_of("filename"), Some("--another-flag")); + assert_eq!( + m.get_one::("filename").map(|v| v.as_str()), + Some("--another-flag") + ); let m = cmd .clone() @@ -158,7 +161,10 @@ fn issue_1284_argument_in_flag_style() { .clone() .try_get_matches_from(vec!["", "--", "--a-flag"]) .unwrap(); - assert_eq!(m.value_of("filename"), Some("--a-flag")); + assert_eq!( + m.get_one::("filename").map(|v| v.as_str()), + Some("--a-flag") + ); utils::assert_output(cmd, "mycat --another-flag", USE_FLAG_AS_ARGUMENT, true); } diff --git a/tests/builder/global_args.rs b/tests/builder/global_args.rs index d8024089664..a2eb4963348 100644 --- a/tests/builder/global_args.rs +++ b/tests/builder/global_args.rs @@ -40,7 +40,8 @@ fn propagate_global_arg_in_subcommand_to_subsubcommand_1385() { .unwrap() .subcommand_matches("sub1a") .unwrap() - .value_of("arg1") + .get_one::("arg1") + .map(|v| v.as_str()) .unwrap() ); } @@ -70,7 +71,10 @@ fn propagate_global_arg_to_subcommand_in_subsubcommand_2053() { .unwrap(); assert_eq!( Some("world"), - m.subcommand_matches("test").unwrap().value_of("sub-str") + m.subcommand_matches("test") + .unwrap() + .get_one::("sub-str") + .map(|v| v.as_str()) ); } diff --git a/tests/builder/grouped_values.rs b/tests/builder/grouped_values.rs index 622e9c93e87..8b284dcdab2 100644 --- a/tests/builder/grouped_values.rs +++ b/tests/builder/grouped_values.rs @@ -188,13 +188,19 @@ fn issue_1374() { .clone() .try_get_matches_from(&["MyApp", "--input", "a", "b", "c", "--input", "d"]) .unwrap(); - let vs = matches.values_of("input").unwrap(); + let vs = matches + .get_many::("input") + .unwrap() + .map(|v| v.as_str()); assert_eq!(vs.collect::>(), vec!["a", "b", "c", "d"]); let matches = cmd .clone() .try_get_matches_from(&["MyApp", "--input", "a", "b", "--input", "c", "d"]) .unwrap(); - let vs = matches.values_of("input").unwrap(); + let vs = matches + .get_many::("input") + .unwrap() + .map(|v| v.as_str()); assert_eq!(vs.collect::>(), vec!["a", "b", "c", "d"]); } diff --git a/tests/builder/groups.rs b/tests/builder/groups.rs index e9f0c561cd6..2247b989728 100644 --- a/tests/builder/groups.rs +++ b/tests/builder/groups.rs @@ -94,7 +94,10 @@ fn group_single_value() { let m = res.unwrap(); assert!(m.is_present("grp")); - assert_eq!(m.value_of("grp").unwrap(), "blue"); + assert_eq!( + m.get_one::("grp").map(|v| v.as_str()).unwrap(), + "blue" + ); } #[test] @@ -108,7 +111,7 @@ fn group_single_flag() { let m = res.unwrap(); assert!(m.is_present("grp")); - assert!(m.value_of("grp").is_none()); + assert!(m.get_one::("grp").map(|v| v.as_str()).is_none()); } #[test] @@ -122,7 +125,7 @@ fn group_empty() { let m = res.unwrap(); assert!(!m.is_present("grp")); - assert!(m.value_of("grp").is_none()); + assert!(m.get_one::("grp").map(|v| v.as_str()).is_none()); } #[test] @@ -149,7 +152,10 @@ fn group_multi_value_single_arg() { let m = res.unwrap(); assert!(m.is_present("grp")); assert_eq!( - &*m.values_of("grp").unwrap().collect::>(), + &*m.get_many::("grp") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["blue", "red", "green"] ); } @@ -311,15 +317,15 @@ fn issue_1794() { ); let m = cmd.clone().try_get_matches_from(&["cmd", "pos1", "pos2"]).unwrap(); - assert_eq!(m.value_of("pos1"), Some("pos1")); - assert_eq!(m.value_of("pos2"), Some("pos2")); + assert_eq!(m.get_one::("pos1").map(|v| v.as_str()), Some("pos1")); + assert_eq!(m.get_one::("pos2").map(|v| v.as_str()), Some("pos2")); assert!(!m.is_present("option1")); let m = cmd .clone() .try_get_matches_from(&["cmd", "--option1", "positional"]).unwrap(); - assert_eq!(m.value_of("pos1"), None); - assert_eq!(m.value_of("pos2"), Some("positional")); + assert_eq!(m.get_one::("pos1").map(|v| v.as_str()), None); + assert_eq!(m.get_one::("pos2").map(|v| v.as_str()), Some("positional")); assert!(m.is_present("option1")); } */ diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 68cb2811c8d..737ef25c8ae 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -2651,7 +2651,11 @@ fn override_help_subcommand() { .disable_help_subcommand(true); let matches = cmd.try_get_matches_from(&["bar", "help", "foo"]).unwrap(); assert_eq!( - matches.subcommand_matches("help").unwrap().value_of("arg"), + matches + .subcommand_matches("help") + .unwrap() + .get_one::("arg") + .map(|v| v.as_str()), Some("foo") ); } @@ -2752,7 +2756,10 @@ fn help_without_short() { assert_eq!(help.get_short(), None); let m = cmd.try_get_matches_from(["test", "-h", "0x100"]).unwrap(); - assert_eq!(m.value_of("hex"), Some("0x100")); + assert_eq!( + m.get_one::("hex").map(|v| v.as_str()), + Some("0x100") + ); } #[test] diff --git a/tests/builder/ignore_errors.rs b/tests/builder/ignore_errors.rs index 894b7d6c876..547320c5b0a 100644 --- a/tests/builder/ignore_errors.rs +++ b/tests/builder/ignore_errors.rs @@ -44,9 +44,12 @@ fn multiple_args_and_final_arg_without_value() { assert!(r.is_ok(), "unexpected error: {:?}", r); let m = r.unwrap(); - assert_eq!(m.value_of("config"), Some("file")); + assert_eq!( + m.get_one::("config").map(|v| v.as_str()), + Some("file") + ); assert!(m.is_present("f")); - assert_eq!(m.value_of("stuff"), None); + assert_eq!(m.get_one::("stuff").map(|v| v.as_str()), None); } #[test] @@ -68,9 +71,12 @@ fn multiple_args_and_intermittent_arg_without_value() { assert!(r.is_ok(), "unexpected error: {:?}", r); let m = r.unwrap(); - assert_eq!(m.value_of("config"), Some("file")); + assert_eq!( + m.get_one::("config").map(|v| v.as_str()), + Some("file") + ); assert!(m.is_present("f")); - assert_eq!(m.value_of("stuff"), None); + assert_eq!(m.get_one::("stuff").map(|v| v.as_str()), None); } #[test] @@ -112,6 +118,9 @@ fn subcommand() { sub_m.is_present("test"), "expected subcommand to be present due to partial parsing" ); - assert_eq!(sub_m.value_of("test"), None); - assert_eq!(sub_m.value_of("stuff"), Some("some other val")); + assert_eq!(sub_m.get_one::("test").map(|v| v.as_str()), None); + assert_eq!( + sub_m.get_one::("stuff").map(|v| v.as_str()), + Some("some other val") + ); } diff --git a/tests/builder/multiple_occurrences.rs b/tests/builder/multiple_occurrences.rs index 6e7c6339172..e3f087a96b0 100644 --- a/tests/builder/multiple_occurrences.rs +++ b/tests/builder/multiple_occurrences.rs @@ -60,7 +60,7 @@ fn multiple_occurrences_of_positional() { .expect("zero occurrences work"); assert!(!m.is_present("multi")); assert_eq!(m.occurrences_of("multi"), 0); - assert!(m.values_of("multi").is_none()); + assert!(m.get_many::("multi").is_none()); let m = cmd .clone() @@ -68,7 +68,13 @@ fn multiple_occurrences_of_positional() { .expect("single occurrence work"); assert!(m.is_present("multi")); assert_eq!(m.occurrences_of("multi"), 1); - assert_eq!(m.values_of("multi").unwrap().collect::>(), ["one"]); + assert_eq!( + m.get_many::("multi") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + ["one"] + ); let m = cmd .clone() @@ -77,7 +83,10 @@ fn multiple_occurrences_of_positional() { assert!(m.is_present("multi")); assert_eq!(m.occurrences_of("multi"), 4); assert_eq!( - m.values_of("multi").unwrap().collect::>(), + m.get_many::("multi") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["one", "two", "three", "four"] ); } diff --git a/tests/builder/multiple_values.rs b/tests/builder/multiple_values.rs index 3f115e76ade..2029a4df356 100644 --- a/tests/builder/multiple_values.rs +++ b/tests/builder/multiple_values.rs @@ -21,7 +21,10 @@ fn option_long() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 3); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -45,7 +48,10 @@ fn option_short() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 3); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -72,7 +78,10 @@ fn option_mixed() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 4); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4"] ); } @@ -95,7 +104,10 @@ fn option_exact_exact() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 3); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -117,7 +129,10 @@ fn option_exact_exact_not_mult() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -142,7 +157,10 @@ fn option_exact_exact_mult() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 2); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4", "val5", "val6"] ); } @@ -199,7 +217,10 @@ fn option_min_exact() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 3); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -242,10 +263,13 @@ fn option_short_min_more_mult_occurs() { assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("option"), 4); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4"] ); - assert_eq!(m.value_of("arg"), Some("pos")); + assert_eq!(m.get_one::("arg").map(|v| v.as_str()), Some("pos")); } #[test] @@ -267,10 +291,13 @@ fn option_short_min_more_single_occur() { assert!(m.is_present("arg")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4"] ); - assert_eq!(m.value_of("arg"), Some("pos")); + assert_eq!(m.get_one::("arg").map(|v| v.as_str()), Some("pos")); } #[test] @@ -291,7 +318,10 @@ fn option_max_exact() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 3); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -314,7 +344,10 @@ fn option_max_less() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 2); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2"] ); } @@ -354,7 +387,10 @@ fn positional() { assert!(m.is_present("pos")); assert_eq!(m.occurrences_of("pos"), 3); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -375,7 +411,10 @@ fn positional_exact_exact() { assert!(m.is_present("pos")); assert_eq!(m.occurrences_of("pos"), 3); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -420,7 +459,10 @@ fn positional_min_exact() { assert!(m.is_present("pos")); assert_eq!(m.occurrences_of("pos"), 3); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -447,7 +489,10 @@ fn positional_min_more() { assert!(m.is_present("pos")); assert_eq!(m.occurrences_of("pos"), 4); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4"] ); } @@ -464,7 +509,10 @@ fn positional_max_exact() { assert!(m.is_present("pos")); assert_eq!(m.occurrences_of("pos"), 3); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -481,7 +529,10 @@ fn positional_max_less() { assert!(m.is_present("pos")); assert_eq!(m.occurrences_of("pos"), 2); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2"] ); } @@ -513,7 +564,10 @@ fn sep_long_equals() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -535,7 +589,10 @@ fn sep_long_space() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -557,7 +614,10 @@ fn sep_short_equals() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -579,7 +639,10 @@ fn sep_short_space() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -601,7 +664,10 @@ fn sep_short_no_space() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -622,7 +688,10 @@ fn sep_positional() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -644,7 +713,10 @@ fn different_sep() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -665,7 +737,10 @@ fn different_sep_positional() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -687,7 +762,10 @@ fn no_sep() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -706,7 +784,10 @@ fn no_sep_positional() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); - assert_eq!(m.value_of("option").unwrap(), "val1,val2,val3"); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()).unwrap(), + "val1,val2,val3" + ); } #[test] @@ -733,11 +814,17 @@ fn req_delimiter_long() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val1"] ); assert_eq!( - m.values_of("args").unwrap().collect::>(), + m.get_many::("args") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val2", "val3"] ); } @@ -766,11 +853,17 @@ fn req_delimiter_long_with_equal() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val1"] ); assert_eq!( - m.values_of("args").unwrap().collect::>(), + m.get_many::("args") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val2", "val3"] ); } @@ -799,11 +892,17 @@ fn req_delimiter_short_with_space() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val1"] ); assert_eq!( - m.values_of("args").unwrap().collect::>(), + m.get_many::("args") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val2", "val3"] ); } @@ -832,11 +931,17 @@ fn req_delimiter_short_with_no_space() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val1"] ); assert_eq!( - m.values_of("args").unwrap().collect::>(), + m.get_many::("args") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val2", "val3"] ); } @@ -865,11 +970,17 @@ fn req_delimiter_short_with_equal() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 1); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val1"] ); assert_eq!( - m.values_of("args").unwrap().collect::>(), + m.get_many::("args") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["val2", "val3"] ); } @@ -927,14 +1038,20 @@ fn req_delimiter_complex() { assert!(m.is_present("option")); assert_eq!(m.occurrences_of("option"), 10); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &[ "val2", "val4", "val6", "val8", "val10", "val12", "val13", "val15", "val16", "val18", "val19", "val21", "val22", "val24", "val25", ] ); assert_eq!( - m.values_of("args").unwrap().collect::>(), + m.get_many::("args") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &[ "val1", "val3", "val5", "val7", "val9", "val11", "val14", "val17", "val20", "val23", "val26", @@ -1026,10 +1143,16 @@ fn low_index_positional() { assert!(m.is_present("target")); assert_eq!(m.occurrences_of("target"), 1); assert_eq!( - m.values_of("files").unwrap().collect::>(), + m.get_many::("files") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["file1", "file2", "file3"] ); - assert_eq!(m.value_of("target").unwrap(), "target"); + assert_eq!( + m.get_one::("target").map(|v| v.as_str()).unwrap(), + "target" + ); } #[test] @@ -1057,10 +1180,16 @@ fn low_index_positional_in_subcmd() { assert!(sm.is_present("target")); assert_eq!(sm.occurrences_of("target"), 1); assert_eq!( - sm.values_of("files").unwrap().collect::>(), + sm.get_many::("files") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["file1", "file2", "file3"] ); - assert_eq!(sm.value_of("target").unwrap(), "target"); + assert_eq!( + sm.get_one::("target").map(|v| v.as_str()).unwrap(), + "target" + ); } #[test] @@ -1087,11 +1216,20 @@ fn low_index_positional_with_option() { assert!(m.is_present("target")); assert_eq!(m.occurrences_of("target"), 1); assert_eq!( - m.values_of("files").unwrap().collect::>(), + m.get_many::("files") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["file1", "file2", "file3"] ); - assert_eq!(m.value_of("target").unwrap(), "target"); - assert_eq!(m.value_of("opt").unwrap(), "test"); + assert_eq!( + m.get_one::("target").map(|v| v.as_str()).unwrap(), + "target" + ); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()).unwrap(), + "test" + ); } #[test] @@ -1116,10 +1254,16 @@ fn low_index_positional_with_flag() { assert!(m.is_present("target")); assert_eq!(m.occurrences_of("target"), 1); assert_eq!( - m.values_of("files").unwrap().collect::>(), + m.get_many::("files") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["file1", "file2", "file3"] ); - assert_eq!(m.value_of("target").unwrap(), "target"); + assert_eq!( + m.get_one::("target").map(|v| v.as_str()).unwrap(), + "target" + ); assert!(m.is_present("flg")); } @@ -1143,10 +1287,16 @@ fn multiple_value_terminator_option() { assert_eq!(m.occurrences_of("other"), 1); assert!(m.is_present("files")); assert_eq!( - m.values_of("files").unwrap().collect::>(), + m.get_many::("files") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2"] ); - assert_eq!(m.value_of("other"), Some("otherval")); + assert_eq!( + m.get_one::("other").map(|v| v.as_str()), + Some("otherval") + ); } #[test] @@ -1169,10 +1319,16 @@ fn multiple_value_terminator_option_other_arg() { assert!(m.is_present("other")); assert!(m.is_present("files")); assert_eq!( - m.values_of("files").unwrap().collect::>(), + m.get_many::("files") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2"] ); - assert_eq!(m.value_of("other"), Some("otherval")); + assert_eq!( + m.get_one::("other").map(|v| v.as_str()), + Some("otherval") + ); assert!(m.is_present("flag")); } @@ -1200,9 +1356,16 @@ fn multiple_vals_with_hyphen() { assert!(res.is_ok(), "{:?}", res.unwrap_err().kind()); let m = res.unwrap(); - let cmds: Vec<_> = m.values_of("cmds").unwrap().collect(); + let cmds: Vec<_> = m + .get_many::("cmds") + .unwrap() + .map(|v| v.as_str()) + .collect(); assert_eq!(&cmds, &["find", "-type", "f", "-name", "special"]); - assert_eq!(m.value_of("location"), Some("/home/clap")); + assert_eq!( + m.get_one::("location").map(|v| v.as_str()), + Some("/home/clap") + ); } #[test] @@ -1265,7 +1428,10 @@ fn value_names_building_num_vals() { let m = m.unwrap(); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -1280,7 +1446,10 @@ fn value_names_building_num_vals_for_positional() { let m = m.unwrap(); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3"] ); } @@ -1300,7 +1469,10 @@ fn number_of_values_preferred_over_value_names() { let m = m.unwrap(); assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4"] ); } @@ -1320,7 +1492,10 @@ fn values_per_occurrence_named() { Err(err) => panic!("{}", err), }; assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2"] ); @@ -1332,7 +1507,10 @@ fn values_per_occurrence_named() { Err(err) => panic!("{}", err), }; assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4"] ); } @@ -1351,7 +1529,10 @@ fn values_per_occurrence_positional() { Err(err) => panic!("{}", err), }; assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2"] ); @@ -1361,7 +1542,10 @@ fn values_per_occurrence_positional() { Err(err) => panic!("{}", err), }; assert_eq!( - m.values_of("pos").unwrap().collect::>(), + m.get_many::("pos") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), ["val1", "val2", "val3", "val4"] ); } diff --git a/tests/builder/opts.rs b/tests/builder/opts.rs index 9500952cb70..53fd6fa6448 100644 --- a/tests/builder/opts.rs +++ b/tests/builder/opts.rs @@ -79,7 +79,7 @@ fn require_equals_min_values_zero() { assert!(res.is_ok(), "{}", res.unwrap_err()); let m = res.unwrap(); assert!(m.is_present("cfg")); - assert_eq!(m.value_of("cmd"), Some("cmd")); + assert_eq!(m.get_one::("cmd").map(|v| v.as_str()), Some("cmd")); } #[test] @@ -93,7 +93,10 @@ fn double_hyphen_as_value() { ) .try_get_matches_from(vec!["prog", "--config", "--"]); assert!(res.is_ok(), "{:?}", res); - assert_eq!(res.unwrap().value_of("cfg"), Some("--")); + assert_eq!( + res.unwrap().get_one::("cfg").map(|v| v.as_str()), + Some("--") + ); } #[test] @@ -146,7 +149,7 @@ fn stdin_char() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("f")); - assert_eq!(m.value_of("f").unwrap(), "-"); + assert_eq!(m.get_one::("f").map(|v| v.as_str()).unwrap(), "-"); } #[test] @@ -160,9 +163,15 @@ fn opts_using_short() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("f")); - assert_eq!(m.value_of("f").unwrap(), "some"); + assert_eq!( + m.get_one::("f").map(|v| v.as_str()).unwrap(), + "some" + ); assert!(m.is_present("c")); - assert_eq!(m.value_of("c").unwrap(), "other"); + assert_eq!( + m.get_one::("c").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -202,7 +211,7 @@ fn lots_o_vals() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.values_of("o").unwrap().count(), 297); // i.e. more than u8 + assert_eq!(m.get_many::("o").unwrap().count(), 297); // i.e. more than u8 } #[test] @@ -216,9 +225,15 @@ fn opts_using_long_space() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("flag")); - assert_eq!(m.value_of("flag").unwrap(), "some"); + assert_eq!( + m.get_one::("flag").map(|v| v.as_str()).unwrap(), + "some" + ); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "other"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -232,9 +247,15 @@ fn opts_using_long_equals() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("flag")); - assert_eq!(m.value_of("flag").unwrap(), "some"); + assert_eq!( + m.get_one::("flag").map(|v| v.as_str()).unwrap(), + "some" + ); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "other"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -248,9 +269,15 @@ fn opts_using_mixed() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("flag")); - assert_eq!(m.value_of("flag").unwrap(), "some"); + assert_eq!( + m.get_one::("flag").map(|v| v.as_str()).unwrap(), + "some" + ); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "other"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -264,9 +291,15 @@ fn opts_using_mixed2() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("flag")); - assert_eq!(m.value_of("flag").unwrap(), "some"); + assert_eq!( + m.get_one::("flag").map(|v| v.as_str()).unwrap(), + "some" + ); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "other"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -277,7 +310,10 @@ fn default_values_user_value() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.value_of("o").unwrap(), "value"); + assert_eq!( + m.get_one::("o").map(|v| v.as_str()).unwrap(), + "value" + ); } #[test] @@ -289,9 +325,12 @@ fn multiple_vals_pos_arg_equals() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.value_of("o").unwrap(), "1"); + assert_eq!(m.get_one::("o").map(|v| v.as_str()).unwrap(), "1"); assert!(m.is_present("file")); - assert_eq!(m.value_of("file").unwrap(), "some"); + assert_eq!( + m.get_one::("file").map(|v| v.as_str()).unwrap(), + "some" + ); } #[test] @@ -307,9 +346,18 @@ fn multiple_vals_pos_arg_delim() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.values_of("o").unwrap().collect::>(), &["1", "2"]); + assert_eq!( + m.get_many::("o") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["1", "2"] + ); assert!(m.is_present("file")); - assert_eq!(m.value_of("file").unwrap(), "some"); + assert_eq!( + m.get_one::("file").map(|v| v.as_str()).unwrap(), + "some" + ); } #[test] @@ -341,9 +389,18 @@ fn require_delims() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.values_of("o").unwrap().collect::>(), &["1", "2"]); + assert_eq!( + m.get_many::("o") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["1", "2"] + ); assert!(m.is_present("file")); - assert_eq!(m.value_of("file").unwrap(), "some"); + assert_eq!( + m.get_one::("file").map(|v| v.as_str()).unwrap(), + "some" + ); } #[test] @@ -358,7 +415,13 @@ fn leading_hyphen_pass() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.values_of("o").unwrap().collect::>(), &["-2", "3"]); + assert_eq!( + m.get_many::("o") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["-2", "3"] + ); } #[test] @@ -384,7 +447,13 @@ fn leading_hyphen_with_flag_after() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.values_of("o").unwrap().collect::>(), &["-2", "-f"]); + assert_eq!( + m.get_many::("o") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["-2", "-f"] + ); assert!(!m.is_present("f")); } @@ -397,7 +466,13 @@ fn leading_hyphen_with_flag_before() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.values_of("o").unwrap().collect::>(), &["-2"]); + assert_eq!( + m.get_many::("o") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["-2"] + ); assert!(m.is_present("f")); } @@ -415,8 +490,14 @@ fn leading_hyphen_with_only_pos_follows() { assert!(r.is_ok(), "{:?}", r); let m = r.unwrap(); assert!(m.is_present("o")); - assert_eq!(m.values_of("o").unwrap().collect::>(), &["-2"]); - assert_eq!(m.value_of("arg"), Some("val")); + assert_eq!( + m.get_many::("o") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["-2"] + ); + assert_eq!(m.get_one::("arg").map(|v| v.as_str()), Some("val")); } #[test] @@ -440,7 +521,10 @@ fn issue_1047_min_zero_vals_default_val() { .try_get_matches_from(vec!["foo", "-d"]) .unwrap(); assert_eq!(m.occurrences_of("del"), 1); - assert_eq!(m.value_of("del"), Some("default")); + assert_eq!( + m.get_one::("del").map(|v| v.as_str()), + Some("default") + ); } fn issue_1105_setup(argv: Vec<&'static str>) -> Result { @@ -462,7 +546,7 @@ fn issue_1105_empty_value_long_explicit() { let r = issue_1105_setup(vec!["cmd", "--option", ""]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); - assert_eq!(m.value_of("option"), Some("")); + assert_eq!(m.get_one::("option").map(|v| v.as_str()), Some("")); } #[test] @@ -470,7 +554,7 @@ fn issue_1105_empty_value_long_equals() { let r = issue_1105_setup(vec!["cmd", "--option="]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); - assert_eq!(m.value_of("option"), Some("")); + assert_eq!(m.get_one::("option").map(|v| v.as_str()), Some("")); } #[test] @@ -485,7 +569,7 @@ fn issue_1105_empty_value_short_explicit() { let r = issue_1105_setup(vec!["cmd", "-o", ""]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); - assert_eq!(m.value_of("option"), Some("")); + assert_eq!(m.get_one::("option").map(|v| v.as_str()), Some("")); } #[test] @@ -493,7 +577,7 @@ fn issue_1105_empty_value_short_equals() { let r = issue_1105_setup(vec!["cmd", "-o="]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); - assert_eq!(m.value_of("option"), Some("")); + assert_eq!(m.get_one::("option").map(|v| v.as_str()), Some("")); } #[test] @@ -501,7 +585,7 @@ fn issue_1105_empty_value_short_explicit_no_space() { let r = issue_1105_setup(vec!["cmd", "-o", ""]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); - assert_eq!(m.value_of("option"), Some("")); + assert_eq!(m.get_one::("option").map(|v| v.as_str()), Some("")); } #[test] @@ -525,7 +609,13 @@ fn short_non_ascii_no_space() { .try_get_matches_from(&["test", "-磨VALUE"]) .unwrap(); - assert_eq!("VALUE", matches.value_of("opt").unwrap()); + assert_eq!( + "VALUE", + matches + .get_one::("opt") + .map(|v| v.as_str()) + .unwrap() + ); } #[test] @@ -535,7 +625,13 @@ fn short_eq_val_starts_with_eq() { .try_get_matches_from(&["test", "-f==value"]) .unwrap(); - assert_eq!("=value", matches.value_of("opt").unwrap()); + assert_eq!( + "=value", + matches + .get_one::("opt") + .map(|v| v.as_str()) + .unwrap() + ); } #[test] @@ -545,7 +641,13 @@ fn long_eq_val_starts_with_eq() { .try_get_matches_from(&["test", "--foo==value"]) .unwrap(); - assert_eq!("=value", matches.value_of("opt").unwrap()); + assert_eq!( + "=value", + matches + .get_one::("opt") + .map(|v| v.as_str()) + .unwrap() + ); } #[test] @@ -554,7 +656,7 @@ fn issue_2022_get_flags_misuse() { .next_help_heading(Some("test")) .arg(Arg::new("a").long("a").default_value("32")); let matches = cmd.try_get_matches_from(&[""]).unwrap(); - assert!(matches.value_of("a").is_some()) + assert!(matches.get_one::("a").map(|v| v.as_str()).is_some()) } #[test] @@ -565,7 +667,12 @@ fn issue_2279() { .try_get_matches_from(&[""]) .unwrap(); - assert_eq!(before_help_heading.value_of("foo"), Some("bar")); + assert_eq!( + before_help_heading + .get_one::("foo") + .map(|v| v.as_str()), + Some("bar") + ); let after_help_heading = Command::new("cmd") .next_help_heading(Some("This causes default_value to be ignored")) @@ -573,7 +680,12 @@ fn issue_2279() { .try_get_matches_from(&[""]) .unwrap(); - assert_eq!(after_help_heading.value_of("foo"), Some("bar")); + assert_eq!( + after_help_heading + .get_one::("foo") + .map(|v| v.as_str()), + Some("bar") + ); } #[test] @@ -588,21 +700,30 @@ fn infer_long_arg() { .try_get_matches_from(&["test", "--racec=hello"]) .unwrap(); assert!(!matches.is_present("racetrack")); - assert_eq!(matches.value_of("racecar"), Some("hello")); + assert_eq!( + matches.get_one::("racecar").map(|v| v.as_str()), + Some("hello") + ); let matches = cmd .clone() .try_get_matches_from(&["test", "--racet"]) .unwrap(); assert!(matches.is_present("racetrack")); - assert_eq!(matches.value_of("racecar"), None); + assert_eq!( + matches.get_one::("racecar").map(|v| v.as_str()), + None + ); let matches = cmd .clone() .try_get_matches_from(&["test", "--auto"]) .unwrap(); assert!(matches.is_present("racetrack")); - assert_eq!(matches.value_of("racecar"), None); + assert_eq!( + matches.get_one::("racecar").map(|v| v.as_str()), + None + ); let cmd = Command::new("test") .infer_long_args(true) diff --git a/tests/builder/positionals.rs b/tests/builder/positionals.rs index 2e3a4fd890b..ea5b1824246 100644 --- a/tests/builder/positionals.rs +++ b/tests/builder/positionals.rs @@ -9,7 +9,10 @@ fn only_pos_follow() { let m = r.unwrap(); assert!(m.is_present("arg")); assert!(!m.is_present("f")); - assert_eq!(m.value_of("arg").unwrap(), "-f"); + assert_eq!( + m.get_one::("arg").map(|v| v.as_str()).unwrap(), + "-f" + ); } #[test] @@ -28,7 +31,10 @@ fn issue_946() { let matches = r.unwrap(); assert!(matches.is_present("exact")); - assert!(matches.value_of("filter").is_none()); + assert!(matches + .get_one::("filter") + .map(|v| v.as_str()) + .is_none()); } #[test] @@ -40,7 +46,12 @@ fn positional() { let m = r.unwrap(); assert!(m.is_present("positional")); assert!(m.is_present("flag")); - assert_eq!(m.value_of("positional").unwrap(), "test"); + assert_eq!( + m.get_one::("positional") + .map(|v| v.as_str()) + .unwrap(), + "test" + ); let m = Command::new("positional") .args(&[arg!(-f --flag "some flag"), Arg::new("positional").index(1)]) @@ -48,7 +59,12 @@ fn positional() { .unwrap(); assert!(m.is_present("positional")); assert!(m.is_present("flag")); - assert_eq!(m.value_of("positional").unwrap(), "test"); + assert_eq!( + m.get_one::("positional") + .map(|v| v.as_str()) + .unwrap(), + "test" + ); } #[test] @@ -88,7 +104,7 @@ fn lots_o_vals() { assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); assert!(m.is_present("opt")); - assert_eq!(m.values_of("opt").unwrap().count(), 297); // i.e. more than u8 + assert_eq!(m.get_many::("opt").unwrap().count(), 297); // i.e. more than u8 } #[test] @@ -107,7 +123,10 @@ fn positional_multiple() { assert!(m.is_present("positional")); assert!(m.is_present("flag")); assert_eq!( - &*m.values_of("positional").unwrap().collect::>(), + &*m.get_many::("positional") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["test1", "test2", "test3"] ); } @@ -128,7 +147,10 @@ fn positional_multiple_3() { assert!(m.is_present("positional")); assert!(m.is_present("flag")); assert_eq!( - &*m.values_of("positional").unwrap().collect::>(), + &*m.get_many::("positional") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["test1", "test2", "test3"] ); } @@ -156,7 +178,10 @@ fn positional_possible_values() { assert!(m.is_present("positional")); assert!(m.is_present("flag")); assert_eq!( - &*m.values_of("positional").unwrap().collect::>(), + &*m.get_many::("positional") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["test123"] ); } @@ -242,7 +267,13 @@ fn last_positional() { .try_get_matches_from(vec!["test", "tgt", "--", "arg"]); assert!(r.is_ok(), "{}", r.unwrap_err()); let m = r.unwrap(); - assert_eq!(m.values_of("ARGS").unwrap().collect::>(), &["arg"]); + assert_eq!( + m.get_many::("ARGS") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["arg"] + ); } #[test] @@ -306,5 +337,8 @@ fn ignore_hyphen_values_on_last() { ); let matches = cmd.try_get_matches_from(["test", "-n", "foo"]).unwrap(); - assert_eq!(matches.value_of("name"), Some("foo")); + assert_eq!( + matches.get_one::("name").map(|v| v.as_str()), + Some("foo") + ); } diff --git a/tests/builder/posix_compatible.rs b/tests/builder/posix_compatible.rs index 09a0120d81a..7cdd10ec08a 100644 --- a/tests/builder/posix_compatible.rs +++ b/tests/builder/posix_compatible.rs @@ -39,7 +39,10 @@ fn option_overrides_itself() { let m = res.unwrap(); assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 1); - assert_eq!(m.value_of("opt"), Some("other")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("other") + ); } #[test] @@ -60,7 +63,10 @@ fn mult_option_require_delim_overrides_itself() { assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 3); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["some", "other", "one", "two"] ); } @@ -89,7 +95,10 @@ fn mult_option_overrides_itself() { assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 2); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["first", "overrides", "some", "other", "val"] ); } @@ -107,7 +116,10 @@ fn option_use_delim_false_override_itself() { assert!(m.is_present("opt")); assert_eq!(m.occurrences_of("opt"), 1); assert_eq!( - m.values_of("opt").unwrap().collect::>(), + m.get_many::("opt") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["one,two"] ); } @@ -123,7 +135,10 @@ fn pos_mult_overrides_itself() { assert!(m.is_present("val")); assert_eq!(m.occurrences_of("val"), 3); assert_eq!( - m.values_of("val").unwrap().collect::>(), + m.get_many::("val") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["some", "other", "value"] ); } @@ -183,7 +198,10 @@ fn posix_compatible_opts_long() { .try_get_matches_from(vec!["", "--flag", "some", "--color", "other"]) .unwrap(); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "other"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "other" + ); assert!(!m.is_present("flag")); } @@ -200,7 +218,10 @@ fn posix_compatible_opts_long_rev() { .unwrap(); assert!(!m.is_present("color")); assert!(m.is_present("flag")); - assert_eq!(m.value_of("flag").unwrap(), "other"); + assert_eq!( + m.get_one::("flag").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -215,7 +236,10 @@ fn posix_compatible_opts_long_equals() { .try_get_matches_from(vec!["", "--flag=some", "--color=other"]) .unwrap(); assert!(m.is_present("color")); - assert_eq!(m.value_of("color").unwrap(), "other"); + assert_eq!( + m.get_one::("color").map(|v| v.as_str()).unwrap(), + "other" + ); assert!(!m.is_present("flag")); } @@ -232,7 +256,10 @@ fn posix_compatible_opts_long_equals_rev() { .unwrap(); assert!(!m.is_present("color")); assert!(m.is_present("flag")); - assert_eq!(m.value_of("flag").unwrap(), "other"); + assert_eq!( + m.get_one::("flag").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -247,7 +274,10 @@ fn posix_compatible_opts_short() { .try_get_matches_from(vec!["", "-f", "some", "-c", "other"]) .unwrap(); assert!(m.is_present("c")); - assert_eq!(m.value_of("c").unwrap(), "other"); + assert_eq!( + m.get_one::("c").map(|v| v.as_str()).unwrap(), + "other" + ); assert!(!m.is_present("f")); } @@ -264,7 +294,10 @@ fn posix_compatible_opts_short_rev() { .unwrap(); assert!(!m.is_present("c")); assert!(m.is_present("f")); - assert_eq!(m.value_of("f").unwrap(), "other"); + assert_eq!( + m.get_one::("f").map(|v| v.as_str()).unwrap(), + "other" + ); } #[test] @@ -377,13 +410,22 @@ fn issue_1374_overrides_self_with_multiple_values() { .clone() .try_get_matches_from(&["test", "--input", "a", "b", "c", "--input", "d"]) .unwrap(); - assert_eq!(m.values_of("input").unwrap().collect::>(), &["d"]); + assert_eq!( + m.get_many::("input") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["d"] + ); let m = cmd .clone() .try_get_matches_from(&["test", "--input", "a", "b", "--input", "c", "d"]) .unwrap(); assert_eq!( - m.values_of("input").unwrap().collect::>(), + m.get_many::("input") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["c", "d"] ); } @@ -396,6 +438,12 @@ fn incremental_override() { let m = cmd .try_get_matches_from_mut(&["test", "--name=ahmed", "--no-name", "--name=ali"]) .unwrap(); - assert_eq!(m.values_of("name").unwrap().collect::>(), &["ali"]); + assert_eq!( + m.get_many::("name") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), + &["ali"] + ); assert!(!m.is_present("no-name")); } diff --git a/tests/builder/possible_values.rs b/tests/builder/possible_values.rs index 062436e78f3..0d3bf86cd8e 100644 --- a/tests/builder/possible_values.rs +++ b/tests/builder/possible_values.rs @@ -44,7 +44,10 @@ fn possible_values_of_positional() { let m = m.unwrap(); assert!(m.is_present("positional")); - assert_eq!(m.value_of("positional"), Some("test123")); + assert_eq!( + m.get_one::("positional").map(|v| v.as_str()), + Some("test123") + ); } #[test] @@ -63,7 +66,10 @@ fn possible_value_arg_value() { let m = m.unwrap(); assert!(m.is_present("arg_value")); - assert_eq!(m.value_of("arg_value"), Some("test123")); + assert_eq!( + m.get_one::("arg_value").map(|v| v.as_str()), + Some("test123") + ); } #[test] @@ -93,7 +99,10 @@ fn possible_values_of_positional_multiple() { assert!(m.is_present("positional")); assert_eq!( - m.values_of("positional").unwrap().collect::>(), + m.get_many::("positional") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), vec!["test123", "test321"] ); } @@ -130,7 +139,10 @@ fn possible_values_of_option() { let m = m.unwrap(); assert!(m.is_present("option")); - assert_eq!(m.value_of("option"), Some("test123")); + assert_eq!( + m.get_one::("option").map(|v| v.as_str()), + Some("test123") + ); } #[test] @@ -167,7 +179,10 @@ fn possible_values_of_option_multiple() { assert!(m.is_present("option")); assert_eq!( - m.values_of("option").unwrap().collect::>(), + m.get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), vec!["test123", "test321"] ); } @@ -299,7 +314,12 @@ fn alias() { .try_get_matches_from(vec!["pv", "--option", "123"]); assert!(m.is_ok(), "{}", m.unwrap_err()); - assert!(m.unwrap().value_of("option").unwrap().eq("123")); + assert!(m + .unwrap() + .get_one::("option") + .map(|v| v.as_str()) + .unwrap() + .eq("123")); } #[test] @@ -319,7 +339,12 @@ fn aliases() { .try_get_matches_from(vec!["pv", "--option", "2"]); assert!(m.is_ok(), "{}", m.unwrap_err()); - assert!(m.unwrap().value_of("option").unwrap().eq("2")); + assert!(m + .unwrap() + .get_one::("option") + .map(|v| v.as_str()) + .unwrap() + .eq("2")); } #[test] @@ -338,7 +363,8 @@ fn ignore_case() { assert!(m.is_ok(), "{}", m.unwrap_err()); assert!(m .unwrap() - .value_of("option") + .get_one::("option") + .map(|v| v.as_str()) .unwrap() .eq_ignore_ascii_case("test123")); } @@ -375,7 +401,11 @@ fn ignore_case_multiple() { assert!(m.is_ok(), "{}", m.unwrap_err()); assert_eq!( - m.unwrap().values_of("option").unwrap().collect::>(), + m.unwrap() + .get_many::("option") + .unwrap() + .map(|v| v.as_str()) + .collect::>(), &["TeSt123", "teST123", "tESt321"] ); } diff --git a/tests/builder/propagate_globals.rs b/tests/builder/propagate_globals.rs index 88ac5743a8a..68ec2a1d62c 100644 --- a/tests/builder/propagate_globals.rs +++ b/tests/builder/propagate_globals.rs @@ -37,15 +37,21 @@ fn get_inner_matches(m: &ArgMatches) -> &ArgMatches { } fn top_can_access_arg>>(m: &ArgMatches, val: T) -> bool { - m.value_of("GLOBAL_ARG") == val.into() + m.get_one::("GLOBAL_ARG").map(|v| v.as_str()) == val.into() } fn inner_can_access_arg>>(m: &ArgMatches, val: T) -> bool { - get_inner_matches(m).value_of("GLOBAL_ARG") == val.into() + get_inner_matches(m) + .get_one::("GLOBAL_ARG") + .map(|v| v.as_str()) + == val.into() } fn outer_can_access_arg>>(m: &ArgMatches, val: T) -> bool { - get_outer_matches(m).value_of("GLOBAL_ARG") == val.into() + get_outer_matches(m) + .get_one::("GLOBAL_ARG") + .map(|v| v.as_str()) + == val.into() } fn top_can_access_flag(m: &ArgMatches, present: bool, occurrences: u64) -> bool { diff --git a/tests/builder/require.rs b/tests/builder/require.rs index aadae20f1ce..d3157ce0d21 100644 --- a/tests/builder/require.rs +++ b/tests/builder/require.rs @@ -90,9 +90,12 @@ fn option_required_2() { .try_get_matches_from(vec!["", "-f", "val", "-c", "other_val"]) .unwrap(); assert!(m.is_present("c")); - assert_eq!(m.value_of("c").unwrap(), "other_val"); + assert_eq!( + m.get_one::("c").map(|v| v.as_str()).unwrap(), + "other_val" + ); assert!(m.is_present("f")); - assert_eq!(m.value_of("f").unwrap(), "val"); + assert_eq!(m.get_one::("f").map(|v| v.as_str()).unwrap(), "val"); } #[test] @@ -112,7 +115,10 @@ fn positional_required_2() { .try_get_matches_from(vec!["", "someval"]) .unwrap(); assert!(m.is_present("flag")); - assert_eq!(m.value_of("flag").unwrap(), "someval"); + assert_eq!( + m.get_one::("flag").map(|v| v.as_str()).unwrap(), + "someval" + ); } #[test] @@ -1232,7 +1238,10 @@ fn requires_with_default_value() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(!m.is_present("flag")); } @@ -1255,7 +1264,10 @@ fn requires_if_with_default_value() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(!m.is_present("flag")); } @@ -1274,7 +1286,10 @@ fn group_requires_with_default_value() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(!m.is_present("flag")); } @@ -1296,7 +1311,10 @@ fn required_if_eq_on_default_value() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(!m.is_present("flag")); } @@ -1318,7 +1336,10 @@ fn required_if_eq_all_on_default_value() { ); let m = result.unwrap(); - assert_eq!(m.value_of("opt"), Some("default")); + assert_eq!( + m.get_one::("opt").map(|v| v.as_str()), + Some("default") + ); assert!(!m.is_present("flag")); } diff --git a/tests/builder/subcommands.rs b/tests/builder/subcommands.rs index 8e047de642a..82f8725548d 100644 --- a/tests/builder/subcommands.rs +++ b/tests/builder/subcommands.rs @@ -116,7 +116,10 @@ fn subcommand() { assert_eq!(m.subcommand_name().unwrap(), "some"); let sub_m = m.subcommand_matches("some").unwrap(); assert!(sub_m.is_present("test")); - assert_eq!(sub_m.value_of("test").unwrap(), "testing"); + assert_eq!( + sub_m.get_one::("test").map(|v| v.as_str()).unwrap(), + "testing" + ); } #[test] @@ -160,7 +163,10 @@ fn subcommand_multiple() { assert_eq!(m.subcommand_name().unwrap(), "some"); let sub_m = m.subcommand_matches("some").unwrap(); assert!(sub_m.is_present("test")); - assert_eq!(sub_m.value_of("test").unwrap(), "testing"); + assert_eq!( + sub_m.get_one::("test").map(|v| v.as_str()).unwrap(), + "testing" + ); } #[test] @@ -335,7 +341,10 @@ fn issue_1031_args_with_same_name() { assert!(res.is_ok(), "{:?}", res.unwrap_err().kind()); let m = res.unwrap(); - assert_eq!(m.value_of("ui-path"), Some("signer")); + assert_eq!( + m.get_one::("ui-path").map(|v| v.as_str()), + Some("signer") + ); } #[test] @@ -347,7 +356,10 @@ fn issue_1031_args_with_same_name_no_more_vals() { assert!(res.is_ok(), "{:?}", res.unwrap_err().kind()); let m = res.unwrap(); - assert_eq!(m.value_of("ui-path"), Some("value")); + assert_eq!( + m.get_one::("ui-path").map(|v| v.as_str()), + Some("value") + ); assert_eq!(m.subcommand_name(), Some("signer")); } @@ -388,7 +400,9 @@ fn issue_1161_multiple_hyphen_hyphen() { "position", "args", ]); - let actual = m.values_of("slop").map(|vals| vals.collect::>()); + let actual = m + .get_many::("slop") + .map(|vals| vals.map(|s| s.as_str()).collect::>()); assert_eq!(expected, actual); } @@ -399,7 +413,10 @@ fn issue_1722_not_emit_error_when_arg_follows_similar_to_a_subcommand() { .subcommand(Command::new("subcommand")) .arg(Arg::new("argument")) .try_get_matches_from(vec!["myprog", "--", "subcommand"]); - assert_eq!(m.unwrap().value_of("argument"), Some("subcommand")); + assert_eq!( + m.unwrap().get_one::("argument").map(|v| v.as_str()), + Some("subcommand") + ); } #[test] @@ -434,7 +451,10 @@ fn subcommand_after_argument() { .subcommand(Command::new("test")) .try_get_matches_from(vec!["myprog", "teat", "test"]) .unwrap(); - assert_eq!(m.value_of("some_text"), Some("teat")); + assert_eq!( + m.get_one::("some_text").map(|v| v.as_str()), + Some("teat") + ); assert_eq!(m.subcommand().unwrap().0, "test"); } @@ -445,7 +465,10 @@ fn subcommand_after_argument_looks_like_help() { .subcommand(Command::new("test")) .try_get_matches_from(vec!["myprog", "helt", "test"]) .unwrap(); - assert_eq!(m.value_of("some_text"), Some("helt")); + assert_eq!( + m.get_one::("some_text").map(|v| v.as_str()), + Some("helt") + ); assert_eq!(m.subcommand().unwrap().0, "test"); } diff --git a/tests/builder/tests.rs b/tests/builder/tests.rs index 841309ae573..f817c85af3a 100644 --- a/tests/builder/tests.rs +++ b/tests/builder/tests.rs @@ -98,7 +98,7 @@ pub fn check_complex_output(args: &str, out: &str) { } if matches.is_present("option") { - if let Some(v) = matches.value_of("option") { + if let Some(v) = matches.get_one::("option").map(|v| v.as_str()) { writeln!( w, "option present {} times with value: {}", @@ -107,7 +107,7 @@ pub fn check_complex_output(args: &str, out: &str) { ) .unwrap(); } - if let Some(ov) = matches.values_of("option") { + if let Some(ov) = matches.get_many::("option") { for o in ov { writeln!(w, "An option: {}", o).unwrap(); } @@ -116,7 +116,7 @@ pub fn check_complex_output(args: &str, out: &str) { writeln!(w, "option NOT present").unwrap(); } - if let Some(p) = matches.value_of("positional") { + if let Some(p) = matches.get_one::("positional").map(|v| v.as_str()) { writeln!(w, "positional present with value: {}", p).unwrap(); } else { writeln!(w, "positional NOT present").unwrap(); @@ -127,13 +127,19 @@ pub fn check_complex_output(args: &str, out: &str) { writeln!( w, "option2 present with value of: {}", - matches.value_of("long-option-2").unwrap() + matches + .get_one::("long-option-2") + .map(|v| v.as_str()) + .unwrap() ) .unwrap(); writeln!( w, "positional2 present with value of: {}", - matches.value_of("positional2").unwrap() + matches + .get_one::("positional2") + .map(|v| v.as_str()) + .unwrap() ) .unwrap(); } else { @@ -141,31 +147,45 @@ pub fn check_complex_output(args: &str, out: &str) { writeln!( w, "option2 maybe present with value of: {}", - matches.value_of("long-option-2").unwrap_or("Nothing") + matches + .get_one::("long-option-2") + .map(|v| v.as_str()) + .unwrap_or("Nothing") ) .unwrap(); writeln!( w, "positional2 maybe present with value of: {}", - matches.value_of("positional2").unwrap_or("Nothing") + matches + .get_one::("positional2") + .map(|v| v.as_str()) + .unwrap_or("Nothing") ) .unwrap(); } - let _ = match matches.value_of("option3").unwrap_or("") { + let _ = match matches + .get_one::("option3") + .map(|v| v.as_str()) + .unwrap_or("") + { "fast" => writeln!(w, "option3 present quickly"), "slow" => writeln!(w, "option3 present slowly"), _ => writeln!(w, "option3 NOT present"), }; - let _ = match matches.value_of("positional3").unwrap_or("") { + let _ = match matches + .get_one::("positional3") + .map(|v| v.as_str()) + .unwrap_or("") + { "vi" => writeln!(w, "positional3 present in vi mode"), "emacs" => writeln!(w, "positional3 present in emacs mode"), _ => writeln!(w, "positional3 NOT present"), }; if matches.is_present("option") { - if let Some(v) = matches.value_of("option") { + if let Some(v) = matches.get_one::("option").map(|v| v.as_str()) { writeln!( w, "option present {} times with value: {}", @@ -174,7 +194,7 @@ pub fn check_complex_output(args: &str, out: &str) { ) .unwrap(); } - if let Some(ov) = matches.values_of("option") { + if let Some(ov) = matches.get_many::("option") { for o in ov { writeln!(w, "An option: {}", o).unwrap(); } @@ -183,7 +203,7 @@ pub fn check_complex_output(args: &str, out: &str) { writeln!(w, "option NOT present").unwrap(); } - if let Some(p) = matches.value_of("positional") { + if let Some(p) = matches.get_one::("positional").map(|v| v.as_str()) { writeln!(w, "positional present with value: {}", p).unwrap(); } else { writeln!(w, "positional NOT present").unwrap(); @@ -198,10 +218,10 @@ pub fn check_complex_output(args: &str, out: &str) { } if matches.is_present("option") { - if let Some(v) = matches.value_of("option") { + if let Some(v) = matches.get_one::("option").map(|v| v.as_str()) { writeln!(w, "scoption present with value: {}", v).unwrap(); } - if let Some(ov) = matches.values_of("option") { + if let Some(ov) = matches.get_many::("option") { for o in ov { writeln!(w, "An scoption: {}", o).unwrap(); } @@ -210,7 +230,10 @@ pub fn check_complex_output(args: &str, out: &str) { writeln!(w, "scoption NOT present").unwrap(); } - if let Some(p) = matches.value_of("scpositional") { + if let Some(p) = matches + .get_one::("scpositional") + .map(|v| v.as_str()) + { writeln!(w, "scpositional present with value: {}", p).unwrap(); } } diff --git a/tests/builder/unicode.rs b/tests/builder/unicode.rs index 35c0ae054c4..aa9bad55001 100644 --- a/tests/builder/unicode.rs +++ b/tests/builder/unicode.rs @@ -14,5 +14,9 @@ fn possible_values_ignore_case() { .try_get_matches_from(vec!["pv", "--option", "Ä"]); assert!(m.is_ok(), "{}", m.unwrap_err()); - assert!(m.unwrap().value_of("option").is_some()); + assert!(m + .unwrap() + .get_one::("option") + .map(|v| v.as_str()) + .is_some()); } diff --git a/tests/builder/utf8.rs b/tests/builder/utf8.rs index 795fbb0e0fe..e517877267a 100644 --- a/tests/builder/utf8.rs +++ b/tests/builder/utf8.rs @@ -382,7 +382,11 @@ fn allow_invalid_utf8_subcommand_args_with_allow_external_subcommands() { assert!(m.is_ok(), "{}", m.unwrap_err()); let m = m.unwrap(); let (subcommand, args) = m.subcommand().unwrap(); - let args = args.values_of_os("").unwrap().collect::>(); + let args = args + .get_many::("") + .unwrap() + .cloned() + .collect::>(); assert_eq!(subcommand, OsString::from("subcommand")); assert_eq!( args, @@ -399,7 +403,7 @@ fn allow_validated_utf8_value_of() { #![allow(deprecated)] let a = Command::new("test").arg(arg!(--name )); let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap(); - let _ = m.value_of("name"); + let _ = m.get_one::("name").map(|v| v.as_str()); } #[test] @@ -417,7 +421,7 @@ fn panic_validated_utf8_with_defaults() { #![allow(deprecated)] let a = Command::new("test").arg(arg!(--value ).required(false).default_value("foo")); let m = a.try_get_matches_from(["test"]).unwrap(); - let _ = m.value_of("value"); + let _ = m.get_one::("value").map(|v| v.as_str()); let _ = m.value_of_os("value"); } @@ -430,16 +434,16 @@ fn allow_invalid_utf8_value_of_os() { } #[test] -#[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8` at `name`"] +#[should_panic = "Mismatch between definition and access of `name`. Could not downcast to alloc::string::String, need to downcast to std::ffi::os_str::OsString"] fn panic_invalid_utf8_value_of() { #![allow(deprecated)] let a = Command::new("test").arg(arg!(--name ).allow_invalid_utf8(true)); let m = a.try_get_matches_from(["test", "--name", "me"]).unwrap(); - let _ = m.value_of("name"); + let _ = m.get_one::("name").map(|v| v.as_str()); } #[test] -#[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8` at `value`"] +#[should_panic = "Mismatch between definition and access of `value`. Could not downcast to alloc::string::String, need to downcast to std::ffi::os_str::OsString"] fn panic_invalid_utf8_with_defaults() { #![allow(deprecated)] let a = Command::new("test").arg( @@ -450,7 +454,7 @@ fn panic_invalid_utf8_with_defaults() { ); let m = a.try_get_matches_from(["test"]).unwrap(); let _ = m.value_of_os("value"); - let _ = m.value_of("value"); + let _ = m.get_one::("value").map(|v| v.as_str()); } #[test] @@ -458,16 +462,16 @@ fn allow_validated_utf8_external_subcommand_values_of() { let a = Command::new("test").allow_external_subcommands(true); let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); let (_ext, args) = m.subcommand().unwrap(); - args.values_of("").unwrap_or_default().count(); + args.get_many::("").unwrap_or_default().count(); } #[test] -#[should_panic = "Must use `Arg::allow_invalid_utf8` with `_os` lookups"] +#[should_panic = "Mismatch between definition and access of ``. Could not downcast to std::ffi::os_str::OsString, need to downcast to alloc::string::String"] fn panic_validated_utf8_external_subcommand_values_of_os() { let a = Command::new("test").allow_external_subcommands(true); let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); let (_ext, args) = m.subcommand().unwrap(); - args.values_of_os("").unwrap_or_default().count(); + args.get_many::("").unwrap_or_default().count(); } #[test] @@ -477,16 +481,16 @@ fn allow_invalid_utf8_external_subcommand_values_of_os() { .allow_invalid_utf8_for_external_subcommands(true); let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); let (_ext, args) = m.subcommand().unwrap(); - args.values_of_os("").unwrap_or_default().count(); + args.get_many::("").unwrap_or_default().count(); } #[test] -#[should_panic = "Must use `_os` lookups with `Arg::allow_invalid_utf8`"] +#[should_panic = "Mismatch between definition and access of ``. Could not downcast to alloc::string::String, need to downcast to std::ffi::os_str::OsString"] fn panic_invalid_utf8_external_subcommand_values_of() { let a = Command::new("test") .allow_external_subcommands(true) .allow_invalid_utf8_for_external_subcommands(true); let m = a.try_get_matches_from(vec!["test", "cmd", "arg"]).unwrap(); let (_ext, args) = m.subcommand().unwrap(); - args.values_of("").unwrap_or_default().count(); + args.get_many::("").unwrap_or_default().count(); } diff --git a/tests/macros.rs b/tests/macros.rs index caa7b270fbd..df9240eaafb 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -481,7 +481,7 @@ mod arg_impl { .try_get_matches_from(vec!["", "some-val"]) .unwrap(); assert!(m.is_present("some-arg")); - assert_eq!(m.value_of("some-arg").unwrap(), "some-val"); + assert_eq!(m.get_one::("some-arg").unwrap(), "some-val"); } #[test] @@ -502,7 +502,7 @@ mod arg_impl { .try_get_matches_from(vec!["", "-a", "val"]) .unwrap(); assert!(m.is_present("some-val")); - assert_eq!(m.value_of("some-val").unwrap(), "val"); + assert_eq!(m.get_one::("some-val").unwrap(), "val"); } #[test] @@ -523,6 +523,6 @@ mod arg_impl { .try_get_matches_from(vec!["", "--arg", "some-val"]) .unwrap(); assert!(m.is_present("arg")); - assert_eq!(m.value_of("arg").unwrap(), "some-val"); + assert_eq!(m.get_one::("arg").unwrap(), "some-val"); } } From 814d30b1defea27e78f320ad41cc0c2406552480 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 25 May 2022 13:00:51 -0500 Subject: [PATCH 8/9] fix(parser): Deprecate is_valid_arg --- src/parser/matches/arg_matches.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index f6d478e0346..6b27174f78b 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -835,13 +835,9 @@ impl ArgMatches { Some(i) } - /// Check if an arg can be queried - /// - /// By default, `ArgMatches` functions assert on undefined `Id`s to help catch programmer - /// mistakes. In some context, this doesn't work, so users can use this function to check - /// before they do a query on `ArgMatches`. #[inline] #[doc(hidden)] + #[deprecated(since = "3.2.0", note = "Replaced with `ArgMatches::try_get_one()`")] pub fn is_valid_arg(&self, _id: impl Key) -> bool { #[cfg(debug_assertions)] { From 408ca3c5d770cd81698ba7a23206c21599d8f316 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 25 May 2022 13:13:22 -0500 Subject: [PATCH 9/9] test(derive): Update for deprecations --- tests/derive_ui/default_value_t_invalid.rs | 2 +- tests/derive_ui/default_value_t_invalid.stderr | 6 +++--- tests/derive_ui/flatten_and_methods.rs | 4 ++-- tests/derive_ui/flatten_and_parse.rs | 4 ++-- tests/derive_ui/skip_flatten.rs | 9 ++++++--- tests/derive_ui/skip_subcommand.rs | 9 ++++++--- tests/derive_ui/skip_without_default.rs | 2 +- tests/derive_ui/struct_parse.rs | 2 +- tests/derive_ui/struct_subcommand.rs | 2 +- tests/derive_ui/subcommand_and_flatten.rs | 9 ++++++--- tests/derive_ui/subcommand_and_methods.rs | 9 ++++++--- tests/derive_ui/subcommand_and_parse.rs | 9 ++++++--- tests/derive_ui/subcommand_opt_opt.rs | 9 ++++++--- tests/derive_ui/subcommand_opt_vec.rs | 9 ++++++--- 14 files changed, 53 insertions(+), 32 deletions(-) diff --git a/tests/derive_ui/default_value_t_invalid.rs b/tests/derive_ui/default_value_t_invalid.rs index 47fdc9f9a78..25ef73ebde7 100644 --- a/tests/derive_ui/default_value_t_invalid.rs +++ b/tests/derive_ui/default_value_t_invalid.rs @@ -11,7 +11,7 @@ use clap::Parser; #[derive(Parser, Debug)] #[clap(name = "basic")] struct Opt { - #[clap(default_value_t = -10)] + #[clap(value_parser, default_value_t = -10)] value: u32, } diff --git a/tests/derive_ui/default_value_t_invalid.stderr b/tests/derive_ui/default_value_t_invalid.stderr index db54dc82e85..8ce536a9a48 100644 --- a/tests/derive_ui/default_value_t_invalid.stderr +++ b/tests/derive_ui/default_value_t_invalid.stderr @@ -1,7 +1,7 @@ error[E0600]: cannot apply unary operator `-` to type `u32` - --> $DIR/default_value_t_invalid.rs:14:30 + --> $DIR/default_value_t_invalid.rs:14:44 | -14 | #[clap(default_value_t = -10)] - | ^^^ cannot apply unary operator `-` +14 | #[clap(value_parser, default_value_t = -10)] + | ^^^ cannot apply unary operator `-` | = note: unsigned values cannot be negated diff --git a/tests/derive_ui/flatten_and_methods.rs b/tests/derive_ui/flatten_and_methods.rs index b1020a8e988..45dbc4fdcc2 100644 --- a/tests/derive_ui/flatten_and_methods.rs +++ b/tests/derive_ui/flatten_and_methods.rs @@ -10,9 +10,9 @@ use clap::Parser; #[derive(Parser, Debug)] struct DaemonOpts { - #[clap(short)] + #[clap(short, value_parser)] user: String, - #[clap(short)] + #[clap(short, value_parser)] group: String, } diff --git a/tests/derive_ui/flatten_and_parse.rs b/tests/derive_ui/flatten_and_parse.rs index d69b9ae2d5e..ea52dd459af 100644 --- a/tests/derive_ui/flatten_and_parse.rs +++ b/tests/derive_ui/flatten_and_parse.rs @@ -10,9 +10,9 @@ use clap::Parser; #[derive(Parser, Debug)] struct DaemonOpts { - #[clap(short)] + #[clap(short, value_parser)] user: String, - #[clap(short)] + #[clap(short, value_parser)] group: String, } diff --git a/tests/derive_ui/skip_flatten.rs b/tests/derive_ui/skip_flatten.rs index 95e9ba4d614..11941f971cc 100644 --- a/tests/derive_ui/skip_flatten.rs +++ b/tests/derive_ui/skip_flatten.rs @@ -11,7 +11,7 @@ use clap::Parser; #[derive(Parser, Debug)] #[clap(name = "make-cookie")] struct MakeCookie { - #[clap(short)] + #[clap(short, value_parser)] s: String, #[clap(skip, flatten)] @@ -22,10 +22,13 @@ struct MakeCookie { enum Command { #[clap(name = "pound")] /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, + Pound { + #[clap(value_parser)] + acorns: u32, + }, Sparkle { - #[clap(short)] + #[clap(short, value_parser)] color: String, }, } diff --git a/tests/derive_ui/skip_subcommand.rs b/tests/derive_ui/skip_subcommand.rs index 9f38d1eb95f..479c8fddbf4 100644 --- a/tests/derive_ui/skip_subcommand.rs +++ b/tests/derive_ui/skip_subcommand.rs @@ -11,7 +11,7 @@ use clap::Parser; #[derive(Parser, Debug)] #[clap(name = "make-cookie")] struct MakeCookie { - #[clap(short)] + #[clap(short, value_parser)] s: String, #[clap(subcommand, skip)] @@ -22,10 +22,13 @@ struct MakeCookie { enum Command { #[clap(name = "pound")] /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, + Pound { + #[clap(value_parser)] + acorns: u32, + }, Sparkle { - #[clap(short)] + #[clap(short, value_parser)] color: String, }, } diff --git a/tests/derive_ui/skip_without_default.rs b/tests/derive_ui/skip_without_default.rs index 682b13b766c..e7a845eeb42 100644 --- a/tests/derive_ui/skip_without_default.rs +++ b/tests/derive_ui/skip_without_default.rs @@ -17,7 +17,7 @@ enum Kind { #[derive(Parser, Debug)] #[clap(name = "test")] pub struct Opt { - #[clap(short)] + #[clap(short, value_parser)] number: u32, #[clap(skip)] k: Kind, diff --git a/tests/derive_ui/struct_parse.rs b/tests/derive_ui/struct_parse.rs index 03f4034fed8..f06ce48e6dd 100644 --- a/tests/derive_ui/struct_parse.rs +++ b/tests/derive_ui/struct_parse.rs @@ -11,7 +11,7 @@ use clap::Parser; #[derive(Parser, Debug)] #[clap(name = "basic", parse(from_str))] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] s: String, } diff --git a/tests/derive_ui/struct_subcommand.rs b/tests/derive_ui/struct_subcommand.rs index 865ad97f0fb..5ac9c21b38d 100644 --- a/tests/derive_ui/struct_subcommand.rs +++ b/tests/derive_ui/struct_subcommand.rs @@ -11,7 +11,7 @@ use clap::Parser; #[derive(Parser, Debug)] #[clap(name = "basic", subcommand)] struct Opt { - #[clap(short)] + #[clap(short, value_parser)] s: String, } diff --git a/tests/derive_ui/subcommand_and_flatten.rs b/tests/derive_ui/subcommand_and_flatten.rs index f2b4caff3f6..bba348437d4 100644 --- a/tests/derive_ui/subcommand_and_flatten.rs +++ b/tests/derive_ui/subcommand_and_flatten.rs @@ -10,7 +10,7 @@ use clap::Parser; #[derive(Parser, Debug)] struct MakeCookie { - #[clap(short)] + #[clap(short, value_parser)] s: String, #[clap(subcommand, flatten)] @@ -20,10 +20,13 @@ struct MakeCookie { #[derive(Parser, Debug)] enum Command { /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, + Pound { + #[clap(value_parser)] + acorns: u32, + }, Sparkle { - #[clap(short)] + #[clap(short, value_parser)] color: String, }, } diff --git a/tests/derive_ui/subcommand_and_methods.rs b/tests/derive_ui/subcommand_and_methods.rs index e0b3cf5ce10..bb7215dd821 100644 --- a/tests/derive_ui/subcommand_and_methods.rs +++ b/tests/derive_ui/subcommand_and_methods.rs @@ -10,7 +10,7 @@ use clap::Parser; #[derive(Parser, Debug)] struct MakeCookie { - #[clap(short)] + #[clap(short, value_parser)] s: String, #[clap(subcommand, long)] @@ -20,10 +20,13 @@ struct MakeCookie { #[derive(Parser, Debug)] enum Command { /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, + Pound { + #[clap(value_parser)] + acorns: u32, + }, Sparkle { - #[clap(short)] + #[clap(short, value_parser)] color: String, }, } diff --git a/tests/derive_ui/subcommand_and_parse.rs b/tests/derive_ui/subcommand_and_parse.rs index 8d7993c886f..430db74e1ee 100644 --- a/tests/derive_ui/subcommand_and_parse.rs +++ b/tests/derive_ui/subcommand_and_parse.rs @@ -10,7 +10,7 @@ use clap::Parser; #[derive(Parser, Debug)] struct MakeCookie { - #[clap(short)] + #[clap(short, value_parser)] s: String, #[clap(subcommand, parse(from_occurrences))] @@ -20,10 +20,13 @@ struct MakeCookie { #[derive(Parser, Debug)] enum Command { /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, + Pound { + #[clap(value_parser)] + acorns: u32, + }, Sparkle { - #[clap(short)] + #[clap(short, value_parser)] color: String, }, } diff --git a/tests/derive_ui/subcommand_opt_opt.rs b/tests/derive_ui/subcommand_opt_opt.rs index ca8cba6d457..701399c4d30 100644 --- a/tests/derive_ui/subcommand_opt_opt.rs +++ b/tests/derive_ui/subcommand_opt_opt.rs @@ -10,7 +10,7 @@ use clap::Parser; #[derive(Parser, Debug)] struct MakeCookie { - #[clap(short)] + #[clap(short, value_parser)] s: String, #[clap(subcommand)] @@ -20,10 +20,13 @@ struct MakeCookie { #[derive(Parser, Debug)] enum Command { /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, + Pound { + #[clap(value_parser)] + acorns: u32, + }, Sparkle { - #[clap(short)] + #[clap(short, value_parser)] color: String, }, } diff --git a/tests/derive_ui/subcommand_opt_vec.rs b/tests/derive_ui/subcommand_opt_vec.rs index 210af22a04c..7ce7909b536 100644 --- a/tests/derive_ui/subcommand_opt_vec.rs +++ b/tests/derive_ui/subcommand_opt_vec.rs @@ -10,7 +10,7 @@ use clap::Parser; #[derive(Parser, Debug)] struct MakeCookie { - #[clap(short)] + #[clap(short, value_parser)] s: String, #[clap(subcommand)] @@ -20,10 +20,13 @@ struct MakeCookie { #[derive(Parser, Debug)] enum Command { /// Pound acorns into flour for cookie dough. - Pound { acorns: u32 }, + Pound { + #[clap(value_parser)] + acorns: u32, + }, Sparkle { - #[clap(short)] + #[clap(short, value_parser)] color: String, }, }