diff --git a/examples/cargo-example.md b/examples/cargo-example.md index 9279cc49..bf7de9ea 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 -None +Ok(None) $ cargo-example example --manifest-path Cargo.toml -Some("Cargo.toml") +Ok(Some("Cargo.toml")) ``` diff --git a/examples/cargo-example.rs b/examples/cargo-example.rs index 149bf599..45ae67c8 100644 --- a/examples/cargo-example.rs +++ b/examples/cargo-example.rs @@ -8,7 +8,7 @@ fn main() { clap::command!("example").arg( clap::arg!(--"manifest-path" ) .required(false) - .allow_invalid_utf8(true), + .value_parser(clap::value_parser!(std::path::PathBuf)), ), ); let matches = cmd.get_matches(); @@ -16,8 +16,6 @@ fn main() { Some(("example", matches)) => matches, _ => unreachable!("clap should ensure we don't get here"), }; - let manifest_path = matches - .value_of_os("manifest-path") - .map(std::path::PathBuf::from); + let manifest_path = matches.get_one::("manifest-path"); println!("{:?}", manifest_path); } diff --git a/examples/derive_ref/README.md b/examples/derive_ref/README.md index 2cde95ff..b3e16690 100644 --- a/examples/derive_ref/README.md +++ b/examples/derive_ref/README.md @@ -274,16 +274,16 @@ Notes: - Implies `arg.takes_value(true).allow_invalid_utf8(true)` - `from_occurrences`: - Implies `arg.takes_value(false).multiple_occurrences(true)` - - Reads from `clap::ArgMatches::occurrences_of` rather than a `value_of` function + - Reads from `clap::ArgMatches::occurrences_of` rather than a `get_one` function - Note: operations on values, like `default_value`, are unlikely to do what you want - `from_flag` - Implies `arg.takes_value(false)` - - Reads from `clap::ArgMatches::is_present` rather than a `value_of` function + - Reads from `clap::ArgMatches::is_present` rather than a `get_one` function - Note: operations on values, like `default_value`, are unlikely to do what you want **Warning:** -- To support non-UTF8 paths, you must use `parse(from_os_str)`, otherwise - `clap` will use `clap::ArgMatches::value_of` with `PathBuf::FromStr`. +- To support non-UTF8 paths, you should use `#[clap(value_parser)]` otherwise + `clap` will parse it as a `String` which will fail on some paths. ## Doc Comments diff --git a/examples/escaped-positional.rs b/examples/escaped-positional.rs index f6d61bd9..dc0a013d 100644 --- a/examples/escaped-positional.rs +++ b/examples/escaped-positional.rs @@ -1,26 +1,44 @@ // Note: this requires the `cargo` feature -use clap::{arg, command}; +use clap::{arg, command, value_parser}; fn main() { let matches = command!() .arg(arg!(eff: -f)) - .arg(arg!(pea: -p ).required(false)) .arg( - arg!(slop: [SLOP]).multiple_occurrences(true).last(true), // Indicates that `slop` is only accessible after `--`. + arg!(pea: -p ) + .required(false) + .value_parser(value_parser!(String)), + ) + .arg( + // Indicates that `slop` is only accessible after `--`. + arg!(slop: [SLOP]) + .multiple_occurrences(true) + .last(true) + .value_parser(value_parser!(String)), ) .get_matches(); // This is what will happen with `myprog -f -p=bob -- sloppy slop slop`... - println!("-f used: {:?}", matches.is_present("eff")); // -f used: true - println!("-p's value: {:?}", matches.value_of("pea")); // -p's value: Some("bob") + + // -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") + ); + // 'slops' values: Some(["sloppy", "slop", "slop"]) println!( "'slops' values: {:?}", matches - .values_of("slop") + .get_many::("slop") + .expect("matches definition") .map(|vals| vals.collect::>()) .unwrap_or_default() - ); // 'slops' values: Some(["sloppy", "slop", "slop"]) + ); // Continued program logic goes here... } diff --git a/examples/git.rs b/examples/git.rs index 1ced54a9..d410ee43 100644 --- a/examples/git.rs +++ b/examples/git.rs @@ -1,5 +1,6 @@ // Note: this requires the `cargo` feature +use std::ffi::OsString; use std::path::PathBuf; use clap::{arg, Command}; @@ -27,7 +28,7 @@ fn cli() -> Command<'static> { Command::new("add") .about("adds things") .arg_required_else_help(true) - .arg(arg!( ... "Stuff to add").allow_invalid_utf8(true)), + .arg(arg!( ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))), ) .subcommand( Command::new("stash") @@ -50,20 +51,27 @@ fn main() { Some(("clone", sub_matches)) => { println!( "Cloning {}", - sub_matches.value_of("REMOTE").expect("required") + sub_matches + .get_one::("REMOTE") + .expect("matches definition") + .expect("required") ); } Some(("push", sub_matches)) => { println!( "Pushing to {}", - sub_matches.value_of("REMOTE").expect("required") + sub_matches + .get_one::("REMOTE") + .expect("matches definition") + .expect("required") ); } Some(("add", sub_matches)) => { let paths = sub_matches - .values_of_os("PATH") - .unwrap_or_default() - .map(PathBuf::from) + .get_many::("PATH") + .expect("matches definition") + .into_iter() + .flatten() .collect::>(); println!("Adding {:?}", paths); } @@ -71,15 +79,21 @@ fn main() { let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches)); match stash_command { ("apply", sub_matches) => { - let stash = sub_matches.value_of("STASH"); + let stash = sub_matches + .get_one::("STASH") + .expect("matches definition"); println!("Applying {:?}", stash); } ("pop", sub_matches) => { - let stash = sub_matches.value_of("STASH"); + let stash = sub_matches + .get_one::("STASH") + .expect("matches definition"); println!("Popping {:?}", stash); } ("push", sub_matches) => { - let message = sub_matches.value_of("message"); + let message = sub_matches + .get_one::("message") + .expect("matches definition"); println!("Pushing {:?}", message); } (name, _) => { @@ -89,8 +103,10 @@ fn main() { } Some((ext, sub_matches)) => { let args = sub_matches - .values_of_os("") - .unwrap_or_default() + .get_many::("") + .expect("matches definition") + .into_iter() + .flatten() .collect::>(); println!("Calling out to {:?} with {:?}", ext, args); } diff --git a/examples/multicall-busybox.rs b/examples/multicall-busybox.rs index f9d67867..ec0d7600 100644 --- a/examples/multicall-busybox.rs +++ b/examples/multicall-busybox.rs @@ -1,6 +1,7 @@ +use std::path::PathBuf; use std::process::exit; -use clap::{Arg, Command}; +use clap::{value_parser, Arg, Command}; fn applet_commands() -> [Command<'static>; 2] { [ @@ -24,6 +25,7 @@ fn main() { .exclusive(true) .takes_value(true) .default_missing_value("/usr/local/bin") + .value_parser(value_parser!(PathBuf)) .use_value_delimiter(false), ) .subcommands(applet_commands()), diff --git a/examples/pacman.rs b/examples/pacman.rs index c088a8fe..974f1cb1 100644 --- a/examples/pacman.rs +++ b/examples/pacman.rs @@ -71,13 +71,23 @@ fn main() { match matches.subcommand() { Some(("sync", sync_matches)) => { if sync_matches.is_present("search") { - let packages: Vec<_> = sync_matches.values_of("search").unwrap().collect(); + let packages: Vec<_> = sync_matches + .get_many::("search") + .expect("matches definition") + .expect("is present") + .map(|s| s.as_str()) + .collect(); let values = packages.join(", "); println!("Searching for {}...", values); return; } - let packages: Vec<_> = sync_matches.values_of("package").unwrap().collect(); + let packages: Vec<_> = sync_matches + .get_many::("package") + .expect("matches definition") + .expect("is present") + .map(|s| s.as_str()) + .collect(); let values = packages.join(", "); if sync_matches.is_present("info") { @@ -87,11 +97,17 @@ fn main() { } } Some(("query", query_matches)) => { - if let Some(packages) = query_matches.values_of("info") { - let comma_sep = packages.collect::>().join(", "); + if let Some(packages) = query_matches + .get_many::("info") + .expect("matches definition") + { + let comma_sep = packages.map(|s| s.as_str()).collect::>().join(", "); println!("Retrieving info for {}...", comma_sep); - } else if let Some(queries) = query_matches.values_of("search") { - let comma_sep = queries.collect::>().join(", "); + } else if let Some(queries) = query_matches + .get_many::("search") + .expect("matches definition") + { + let comma_sep = queries.map(|s| s.as_str()).collect::>().join(", "); println!("Searching Locally for {}...", comma_sep); } else { println!("Displaying all locally installed packages..."); diff --git a/examples/tutorial_builder/01_quick.rs b/examples/tutorial_builder/01_quick.rs index 7ab5081d..45ae9ec2 100644 --- a/examples/tutorial_builder/01_quick.rs +++ b/examples/tutorial_builder/01_quick.rs @@ -1,7 +1,8 @@ // Note: this requires the `cargo` feature -use clap::{arg, command, Command}; -use std::path::Path; +use std::path::PathBuf; + +use clap::{arg, command, value_parser, Command}; fn main() { let matches = command!() @@ -12,8 +13,7 @@ fn main() { ) // We don't have syntax yet for optional options, so manually calling `required` .required(false) - // Support non-UTF8 paths - .allow_invalid_utf8(true), + .value_parser(value_parser!(PathBuf)), ) .arg(arg!( -d --debug ... "Turn debugging information on" @@ -26,12 +26,17 @@ fn main() { .get_matches(); // You can check the value provided by positional arguments, or option arguments - if let Some(name) = matches.value_of("name") { + if let Some(name) = matches + .get_one::("name") + .expect("matches definition") + { println!("Value for name: {}", name); } - if let Some(raw_config) = matches.value_of_os("config") { - let config_path = Path::new(raw_config); + if let Some(config_path) = matches + .get_one::("config") + .expect("matches definition") + { 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 3485f588..41cbeb74 100644 --- a/examples/tutorial_builder/02_app_settings.rs +++ b/examples/tutorial_builder/02_app_settings.rs @@ -11,6 +11,18 @@ fn main() { .arg(arg!(--one )) .get_matches(); - println!("two: {:?}", matches.value_of("two").expect("required")); - println!("one: {:?}", matches.value_of("one").expect("required")); + println!( + "two: {:?}", + matches + .get_one::("two") + .expect("matches definition") + .expect("required") + ); + println!( + "one: {:?}", + matches + .get_one::("one") + .expect("matches definition") + .expect("required") + ); } diff --git a/examples/tutorial_builder/02_apps.rs b/examples/tutorial_builder/02_apps.rs index c9422d64..da9baf58 100644 --- a/examples/tutorial_builder/02_apps.rs +++ b/examples/tutorial_builder/02_apps.rs @@ -9,6 +9,18 @@ fn main() { .arg(arg!(--one )) .get_matches(); - println!("two: {:?}", matches.value_of("two").expect("required")); - println!("one: {:?}", matches.value_of("one").expect("required")); + println!( + "two: {:?}", + matches + .get_one::("two") + .expect("matches definition") + .expect("required") + ); + println!( + "one: {:?}", + matches + .get_one::("one") + .expect("matches definition") + .expect("required") + ); } diff --git a/examples/tutorial_builder/02_crate.rs b/examples/tutorial_builder/02_crate.rs index df214f3f..6b8ecaae 100644 --- a/examples/tutorial_builder/02_crate.rs +++ b/examples/tutorial_builder/02_crate.rs @@ -8,6 +8,18 @@ fn main() { .arg(arg!(--one )) .get_matches(); - println!("two: {:?}", matches.value_of("two").expect("required")); - println!("one: {:?}", matches.value_of("one").expect("required")); + println!( + "two: {:?}", + matches + .get_one::("two") + .expect("matches definition") + .expect("required") + ); + println!( + "one: {:?}", + matches + .get_one::("one") + .expect("matches definition") + .expect("required") + ); } diff --git a/examples/tutorial_builder/03_02_option.rs b/examples/tutorial_builder/03_02_option.rs index 29ad60a9..bd8f351a 100644 --- a/examples/tutorial_builder/03_02_option.rs +++ b/examples/tutorial_builder/03_02_option.rs @@ -7,5 +7,10 @@ fn main() { .arg(arg!(-n --name ).required(false)) .get_matches(); - println!("name: {:?}", matches.value_of("name")); + println!( + "name: {:?}", + matches + .get_one::("name") + .expect("matches definition") + ); } diff --git a/examples/tutorial_builder/03_03_positional.rs b/examples/tutorial_builder/03_03_positional.rs index 03bfab8e..5024319e 100644 --- a/examples/tutorial_builder/03_03_positional.rs +++ b/examples/tutorial_builder/03_03_positional.rs @@ -5,5 +5,10 @@ use clap::{arg, command}; fn main() { let matches = command!().arg(arg!([NAME])).get_matches(); - println!("NAME: {:?}", matches.value_of("NAME")); + println!( + "NAME: {:?}", + matches + .get_one::("NAME") + .expect("matches definition") + ); } diff --git a/examples/tutorial_builder/03_04_subcommands.rs b/examples/tutorial_builder/03_04_subcommands.rs index 1ab79e71..95a51212 100644 --- a/examples/tutorial_builder/03_04_subcommands.rs +++ b/examples/tutorial_builder/03_04_subcommands.rs @@ -17,7 +17,9 @@ fn main() { match matches.subcommand() { Some(("add", sub_matches)) => println!( "'myapp add' was used, name is: {:?}", - sub_matches.value_of("NAME") + sub_matches + .get_one::("NAME") + .expect("matches definition") ), _ => 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 f88e3953..a49b01d6 100644 --- a/examples/tutorial_builder/03_05_default_values.rs +++ b/examples/tutorial_builder/03_05_default_values.rs @@ -10,7 +10,8 @@ fn main() { println!( "NAME: {:?}", matches - .value_of("NAME") + .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 128b3cdc..a788e326 100644 --- a/examples/tutorial_builder/04_01_enum.rs +++ b/examples/tutorial_builder/04_01_enum.rs @@ -1,6 +1,6 @@ // Note: this requires the `cargo` feature -use clap::{arg, command, ArgEnum, PossibleValue}; +use clap::{arg, command, value_parser, ArgEnum}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ArgEnum)] enum Mode { @@ -8,48 +8,19 @@ enum Mode { Slow, } -impl Mode { - pub fn possible_values() -> impl Iterator> { - Mode::value_variants() - .iter() - .filter_map(ArgEnum::to_possible_value) - } -} - -impl std::fmt::Display for Mode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.to_possible_value() - .expect("no values are skipped") - .get_name() - .fmt(f) - } -} - -impl std::str::FromStr for Mode { - type Err = String; - - fn from_str(s: &str) -> Result { - for variant in Self::value_variants() { - if variant.to_possible_value().unwrap().matches(s, false) { - return Ok(*variant); - } - } - Err(format!("Invalid variant: {}", s)) - } -} - fn main() { let matches = command!() .arg( arg!() .help("What mode to run the program in") - .possible_values(Mode::possible_values()), + .value_parser(value_parser!(Mode)), ) .get_matches(); // Note, it's safe to call unwrap() because the arg is required match matches - .value_of_t("MODE") + .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 77160392..889bc78e 100644 --- a/examples/tutorial_builder/04_01_possible.rs +++ b/examples/tutorial_builder/04_01_possible.rs @@ -7,14 +7,16 @@ fn main() { .arg( arg!() .help("What mode to run the program in") - .possible_values(["fast", "slow"]), + .value_parser(["fast", "slow"]), ) .get_matches(); // Note, it's safe to call unwrap() because the arg is required match matches - .value_of("MODE") + .get_one::("MODE") + .expect("matches definition") .expect("'MODE' is required and parsing will fail if its missing") + .as_str() { "fast" => { println!("Hare"); diff --git a/examples/tutorial_builder/04_02_parse.rs b/examples/tutorial_builder/04_02_parse.rs index e354af3a..3cca7924 100644 --- a/examples/tutorial_builder/04_02_parse.rs +++ b/examples/tutorial_builder/04_02_parse.rs @@ -1,19 +1,20 @@ // Note: this requires the `cargo` feature -use clap::{arg, command}; +use clap::{arg, command, value_parser}; fn main() { let matches = command!() .arg( arg!() .help("Network port to use") - .validator(|s| s.parse::()), + .value_parser(value_parser!(u16).range(1..)), ) .get_matches(); // Note, it's safe to call unwrap() because the arg is required - let port: usize = matches - .value_of_t("PORT") + 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 a49f869e..df53f285 100644 --- a/examples/tutorial_builder/04_02_validate.rs +++ b/examples/tutorial_builder/04_02_validate.rs @@ -9,25 +9,26 @@ fn main() { .arg( arg!() .help("Network port to use") - .validator(port_in_range), + .value_parser(port_in_range), ) .get_matches(); // Note, it's safe to call unwrap() because the arg is required - let port: usize = matches - .value_of_t("PORT") + let port: u16 = *matches + .get_one::("PORT") + .expect("matches definition") .expect("'PORT' is required and parsing will fail if its missing"); println!("PORT = {}", port); } const PORT_RANGE: RangeInclusive = 1..=65535; -fn port_in_range(s: &str) -> Result<(), String> { +fn port_in_range(s: &str) -> Result { let port: usize = s .parse() .map_err(|_| format!("`{}` isn't a port number", s))?; if PORT_RANGE.contains(&port) { - Ok(()) + Ok(port as u16) } else { Err(format!( "Port not in range {}-{}", diff --git a/examples/tutorial_builder/04_03_relations.rs b/examples/tutorial_builder/04_03_relations.rs index 495bf365..2f9108eb 100644 --- a/examples/tutorial_builder/04_03_relations.rs +++ b/examples/tutorial_builder/04_03_relations.rs @@ -1,6 +1,8 @@ // Note: this requires the `cargo` feature -use clap::{arg, command, ArgGroup}; +use std::path::PathBuf; + +use clap::{arg, command, value_parser, ArgGroup}; fn main() { // Create application like normal @@ -18,15 +20,25 @@ fn main() { ) // Arguments can also be added to a group individually, these two arguments // are part of the "input" group which is not required - .arg(arg!([INPUT_FILE] "some regular input").group("input")) + .arg( + arg!([INPUT_FILE] "some regular input") + .value_parser(value_parser!(PathBuf)) + .group("input"), + ) .arg( arg!(--"spec-in" "some special input argument") .required(false) + .value_parser(value_parser!(PathBuf)) .group("input"), ) // Now let's assume we have a -c [config] argument which requires one of // (but **not** both) the "input" arguments - .arg(arg!(config: -c ).required(false).requires("input")) + .arg( + arg!(config: -c ) + .required(false) + .value_parser(value_parser!(PathBuf)) + .requires("input"), + ) .get_matches(); // Let's assume the old version 1.2.3 @@ -35,8 +47,11 @@ fn main() { let mut patch = 3; // See if --set-ver was used to set the version manually - let version = if let Some(ver) = matches.value_of("set-ver") { - ver.to_string() + let version = if let Some(ver) = matches + .get_one::("set-ver") + .expect("matches definition") + { + ver.to_owned() } else { // Increment the one requested (in a real program, we'd reset the lower numbers) let (maj, min, pat) = ( @@ -58,12 +73,23 @@ fn main() { // Check for usage of -c if matches.is_present("config") { let input = matches - .value_of("INPUT_FILE") - .unwrap_or_else(|| matches.value_of("spec-in").unwrap()); + .get_one::("INPUT_FILE") + .expect("matches definition") + .unwrap_or_else(|| { + matches + .get_one::("spec-in") + .expect("matches definition") + .unwrap() + }) + .display(); println!( "Doing work using input {} and config {}", input, - matches.value_of("config").unwrap() + matches + .get_one::("config") + .expect("matches definition") + .unwrap() + .display() ); } } diff --git a/examples/tutorial_builder/04_04_custom.rs b/examples/tutorial_builder/04_04_custom.rs index 6993329d..4767ae68 100644 --- a/examples/tutorial_builder/04_04_custom.rs +++ b/examples/tutorial_builder/04_04_custom.rs @@ -1,6 +1,8 @@ // Note: this requires the `cargo` feature -use clap::{arg, command, ErrorKind}; +use std::path::PathBuf; + +use clap::{arg, command, value_parser, ErrorKind}; fn main() { // Create application like normal @@ -12,11 +14,19 @@ fn main() { .arg(arg!(--patch "auto inc patch")) // Arguments can also be added to a group individually, these two arguments // are part of the "input" group which is not required - .arg(arg!([INPUT_FILE] "some regular input")) - .arg(arg!(--"spec-in" "some special input argument").required(false)) + .arg(arg!([INPUT_FILE] "some regular input").value_parser(value_parser!(PathBuf))) + .arg( + arg!(--"spec-in" "some special input argument") + .required(false) + .value_parser(value_parser!(PathBuf)), + ) // Now let's assume we have a -c [config] argument which requires one of // (but **not** both) the "input" arguments - .arg(arg!(config: -c ).required(false)); + .arg( + arg!(config: -c ) + .required(false) + .value_parser(value_parser!(PathBuf)), + ); let matches = cmd.get_matches_mut(); // Let's assume the old version 1.2.3 @@ -25,7 +35,10 @@ fn main() { let mut patch = 3; // See if --set-ver was used to set the version manually - let version = if let Some(ver) = matches.value_of("set-ver") { + let version = if let Some(ver) = matches + .get_one::("set-ver") + .expect("matches definition") + { if matches.is_present("major") || matches.is_present("minor") || matches.is_present("patch") { cmd.error( @@ -62,19 +75,29 @@ fn main() { // Check for usage of -c if matches.is_present("config") { let input = matches - .value_of("INPUT_FILE") - .or_else(|| matches.value_of("spec-in")) + .get_one::("INPUT_FILE") + .expect("matches definition") + .or_else(|| { + matches + .get_one::("spec-in") + .expect("matches definition") + }) .unwrap_or_else(|| { cmd.error( ErrorKind::MissingRequiredArgument, "INPUT_FILE or --spec-in is required when using --config", ) .exit() - }); + }) + .display(); println!( "Doing work using input {} and config {}", input, - matches.value_of("config").unwrap() + matches + .get_one::("config") + .expect("matches definition") + .unwrap() + .display() ); } } diff --git a/examples/tutorial_builder/05_01_assert.rs b/examples/tutorial_builder/05_01_assert.rs index f40f6ebd..45a982fb 100644 --- a/examples/tutorial_builder/05_01_assert.rs +++ b/examples/tutorial_builder/05_01_assert.rs @@ -1,13 +1,14 @@ // Note: this requires the `cargo` feature -use clap::{arg, command}; +use clap::{arg, command, value_parser}; fn main() { let matches = cmd().get_matches(); // Note, it's safe to call unwrap() because the arg is required - let port: usize = matches - .value_of_t("PORT") + let port: usize = *matches + .get_one::("PORT") + .expect("matches definition") .expect("'PORT' is required and parsing will fail if its missing"); println!("PORT = {}", port); } @@ -16,7 +17,7 @@ fn cmd() -> clap::Command<'static> { command!().arg( arg!() .help("Network port to use") - .validator(|s| s.parse::()), + .value_parser(value_parser!(usize)), ) } diff --git a/examples/tutorial_builder/README.md b/examples/tutorial_builder/README.md index 0820c535..b0012fb1 100644 --- a/examples/tutorial_builder/README.md +++ b/examples/tutorial_builder/README.md @@ -444,7 +444,7 @@ For more information try --help ### Validated values -More generally, you can parse into any data type. +More generally, you can validate and parse into any data type. [Example:](04_02_parse.rs) ```console @@ -471,9 +471,15 @@ error: Invalid value "foobar" for '': invalid digit found in string For more information try --help +$ 04_02_parse_derive 0 +? failed +error: Invalid value "0" for '': 0 is not in 1..=65535 + +For more information try --help + ``` -A custom validator can be used to improve the error messages or provide additional validation: +A custom parser can be used to improve the error messages or provide additional validation: [Example:](04_02_validate.rs) ```console