diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index 1319af34171..c801eeb9d8d 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -601,7 +601,6 @@ fn gen_parsers( Ty::Option => { quote_spanned! { ty.span()=> #arg_matches.#get_one(#id) - .expect("unexpected type") .map(#deref) .map(#parse) .transpose()? @@ -612,7 +611,6 @@ fn gen_parsers( if #arg_matches.is_present(#id) { Some( #arg_matches.#get_one(#id) - .expect("unexpected type") .map(#deref) .map(#parse).transpose()? ) @@ -624,7 +622,6 @@ fn gen_parsers( Ty::OptionVec => quote_spanned! { ty.span()=> if #arg_matches.is_present(#id) { Some(#arg_matches.#get_many(#id) - .expect("unexpected type") .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result, clap::Error>>()) .transpose()? .unwrap_or_else(Vec::new)) @@ -636,7 +633,6 @@ fn gen_parsers( Ty::Vec => { quote_spanned! { ty.span()=> #arg_matches.#get_many(#id) - .expect("unexpected type") .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result, clap::Error>>()) .transpose()? .unwrap_or_else(Vec::new) @@ -658,7 +654,6 @@ fn gen_parsers( Ty::Other => { quote_spanned! { ty.span()=> #arg_matches.#get_one(#id) - .expect("unexpected type") .map(#deref) .ok_or_else(|| clap::Error::raw(clap::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id))) .and_then(#parse)? diff --git a/clap_derive/src/derives/subcommand.rs b/clap_derive/src/derives/subcommand.rs index f391875d84a..77409adf753 100644 --- a/clap_derive/src/derives/subcommand.rs +++ b/clap_derive/src/derives/subcommand.rs @@ -528,7 +528,6 @@ fn gen_from_arg_matches( .chain( #sub_arg_matches_var .remove_many::<#str_ty>("") - .expect("unexpected type") .into_iter().flatten() // `""` isn't present, bug in `unstable-v4` .map(#str_ty::from) ) diff --git a/examples/cargo-example.md b/examples/cargo-example.md index bf7de9ea0f6..9279cc49250 100644 --- a/examples/cargo-example.md +++ b/examples/cargo-example.md @@ -37,9 +37,9 @@ OPTIONS: Then to directly invoke the command, run: ```console $ cargo-example example -Ok(None) +None $ cargo-example example --manifest-path Cargo.toml -Ok(Some("Cargo.toml")) +Some("Cargo.toml") ``` diff --git a/examples/derive_ref/flatten_hand_args.rs b/examples/derive_ref/flatten_hand_args.rs index 31b49f0d7a6..9689170d266 100644 --- a/examples/derive_ref/flatten_hand_args.rs +++ b/examples/derive_ref/flatten_hand_args.rs @@ -17,9 +17,7 @@ impl FromArgMatches for CliArgs { Ok(Self { foo: matches.is_present("foo"), bar: matches.is_present("bar"), - quuz: matches - .remove_one::("quuz") - .expect("matches definition"), + quuz: matches.remove_one::("quuz"), }) } fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> { @@ -29,10 +27,7 @@ impl FromArgMatches for CliArgs { fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> { self.foo |= matches.is_present("foo"); self.bar |= matches.is_present("bar"); - if let Some(quuz) = matches - .remove_one::("quuz") - .expect("matches definition") - { + if let Some(quuz) = matches.remove_one::("quuz") { self.quuz = Some(quuz); } Ok(()) diff --git a/examples/escaped-positional.rs b/examples/escaped-positional.rs index dc0a013d230..035c7b3e87c 100644 --- a/examples/escaped-positional.rs +++ b/examples/escaped-positional.rs @@ -24,18 +24,12 @@ fn main() { // -f used: true println!("-f used: {:?}", matches.is_present("eff")); // -p's value: Some("bob") - println!( - "-p's value: {:?}", - matches - .get_one::("pea") - .expect("matches definition") - ); + println!("-p's value: {:?}", matches.get_one::("pea")); // 'slops' values: Some(["sloppy", "slop", "slop"]) println!( "'slops' values: {:?}", matches .get_many::("slop") - .expect("matches definition") .map(|vals| vals.collect::>()) .unwrap_or_default() ); diff --git a/examples/git.rs b/examples/git.rs index d410ee43868..5536f1487ca 100644 --- a/examples/git.rs +++ b/examples/git.rs @@ -51,25 +51,18 @@ fn main() { Some(("clone", sub_matches)) => { println!( "Cloning {}", - sub_matches - .get_one::("REMOTE") - .expect("matches definition") - .expect("required") + sub_matches.get_one::("REMOTE").expect("required") ); } Some(("push", sub_matches)) => { println!( "Pushing to {}", - sub_matches - .get_one::("REMOTE") - .expect("matches definition") - .expect("required") + sub_matches.get_one::("REMOTE").expect("required") ); } Some(("add", sub_matches)) => { let paths = sub_matches .get_many::("PATH") - .expect("matches definition") .into_iter() .flatten() .collect::>(); @@ -79,21 +72,15 @@ fn main() { let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches)); match stash_command { ("apply", sub_matches) => { - let stash = sub_matches - .get_one::("STASH") - .expect("matches definition"); + let stash = sub_matches.get_one::("STASH"); println!("Applying {:?}", stash); } ("pop", sub_matches) => { - let stash = sub_matches - .get_one::("STASH") - .expect("matches definition"); + let stash = sub_matches.get_one::("STASH"); println!("Popping {:?}", stash); } ("push", sub_matches) => { - let message = sub_matches - .get_one::("message") - .expect("matches definition"); + let message = sub_matches.get_one::("message"); println!("Pushing {:?}", message); } (name, _) => { @@ -104,7 +91,6 @@ fn main() { Some((ext, sub_matches)) => { let args = sub_matches .get_many::("") - .expect("matches definition") .into_iter() .flatten() .collect::>(); diff --git a/examples/pacman.rs b/examples/pacman.rs index 974f1cb11b8..9c90f52b69d 100644 --- a/examples/pacman.rs +++ b/examples/pacman.rs @@ -73,7 +73,6 @@ fn main() { if sync_matches.is_present("search") { let packages: Vec<_> = sync_matches .get_many::("search") - .expect("matches definition") .expect("is present") .map(|s| s.as_str()) .collect(); @@ -84,7 +83,6 @@ fn main() { let packages: Vec<_> = sync_matches .get_many::("package") - .expect("matches definition") .expect("is present") .map(|s| s.as_str()) .collect(); @@ -97,16 +95,10 @@ fn main() { } } Some(("query", query_matches)) => { - if let Some(packages) = query_matches - .get_many::("info") - .expect("matches definition") - { + if let Some(packages) = query_matches.get_many::("info") { let comma_sep = packages.map(|s| s.as_str()).collect::>().join(", "); println!("Retrieving info for {}...", comma_sep); - } else if let Some(queries) = query_matches - .get_many::("search") - .expect("matches definition") - { + } else if let Some(queries) = query_matches.get_many::("search") { let comma_sep = queries.map(|s| s.as_str()).collect::>().join(", "); println!("Searching Locally for {}...", comma_sep); } else { diff --git a/examples/tutorial_builder/01_quick.rs b/examples/tutorial_builder/01_quick.rs index 45ae9ec2540..417f738026e 100644 --- a/examples/tutorial_builder/01_quick.rs +++ b/examples/tutorial_builder/01_quick.rs @@ -26,17 +26,11 @@ fn main() { .get_matches(); // You can check the value provided by positional arguments, or option arguments - if let Some(name) = matches - .get_one::("name") - .expect("matches definition") - { + if let Some(name) = matches.get_one::("name") { println!("Value for name: {}", name); } - if let Some(config_path) = matches - .get_one::("config") - .expect("matches definition") - { + if let Some(config_path) = matches.get_one::("config") { println!("Value for config: {}", config_path.display()); } diff --git a/examples/tutorial_builder/02_app_settings.rs b/examples/tutorial_builder/02_app_settings.rs index 41cbeb741e1..d969f537edf 100644 --- a/examples/tutorial_builder/02_app_settings.rs +++ b/examples/tutorial_builder/02_app_settings.rs @@ -13,16 +13,10 @@ fn main() { println!( "two: {:?}", - matches - .get_one::("two") - .expect("matches definition") - .expect("required") + matches.get_one::("two").expect("required") ); println!( "one: {:?}", - matches - .get_one::("one") - .expect("matches definition") - .expect("required") + matches.get_one::("one").expect("required") ); } diff --git a/examples/tutorial_builder/02_apps.rs b/examples/tutorial_builder/02_apps.rs index da9baf589e2..db9da18f902 100644 --- a/examples/tutorial_builder/02_apps.rs +++ b/examples/tutorial_builder/02_apps.rs @@ -11,16 +11,10 @@ fn main() { println!( "two: {:?}", - matches - .get_one::("two") - .expect("matches definition") - .expect("required") + matches.get_one::("two").expect("required") ); println!( "one: {:?}", - matches - .get_one::("one") - .expect("matches definition") - .expect("required") + matches.get_one::("one").expect("required") ); } diff --git a/examples/tutorial_builder/02_crate.rs b/examples/tutorial_builder/02_crate.rs index 6b8ecaaeda2..16b7e7ee0d6 100644 --- a/examples/tutorial_builder/02_crate.rs +++ b/examples/tutorial_builder/02_crate.rs @@ -10,16 +10,10 @@ fn main() { println!( "two: {:?}", - matches - .get_one::("two") - .expect("matches definition") - .expect("required") + matches.get_one::("two").expect("required") ); println!( "one: {:?}", - matches - .get_one::("one") - .expect("matches definition") - .expect("required") + matches.get_one::("one").expect("required") ); } diff --git a/examples/tutorial_builder/03_02_option.rs b/examples/tutorial_builder/03_02_option.rs index bd8f351ad6a..80e2b915901 100644 --- a/examples/tutorial_builder/03_02_option.rs +++ b/examples/tutorial_builder/03_02_option.rs @@ -7,10 +7,5 @@ fn main() { .arg(arg!(-n --name ).required(false)) .get_matches(); - println!( - "name: {:?}", - matches - .get_one::("name") - .expect("matches definition") - ); + println!("name: {:?}", matches.get_one::("name")); } diff --git a/examples/tutorial_builder/03_03_positional.rs b/examples/tutorial_builder/03_03_positional.rs index 5024319edd8..c6579409a71 100644 --- a/examples/tutorial_builder/03_03_positional.rs +++ b/examples/tutorial_builder/03_03_positional.rs @@ -5,10 +5,5 @@ use clap::{arg, command}; fn main() { let matches = command!().arg(arg!([NAME])).get_matches(); - println!( - "NAME: {:?}", - matches - .get_one::("NAME") - .expect("matches definition") - ); + println!("NAME: {:?}", matches.get_one::("NAME")); } diff --git a/examples/tutorial_builder/03_04_subcommands.rs b/examples/tutorial_builder/03_04_subcommands.rs index 95a51212bbf..1dd1cbf0940 100644 --- a/examples/tutorial_builder/03_04_subcommands.rs +++ b/examples/tutorial_builder/03_04_subcommands.rs @@ -17,9 +17,7 @@ fn main() { match matches.subcommand() { Some(("add", sub_matches)) => println!( "'myapp add' was used, name is: {:?}", - sub_matches - .get_one::("NAME") - .expect("matches definition") + sub_matches.get_one::("NAME") ), _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"), } diff --git a/examples/tutorial_builder/03_05_default_values.rs b/examples/tutorial_builder/03_05_default_values.rs index a49b01d6f0e..c68e8797332 100644 --- a/examples/tutorial_builder/03_05_default_values.rs +++ b/examples/tutorial_builder/03_05_default_values.rs @@ -11,7 +11,6 @@ fn main() { "NAME: {:?}", matches .get_one::("NAME") - .expect("matches definition") .expect("default ensures there is always a value") ); } diff --git a/examples/tutorial_builder/04_01_enum.rs b/examples/tutorial_builder/04_01_enum.rs index a788e32645d..61f70125db3 100644 --- a/examples/tutorial_builder/04_01_enum.rs +++ b/examples/tutorial_builder/04_01_enum.rs @@ -20,7 +20,6 @@ fn main() { // Note, it's safe to call unwrap() because the arg is required match matches .get_one::("MODE") - .expect("matches definition") .expect("'MODE' is required and parsing will fail if its missing") { Mode::Fast => { diff --git a/examples/tutorial_builder/04_01_possible.rs b/examples/tutorial_builder/04_01_possible.rs index 889bc78e0f9..f7b0cfb3415 100644 --- a/examples/tutorial_builder/04_01_possible.rs +++ b/examples/tutorial_builder/04_01_possible.rs @@ -14,7 +14,6 @@ fn main() { // Note, it's safe to call unwrap() because the arg is required match matches .get_one::("MODE") - .expect("matches definition") .expect("'MODE' is required and parsing will fail if its missing") .as_str() { diff --git a/examples/tutorial_builder/04_02_parse.rs b/examples/tutorial_builder/04_02_parse.rs index 3cca7924119..c2f3cc53341 100644 --- a/examples/tutorial_builder/04_02_parse.rs +++ b/examples/tutorial_builder/04_02_parse.rs @@ -14,7 +14,6 @@ fn main() { // Note, it's safe to call unwrap() because the arg is required let port: u16 = *matches .get_one::("PORT") - .expect("matches definition") .expect("'PORT' is required and parsing will fail if its missing"); println!("PORT = {}", port); } diff --git a/examples/tutorial_builder/04_02_validate.rs b/examples/tutorial_builder/04_02_validate.rs index df53f285ab4..e60018a4615 100644 --- a/examples/tutorial_builder/04_02_validate.rs +++ b/examples/tutorial_builder/04_02_validate.rs @@ -16,7 +16,6 @@ fn main() { // Note, it's safe to call unwrap() because the arg is required let port: u16 = *matches .get_one::("PORT") - .expect("matches definition") .expect("'PORT' is required and parsing will fail if its missing"); println!("PORT = {}", port); } diff --git a/examples/tutorial_builder/04_03_relations.rs b/examples/tutorial_builder/04_03_relations.rs index 2f9108ebf48..a3fbe0c3682 100644 --- a/examples/tutorial_builder/04_03_relations.rs +++ b/examples/tutorial_builder/04_03_relations.rs @@ -47,10 +47,7 @@ fn main() { let mut patch = 3; // See if --set-ver was used to set the version manually - let version = if let Some(ver) = matches - .get_one::("set-ver") - .expect("matches definition") - { + let version = if let Some(ver) = matches.get_one::("set-ver") { ver.to_owned() } else { // Increment the one requested (in a real program, we'd reset the lower numbers) @@ -74,22 +71,12 @@ fn main() { if matches.is_present("config") { let input = matches .get_one::("INPUT_FILE") - .expect("matches definition") - .unwrap_or_else(|| { - matches - .get_one::("spec-in") - .expect("matches definition") - .unwrap() - }) + .unwrap_or_else(|| matches.get_one::("spec-in").unwrap()) .display(); println!( "Doing work using input {} and config {}", input, - matches - .get_one::("config") - .expect("matches definition") - .unwrap() - .display() + matches.get_one::("config").unwrap().display() ); } } diff --git a/examples/tutorial_builder/04_04_custom.rs b/examples/tutorial_builder/04_04_custom.rs index 4767ae68c0d..d88698380b2 100644 --- a/examples/tutorial_builder/04_04_custom.rs +++ b/examples/tutorial_builder/04_04_custom.rs @@ -35,10 +35,7 @@ fn main() { let mut patch = 3; // See if --set-ver was used to set the version manually - let version = if let Some(ver) = matches - .get_one::("set-ver") - .expect("matches definition") - { + let version = if let Some(ver) = matches.get_one::("set-ver") { if matches.is_present("major") || matches.is_present("minor") || matches.is_present("patch") { cmd.error( @@ -76,12 +73,7 @@ fn main() { if matches.is_present("config") { let input = matches .get_one::("INPUT_FILE") - .expect("matches definition") - .or_else(|| { - matches - .get_one::("spec-in") - .expect("matches definition") - }) + .or_else(|| matches.get_one::("spec-in")) .unwrap_or_else(|| { cmd.error( ErrorKind::MissingRequiredArgument, @@ -93,11 +85,7 @@ fn main() { println!( "Doing work using input {} and config {}", input, - matches - .get_one::("config") - .expect("matches definition") - .unwrap() - .display() + matches.get_one::("config").unwrap().display() ); } } diff --git a/examples/tutorial_builder/05_01_assert.rs b/examples/tutorial_builder/05_01_assert.rs index 45a982fb2aa..d6f19ffe538 100644 --- a/examples/tutorial_builder/05_01_assert.rs +++ b/examples/tutorial_builder/05_01_assert.rs @@ -8,7 +8,6 @@ fn main() { // Note, it's safe to call unwrap() because the arg is required let port: usize = *matches .get_one::("PORT") - .expect("matches definition") .expect("'PORT' is required and parsing will fail if its missing"); println!("PORT = {}", port); } diff --git a/src/builder/arg.rs b/src/builder/arg.rs index 2013dd640c9..e76128d04d8 100644 --- a/src/builder/arg.rs +++ b/src/builder/arg.rs @@ -1042,15 +1042,15 @@ impl<'help> Arg<'help> { /// ).unwrap(); /// /// let color: &String = m.get_one("color") - /// .expect("matches definition").expect("default"); + /// .expect("default"); /// assert_eq!(color, "auto"); /// /// let hostname: &String = m.get_one("hostname") - /// .expect("matches definition").expect("required"); + /// .expect("required"); /// assert_eq!(hostname, "rust-lang.org"); /// /// let port: u16 = *m.get_one("port") - /// .expect("matches definition").expect("required"); + /// .expect("required"); /// assert_eq!(port, 3001); /// ``` pub fn value_parser(mut self, parser: impl Into) -> Self { diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs index f12731f2cc6..f1f4c0dda13 100644 --- a/src/builder/value_parser.rs +++ b/src/builder/value_parser.rs @@ -46,15 +46,15 @@ use crate::parser::AnyValueId; /// ).unwrap(); /// /// let color: &String = m.get_one("color") -/// .expect("matches definition").expect("default"); +/// .expect("default"); /// assert_eq!(color, "auto"); /// /// let hostname: &String = m.get_one("hostname") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(hostname, "rust-lang.org"); /// /// let port: u16 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 3001); /// ``` #[derive(Clone)] @@ -105,7 +105,7 @@ impl ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "key=value"]).unwrap(); /// let port: &EnvVar = m.get_one("env") - /// .expect("matches definition").expect("required"); + /// .expect("required"); /// assert_eq!(*port, ("key".into(), Some("value".into()))); /// ``` pub fn new(other: impl AnyValueParser + Send + Sync + 'static) -> Self { @@ -130,7 +130,7 @@ impl ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); /// let port: bool = *m.get_one("download") - /// .expect("matches definition").expect("required"); + /// .expect("required"); /// assert_eq!(port, true); /// /// assert!(cmd.try_get_matches_from_mut(["cmd", "forever"]).is_err()); @@ -156,7 +156,7 @@ impl ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "80"]).unwrap(); /// let port: &String = m.get_one("port") - /// .expect("matches definition").expect("required"); + /// .expect("required"); /// assert_eq!(port, "80"); /// ``` pub const fn string() -> Self { @@ -184,7 +184,7 @@ impl ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "hello.txt"]).unwrap(); /// let port: &PathBuf = m.get_one("output") - /// .expect("matches definition").expect("required"); + /// .expect("required"); /// assert_eq!(port, Path::new("hello.txt")); /// /// assert!(cmd.try_get_matches_from_mut(["cmd", ""]).is_err()); @@ -264,7 +264,7 @@ impl ValueParser { /// ).unwrap(); /// /// let hostname: &String = m.get_one("hostname") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(hostname, "rust-lang.org"); /// ``` impl From

for ValueParser { @@ -291,7 +291,7 @@ impl From

for ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); /// let port: i64 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 3001); /// ``` impl From> for ValueParser { @@ -319,7 +319,7 @@ impl From> for ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); /// let port: i64 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 3001); /// ``` impl From> for ValueParser { @@ -347,7 +347,7 @@ impl From> for ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); /// let port: i64 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 3001); /// ``` impl From> for ValueParser { @@ -375,7 +375,7 @@ impl From> for ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "80"]).unwrap(); /// let port: i64 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 80); /// ``` impl From> for ValueParser { @@ -403,7 +403,7 @@ impl From> for ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "80"]).unwrap(); /// let port: i64 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 80); /// ``` impl From> for ValueParser { @@ -431,7 +431,7 @@ impl From> for ValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); /// let port: i64 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 3001); /// ``` impl From for ValueParser { @@ -462,7 +462,7 @@ impl From for ValueParser { /// ).unwrap(); /// /// let color: &String = m.get_one("color") -/// .expect("matches definition").expect("default"); +/// .expect("default"); /// assert_eq!(color, "never"); /// ``` impl From<[P; C]> for ValueParser @@ -816,7 +816,7 @@ impl Default for PathBufValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "always"]).unwrap(); /// let port: ColorChoice = *m.get_one("color") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, ColorChoice::Always); /// /// // Semantics @@ -925,7 +925,7 @@ impl Default for ArgEnumValue /// /// let m = cmd.try_get_matches_from_mut(["cmd", "always"]).unwrap(); /// let port: &String = m.get_one("color") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, "always"); /// ``` /// @@ -1032,7 +1032,7 @@ where /// /// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); /// let port: u16 = *m.get_one("port") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, 3001); /// ``` /// @@ -1293,7 +1293,7 @@ impl Default for BoolValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); /// let port: bool = *m.get_one("append") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, true); /// ``` /// @@ -1386,7 +1386,7 @@ impl Default for FalseyValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); /// let port: bool = *m.get_one("append") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, true); /// ``` /// @@ -1484,7 +1484,7 @@ impl Default for BoolishValueParser { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); /// let port: &String = m.get_one("append") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, "true"); /// ``` /// @@ -1693,7 +1693,7 @@ pub mod via_prelude { /// /// let m = cmd.try_get_matches_from_mut(["cmd", "file.txt"]).unwrap(); /// let port: &PathBuf = m.get_one("output") -/// .expect("matches definition").expect("required"); +/// .expect("required"); /// assert_eq!(port, Path::new("file.txt")); /// ``` /// diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index 2642d90ee25..b5e8e3f8d8d 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -81,6 +81,7 @@ pub struct ArgMatches { pub(crate) subcommand: Option>, } +/// # Arguments impl ArgMatches { /// Gets the value of a specific option or positional argument. /// @@ -93,6 +94,11 @@ impl ArgMatches { /// *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. /// + /// # Panic + /// + /// If the argument definition and access mismatch. To handle this case programmatically, see + /// [`ArgMatches::try_get_one`]. + /// /// # Examples /// /// ```rust @@ -106,7 +112,6 @@ impl ArgMatches { /// /// let port: usize = *m /// .get_one("port") - /// .expect("`port` is a `usize`") /// .expect("`port`is required"); /// assert_eq!(port, 2020); /// ``` @@ -115,22 +120,10 @@ impl ArgMatches { /// [`ArgMatches::values_of`]: ArgMatches::values_of() /// [`default_value`]: crate::Arg::default_value() /// [`occurrences_of`]: crate::ArgMatches::occurrences_of() - pub fn get_one( - &self, - name: &str, - ) -> Result, MatchesError> { - let id = Id::from(name); - let arg = self.try_get_arg_t::(&id)?; - let value = match arg.and_then(|a| a.first()) { - Some(value) => value, - None => { - return Ok(None); - } - }; - Ok(value - .downcast_ref::() - .map(Some) - .expect(INTERNAL_ERROR_MSG)) // enforced by `try_get_arg_t` + #[track_caller] + pub fn get_one(&self, name: &str) -> Option<&T> { + self.try_get_one(name) + .expect("caller error: argument definition and access must match") } /// Iterate over values of a specific option or positional argument. @@ -141,6 +134,11 @@ impl ArgMatches { /// /// Returns `None` if the option wasn't present. /// + /// # Panic + /// + /// If the argument definition and access mismatch. To handle this case programmatically, see + /// [`ArgMatches::try_get_many`]. + /// /// # Examples /// /// ```rust @@ -156,7 +154,6 @@ impl ArgMatches { /// "myprog", "-p", "22", "-p", "80", "-p", "2020" /// ]); /// let vals: Vec = m.get_many("ports") - /// .expect("`port` is a `usize`") /// .expect("`port`is required") /// .copied() /// .collect(); @@ -165,20 +162,9 @@ impl ArgMatches { pub fn get_many( &self, name: &str, - ) -> Result>, MatchesError> { - let id = Id::from(name); - let arg = match self.try_get_arg(&id)? { - Some(arg) => arg, - None => return Ok(None), - }; - let len = arg.num_vals(); - let values = arg.vals_flatten(); - let values = ValuesRef { - // enforced by `try_get_arg_t` - iter: values.map(|v| v.downcast_ref::().expect(INTERNAL_ERROR_MSG)), - len, - }; - Ok(Some(values)) + ) -> Option> { + self.try_get_many(name) + .expect("caller error: argument definition and access must match") } /// Iterate over the original argument values. @@ -189,6 +175,11 @@ impl ArgMatches { /// /// Returns `None` if the option wasn't present. /// + /// # Panic + /// + /// If the argument definition and access mismatch. To handle this case programmatically, see + /// [`ArgMatches::try_get_raw`]. + /// /// # Examples /// #[cfg_attr(not(unix), doc = " ```ignore")] @@ -207,7 +198,6 @@ impl ArgMatches { /// OsString::from_vec(vec![0xe9, b'!'])]); /// /// let mut itr = m.get_raw("arg") - /// .expect("`port` is defined") /// .expect("`port`is required") /// .into_iter(); /// assert_eq!(itr.next(), Some(OsStr::new("Hi"))); @@ -218,19 +208,9 @@ impl ArgMatches { /// [`OsSt`]: std::ffi::OsStr /// [values]: OsValues /// [`String`]: std::string::String - pub fn get_raw(&self, id: T) -> Result>, MatchesError> { - let id = Id::from(id); - let arg = match self.try_get_arg(&id)? { - Some(arg) => arg, - None => return Ok(None), - }; - let len = arg.num_vals(); - let values = arg.raw_vals_flatten(); - let values = RawValues { - iter: values.map(OsString::as_os_str), - len, - }; - Ok(Some(values)) + pub fn get_raw(&self, id: T) -> Option> { + self.try_get_raw(id) + .expect("caller error: argument definition and access must match") } /// Returns the value of a specific option or positional argument. @@ -244,6 +224,11 @@ impl ArgMatches { /// *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. /// + /// # Panic + /// + /// If the argument definition and access mismatch. To handle this case programmatically, see + /// [`ArgMatches::try_remove_one`]. + /// /// # Examples /// /// ```rust @@ -256,7 +241,6 @@ impl ArgMatches { /// "myprog", "file.txt", /// ]); /// let vals: String = m.remove_one("file") - /// .expect("`file` is a `String`") /// .expect("`file`is required"); /// assert_eq!(vals, "file.txt"); /// ``` @@ -265,19 +249,9 @@ impl ArgMatches { /// [`ArgMatches::values_of`]: ArgMatches::values_of() /// [`default_value`]: crate::Arg::default_value() /// [`occurrences_of`]: crate::ArgMatches::occurrences_of() - pub fn remove_one( - &mut self, - name: &str, - ) -> Result, MatchesError> { - let id = Id::from(name); - match self.try_remove_arg_t::(&id)? { - Some(values) => Ok(values - .into_vals_flatten() - // enforced by `try_get_arg_t` - .map(|v| v.downcast_into::().expect(INTERNAL_ERROR_MSG)) - .next()), - None => Ok(None), - } + pub fn remove_one(&mut self, name: &str) -> Option { + self.try_remove_one(name) + .expect("caller error: argument definition and access must match") } /// Return values of a specific option or positional argument. @@ -288,6 +262,11 @@ impl ArgMatches { /// /// Returns `None` if the option wasn't present. /// + /// # Panic + /// + /// If the argument definition and access mismatch. To handle this case programmatically, see + /// [`ArgMatches::try_remove_many`]. + /// /// # Examples /// /// ```rust @@ -301,7 +280,6 @@ impl ArgMatches { /// "myprog", "file1.txt", "file2.txt", "file3.txt", "file4.txt", /// ]); /// let vals: Vec = m.remove_many("file") - /// .expect("`file` is a `String`") /// .expect("`file`is required") /// .collect(); /// assert_eq!(vals, ["file1.txt", "file2.txt", "file3.txt", "file4.txt"]); @@ -309,20 +287,9 @@ impl ArgMatches { pub fn remove_many( &mut self, name: &str, - ) -> Result>, MatchesError> { - let id = Id::from(name); - let arg = match self.try_remove_arg_t::(&id)? { - Some(arg) => arg, - None => return Ok(None), - }; - let len = arg.num_vals(); - let values = arg.into_vals_flatten(); - let values = Values2 { - // enforced by `try_get_arg_t` - iter: values.map(|v| v.downcast_into::().expect(INTERNAL_ERROR_MSG)), - len, - }; - Ok(Some(values)) + ) -> Option> { + self.try_remove_many(name) + .expect("caller error: argument definition and access must match") } /// Check if any args were present on the command line @@ -1196,6 +1163,28 @@ 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)] + pub fn is_valid_arg(&self, _id: impl Key) -> bool { + #[cfg(debug_assertions)] + { + let id = Id::from(_id); + self.disable_asserts || id == Id::empty_hash() || self.valid_args.contains(&id) + } + #[cfg(not(debug_assertions))] + { + true + } + } +} + +/// # Subcommands +impl ArgMatches { /// The name and `ArgMatches` of the current [subcommand]. /// /// Subcommand values are put in a child [`ArgMatches`] @@ -1294,7 +1283,6 @@ impl ArgMatches { /// match app_m.remove_subcommand() { /// Some((external, mut sub_m)) => { /// let ext_args: Vec = sub_m.remove_many("") - /// .expect("`file` is a `String`") /// .expect("`file`is required") /// .collect(); /// assert_eq!(external, "subcmd"); @@ -1377,25 +1365,6 @@ impl ArgMatches { self.subcommand.as_ref().map(|sc| &*sc.name) } - /// 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)] - pub fn is_valid_arg(&self, _id: impl Key) -> bool { - #[cfg(debug_assertions)] - { - let id = Id::from(_id); - self.disable_asserts || id == Id::empty_hash() || self.valid_args.contains(&id) - } - #[cfg(not(debug_assertions))] - { - true - } - } - /// Check if a subcommand can be queried /// /// By default, `ArgMatches` functions assert on undefined `Id`s to help catch programmer @@ -1416,6 +1385,100 @@ impl ArgMatches { } } +/// # Advanced +impl ArgMatches { + /// Non-panicking version of [`ArgMatches::get_one`] + pub fn try_get_one( + &self, + name: &str, + ) -> Result, MatchesError> { + let id = Id::from(name); + let arg = self.try_get_arg_t::(&id)?; + let value = match arg.and_then(|a| a.first()) { + Some(value) => value, + None => { + return Ok(None); + } + }; + Ok(value + .downcast_ref::() + .map(Some) + .expect(INTERNAL_ERROR_MSG)) // enforced by `try_get_arg_t` + } + + /// Non-panicking version of [`ArgMatches::get_many`] + pub fn try_get_many( + &self, + name: &str, + ) -> Result>, MatchesError> { + let id = Id::from(name); + let arg = match self.try_get_arg(&id)? { + Some(arg) => arg, + None => return Ok(None), + }; + let len = arg.num_vals(); + let values = arg.vals_flatten(); + let values = ValuesRef { + // enforced by `try_get_arg_t` + iter: values.map(|v| v.downcast_ref::().expect(INTERNAL_ERROR_MSG)), + len, + }; + Ok(Some(values)) + } + + /// Non-panicking version of [`ArgMatches::get_raw`] + pub fn try_get_raw(&self, id: T) -> Result>, MatchesError> { + let id = Id::from(id); + let arg = match self.try_get_arg(&id)? { + Some(arg) => arg, + None => return Ok(None), + }; + let len = arg.num_vals(); + let values = arg.raw_vals_flatten(); + let values = RawValues { + iter: values.map(OsString::as_os_str), + len, + }; + Ok(Some(values)) + } + + /// Non-panicking version of [`ArgMatches::remove_one`] + pub fn try_remove_one( + &mut self, + name: &str, + ) -> Result, MatchesError> { + let id = Id::from(name); + match self.try_remove_arg_t::(&id)? { + Some(values) => Ok(values + .into_vals_flatten() + // enforced by `try_get_arg_t` + .map(|v| v.downcast_into::().expect(INTERNAL_ERROR_MSG)) + .next()), + None => Ok(None), + } + } + + /// Non-panicking version of [`ArgMatches::remove_many`] + pub fn try_remove_many( + &mut self, + name: &str, + ) -> Result>, MatchesError> { + let id = Id::from(name); + let arg = match self.try_remove_arg_t::(&id)? { + Some(arg) => arg, + None => return Ok(None), + }; + let len = arg.num_vals(); + let values = arg.into_vals_flatten(); + let values = Values2 { + // enforced by `try_get_arg_t` + iter: values.map(|v| v.downcast_into::().expect(INTERNAL_ERROR_MSG)), + len, + }; + Ok(Some(values)) + } +} + // Private methods impl ArgMatches { #[inline] @@ -1573,7 +1636,6 @@ pub(crate) struct SubCommand { /// .get_matches_from(vec!["myapp", "-o", "val1", "-o", "val2"]); /// /// let mut values = m.remove_many::("output") -/// .unwrap() /// .unwrap(); /// /// assert_eq!(values.next(), Some(String::from("val1"))); @@ -1632,7 +1694,6 @@ impl Default for Values2 { /// /// let mut values = m.get_many::("output") /// .unwrap() -/// .unwrap() /// .map(|s| s.as_str()); /// /// assert_eq!(values.next(), Some("val1")); @@ -1695,7 +1756,6 @@ impl<'a, T: 'a> Default for ValuesRef<'a, T> { /// assert_eq!( /// &*m.get_raw("arg") /// .unwrap() -/// .unwrap() /// .next().unwrap() /// .as_bytes(), /// [b'H', b'i', b' ', 0xe9, b'!']