diff options
Diffstat (limited to '')
18 files changed, 1198 insertions, 0 deletions
diff --git a/vendor/clap/examples/tutorial_builder/01_quick.rs b/vendor/clap/examples/tutorial_builder/01_quick.rs new file mode 100644 index 000000000..61cc3432d --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/01_quick.rs @@ -0,0 +1,65 @@ +// Note: this requires the `cargo` feature + +use std::path::PathBuf; + +use clap::{arg, command, value_parser, ArgAction, Command}; + +fn main() { + let matches = command!() + .arg(arg!([name] "Optional name to operate on")) + .arg( + arg!( + -c --config <FILE> "Sets a custom config file" + ) + // We don't have syntax yet for optional options, so manually calling `required` + .required(false) + .value_parser(value_parser!(PathBuf)), + ) + .arg( + arg!( + -d --debug "Turn debugging information on" + ) + .action(ArgAction::Count), + ) + .subcommand( + Command::new("test") + .about("does testing things") + .arg(arg!(-l --list "lists test values").action(ArgAction::SetTrue)), + ) + .get_matches(); + + // You can check the value provided by positional arguments, or option arguments + if let Some(name) = matches.get_one::<String>("name") { + println!("Value for name: {}", name); + } + + if let Some(config_path) = matches.get_one::<PathBuf>("config") { + println!("Value for config: {}", config_path.display()); + } + + // You can see how many times a particular flag or argument occurred + // Note, only flags can have multiple occurrences + match matches + .get_one::<u8>("debug") + .expect("Count's are defaulted") + { + 0 => println!("Debug mode is off"), + 1 => println!("Debug mode is kind of on"), + 2 => println!("Debug mode is on"), + _ => println!("Don't be crazy"), + } + + // You can check for the existence of subcommands, and if found use their + // matches just as you would the top level cmd + if let Some(matches) = matches.subcommand_matches("test") { + // "$ myapp test" was run + if *matches.get_one::<bool>("list").expect("defaulted by clap") { + // "$ myapp test -l" was run + println!("Printing testing lists..."); + } else { + println!("Not printing testing lists..."); + } + } + + // Continued program logic goes here... +} diff --git a/vendor/clap/examples/tutorial_builder/02_app_settings.rs b/vendor/clap/examples/tutorial_builder/02_app_settings.rs new file mode 100644 index 000000000..7bbedd3eb --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/02_app_settings.rs @@ -0,0 +1,21 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command, AppSettings, ArgAction}; + +fn main() { + let matches = command!() + .global_setting(AppSettings::DeriveDisplayOrder) + .allow_negative_numbers(true) + .arg(arg!(--two <VALUE>).action(ArgAction::Set)) + .arg(arg!(--one <VALUE>).action(ArgAction::Set)) + .get_matches(); + + println!( + "two: {:?}", + matches.get_one::<String>("two").expect("required") + ); + println!( + "one: {:?}", + matches.get_one::<String>("one").expect("required") + ); +} diff --git a/vendor/clap/examples/tutorial_builder/02_apps.rs b/vendor/clap/examples/tutorial_builder/02_apps.rs new file mode 100644 index 000000000..db9da18f9 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/02_apps.rs @@ -0,0 +1,20 @@ +use clap::{arg, Command}; + +fn main() { + let matches = Command::new("MyApp") + .version("1.0") + .author("Kevin K. <kbknapp@gmail.com>") + .about("Does awesome things") + .arg(arg!(--two <VALUE>)) + .arg(arg!(--one <VALUE>)) + .get_matches(); + + println!( + "two: {:?}", + matches.get_one::<String>("two").expect("required") + ); + println!( + "one: {:?}", + matches.get_one::<String>("one").expect("required") + ); +} diff --git a/vendor/clap/examples/tutorial_builder/02_crate.rs b/vendor/clap/examples/tutorial_builder/02_crate.rs new file mode 100644 index 000000000..16b7e7ee0 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/02_crate.rs @@ -0,0 +1,19 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command}; + +fn main() { + let matches = command!() + .arg(arg!(--two <VALUE>)) + .arg(arg!(--one <VALUE>)) + .get_matches(); + + println!( + "two: {:?}", + matches.get_one::<String>("two").expect("required") + ); + println!( + "one: {:?}", + matches.get_one::<String>("one").expect("required") + ); +} diff --git a/vendor/clap/examples/tutorial_builder/03_01_flag_bool.rs b/vendor/clap/examples/tutorial_builder/03_01_flag_bool.rs new file mode 100644 index 000000000..41ecbb1d7 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/03_01_flag_bool.rs @@ -0,0 +1,21 @@ +// Note: this requires the `cargo` feature + +use clap::{command, Arg, ArgAction}; + +fn main() { + let matches = command!() + .arg( + Arg::new("verbose") + .short('v') + .long("verbose") + .action(ArgAction::SetTrue), + ) + .get_matches(); + + println!( + "verbose: {:?}", + *matches + .get_one::<bool>("verbose") + .expect("defaulted by clap") + ); +} diff --git a/vendor/clap/examples/tutorial_builder/03_01_flag_count.rs b/vendor/clap/examples/tutorial_builder/03_01_flag_count.rs new file mode 100644 index 000000000..764affbd8 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/03_01_flag_count.rs @@ -0,0 +1,16 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command, ArgAction}; + +fn main() { + let matches = command!() + .arg(arg!(-v - -verbose).action(ArgAction::Count)) + .get_matches(); + + println!( + "verbose: {:?}", + matches + .get_one::<u8>("verbose") + .expect("Count always defaulted") + ); +} diff --git a/vendor/clap/examples/tutorial_builder/03_02_option.rs b/vendor/clap/examples/tutorial_builder/03_02_option.rs new file mode 100644 index 000000000..80e2b9159 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/03_02_option.rs @@ -0,0 +1,11 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command}; + +fn main() { + let matches = command!() + .arg(arg!(-n --name <NAME>).required(false)) + .get_matches(); + + println!("name: {:?}", matches.get_one::<String>("name")); +} diff --git a/vendor/clap/examples/tutorial_builder/03_03_positional.rs b/vendor/clap/examples/tutorial_builder/03_03_positional.rs new file mode 100644 index 000000000..c6579409a --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/03_03_positional.rs @@ -0,0 +1,9 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command}; + +fn main() { + let matches = command!().arg(arg!([NAME])).get_matches(); + + println!("NAME: {:?}", matches.get_one::<String>("NAME")); +} diff --git a/vendor/clap/examples/tutorial_builder/03_04_subcommands.rs b/vendor/clap/examples/tutorial_builder/03_04_subcommands.rs new file mode 100644 index 000000000..1dd1cbf09 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/03_04_subcommands.rs @@ -0,0 +1,24 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command, Command}; + +fn main() { + let matches = command!() + .propagate_version(true) + .subcommand_required(true) + .arg_required_else_help(true) + .subcommand( + Command::new("add") + .about("Adds files to myapp") + .arg(arg!([NAME])), + ) + .get_matches(); + + match matches.subcommand() { + Some(("add", sub_matches)) => println!( + "'myapp add' was used, name is: {:?}", + sub_matches.get_one::<String>("NAME") + ), + _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"), + } +} diff --git a/vendor/clap/examples/tutorial_builder/03_05_default_values.rs b/vendor/clap/examples/tutorial_builder/03_05_default_values.rs new file mode 100644 index 000000000..c68e87973 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/03_05_default_values.rs @@ -0,0 +1,16 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command}; + +fn main() { + let matches = command!() + .arg(arg!([NAME]).default_value("alice")) + .get_matches(); + + println!( + "NAME: {:?}", + matches + .get_one::<String>("NAME") + .expect("default ensures there is always a value") + ); +} diff --git a/vendor/clap/examples/tutorial_builder/04_01_enum.rs b/vendor/clap/examples/tutorial_builder/04_01_enum.rs new file mode 100644 index 000000000..ad2177c23 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/04_01_enum.rs @@ -0,0 +1,32 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command, value_parser, ValueEnum}; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] +enum Mode { + Fast, + Slow, +} + +fn main() { + let matches = command!() + .arg( + arg!(<MODE>) + .help("What mode to run the program in") + .value_parser(value_parser!(Mode)), + ) + .get_matches(); + + // Note, it's safe to call unwrap() because the arg is required + match matches + .get_one::<Mode>("MODE") + .expect("'MODE' is required and parsing will fail if its missing") + { + Mode::Fast => { + println!("Hare"); + } + Mode::Slow => { + println!("Tortoise"); + } + } +} diff --git a/vendor/clap/examples/tutorial_builder/04_01_possible.rs b/vendor/clap/examples/tutorial_builder/04_01_possible.rs new file mode 100644 index 000000000..f7b0cfb34 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/04_01_possible.rs @@ -0,0 +1,28 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command}; + +fn main() { + let matches = command!() + .arg( + arg!(<MODE>) + .help("What mode to run the program in") + .value_parser(["fast", "slow"]), + ) + .get_matches(); + + // Note, it's safe to call unwrap() because the arg is required + match matches + .get_one::<String>("MODE") + .expect("'MODE' is required and parsing will fail if its missing") + .as_str() + { + "fast" => { + println!("Hare"); + } + "slow" => { + println!("Tortoise"); + } + _ => unreachable!(), + } +} diff --git a/vendor/clap/examples/tutorial_builder/04_02_parse.rs b/vendor/clap/examples/tutorial_builder/04_02_parse.rs new file mode 100644 index 000000000..c2f3cc533 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/04_02_parse.rs @@ -0,0 +1,19 @@ +// Note: this requires the `cargo` feature + +use clap::{arg, command, value_parser}; + +fn main() { + let matches = command!() + .arg( + arg!(<PORT>) + .help("Network port to use") + .value_parser(value_parser!(u16).range(1..)), + ) + .get_matches(); + + // Note, it's safe to call unwrap() because the arg is required + let port: u16 = *matches + .get_one::<u16>("PORT") + .expect("'PORT' is required and parsing will fail if its missing"); + println!("PORT = {}", port); +} diff --git a/vendor/clap/examples/tutorial_builder/04_02_validate.rs b/vendor/clap/examples/tutorial_builder/04_02_validate.rs new file mode 100644 index 000000000..e60018a46 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/04_02_validate.rs @@ -0,0 +1,38 @@ +// Note: this requires the `cargo` feature + +use std::ops::RangeInclusive; + +use clap::{arg, command}; + +fn main() { + let matches = command!() + .arg( + arg!(<PORT>) + .help("Network port to use") + .value_parser(port_in_range), + ) + .get_matches(); + + // Note, it's safe to call unwrap() because the arg is required + let port: u16 = *matches + .get_one::<u16>("PORT") + .expect("'PORT' is required and parsing will fail if its missing"); + println!("PORT = {}", port); +} + +const PORT_RANGE: RangeInclusive<usize> = 1..=65535; + +fn port_in_range(s: &str) -> Result<u16, String> { + let port: usize = s + .parse() + .map_err(|_| format!("`{}` isn't a port number", s))?; + if PORT_RANGE.contains(&port) { + Ok(port as u16) + } else { + Err(format!( + "Port not in range {}-{}", + PORT_RANGE.start(), + PORT_RANGE.end() + )) + } +} diff --git a/vendor/clap/examples/tutorial_builder/04_03_relations.rs b/vendor/clap/examples/tutorial_builder/04_03_relations.rs new file mode 100644 index 000000000..605e5b48e --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/04_03_relations.rs @@ -0,0 +1,82 @@ +// Note: this requires the `cargo` feature + +use std::path::PathBuf; + +use clap::{arg, command, value_parser, ArgAction, ArgGroup}; + +fn main() { + // Create application like normal + let matches = command!() + // Add the version arguments + .arg(arg!(--"set-ver" <VER> "set version manually").required(false)) + .arg(arg!(--major "auto inc major").action(ArgAction::SetTrue)) + .arg(arg!(--minor "auto inc minor").action(ArgAction::SetTrue)) + .arg(arg!(--patch "auto inc patch").action(ArgAction::SetTrue)) + // Create a group, make it required, and add the above arguments + .group( + ArgGroup::new("vers") + .required(true) + .args(&["set-ver", "major", "minor", "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") + .value_parser(value_parser!(PathBuf)) + .group("input"), + ) + .arg( + arg!(--"spec-in" <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 <CONFIG>) + .required(false) + .value_parser(value_parser!(PathBuf)) + .requires("input"), + ) + .get_matches(); + + // Let's assume the old version 1.2.3 + let mut major = 1; + let mut minor = 2; + let mut patch = 3; + + // See if --set-ver was used to set the version manually + let version = if let Some(ver) = matches.get_one::<String>("set-ver") { + ver.to_owned() + } else { + // Increment the one requested (in a real program, we'd reset the lower numbers) + let (maj, min, pat) = ( + *matches.get_one::<bool>("major").expect("defaulted by clap"), + *matches.get_one::<bool>("minor").expect("defaulted by clap"), + *matches.get_one::<bool>("patch").expect("defaulted by clap"), + ); + match (maj, min, pat) { + (true, _, _) => major += 1, + (_, true, _) => minor += 1, + (_, _, true) => patch += 1, + _ => unreachable!(), + }; + format!("{}.{}.{}", major, minor, patch) + }; + + println!("Version: {}", version); + + // Check for usage of -c + if matches.contains_id("config") { + let input = matches + .get_one::<PathBuf>("INPUT_FILE") + .unwrap_or_else(|| matches.get_one::<PathBuf>("spec-in").unwrap()) + .display(); + println!( + "Doing work using input {} and config {}", + input, + matches.get_one::<PathBuf>("config").unwrap().display() + ); + } +} diff --git a/vendor/clap/examples/tutorial_builder/04_04_custom.rs b/vendor/clap/examples/tutorial_builder/04_04_custom.rs new file mode 100644 index 000000000..3dc080505 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/04_04_custom.rs @@ -0,0 +1,93 @@ +// Note: this requires the `cargo` feature + +use std::path::PathBuf; + +use clap::{arg, command, value_parser, ArgAction, ErrorKind}; + +fn main() { + // Create application like normal + let mut cmd = command!() + // Add the version arguments + .arg(arg!(--"set-ver" <VER> "set version manually").required(false)) + .arg(arg!(--major "auto inc major").action(ArgAction::SetTrue)) + .arg(arg!(--minor "auto inc minor").action(ArgAction::SetTrue)) + .arg(arg!(--patch "auto inc patch").action(ArgAction::SetTrue)) + // 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").value_parser(value_parser!(PathBuf))) + .arg( + arg!(--"spec-in" <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 <CONFIG>) + .required(false) + .value_parser(value_parser!(PathBuf)), + ); + let matches = cmd.get_matches_mut(); + + // Let's assume the old version 1.2.3 + let mut major = 1; + let mut minor = 2; + let mut patch = 3; + + // See if --set-ver was used to set the version manually + let version = if let Some(ver) = matches.get_one::<String>("set-ver") { + if *matches.get_one::<bool>("major").expect("defaulted by clap") + || *matches.get_one::<bool>("minor").expect("defaulted by clap") + || *matches.get_one::<bool>("patch").expect("defaulted by clap") + { + cmd.error( + ErrorKind::ArgumentConflict, + "Can't do relative and absolute version change", + ) + .exit(); + } + ver.to_string() + } else { + // Increment the one requested (in a real program, we'd reset the lower numbers) + let (maj, min, pat) = ( + *matches.get_one::<bool>("major").expect("defaulted by clap"), + *matches.get_one::<bool>("minor").expect("defaulted by clap"), + *matches.get_one::<bool>("patch").expect("defaulted by clap"), + ); + match (maj, min, pat) { + (true, false, false) => major += 1, + (false, true, false) => minor += 1, + (false, false, true) => patch += 1, + _ => { + cmd.error( + ErrorKind::ArgumentConflict, + "Can only modify one version field", + ) + .exit(); + } + }; + format!("{}.{}.{}", major, minor, patch) + }; + + println!("Version: {}", version); + + // Check for usage of -c + if matches.contains_id("config") { + let input = matches + .get_one::<PathBuf>("INPUT_FILE") + .or_else(|| matches.get_one::<PathBuf>("spec-in")) + .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.get_one::<PathBuf>("config").unwrap().display() + ); + } +} diff --git a/vendor/clap/examples/tutorial_builder/05_01_assert.rs b/vendor/clap/examples/tutorial_builder/05_01_assert.rs new file mode 100644 index 000000000..d6f19ffe5 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/05_01_assert.rs @@ -0,0 +1,26 @@ +// Note: this requires the `cargo` feature + +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 + .get_one::<usize>("PORT") + .expect("'PORT' is required and parsing will fail if its missing"); + println!("PORT = {}", port); +} + +fn cmd() -> clap::Command<'static> { + command!().arg( + arg!(<PORT>) + .help("Network port to use") + .value_parser(value_parser!(usize)), + ) +} + +#[test] +fn verify_app() { + cmd().debug_assert(); +} diff --git a/vendor/clap/examples/tutorial_builder/README.md b/vendor/clap/examples/tutorial_builder/README.md new file mode 100644 index 000000000..945b01e72 --- /dev/null +++ b/vendor/clap/examples/tutorial_builder/README.md @@ -0,0 +1,658 @@ +# Tutorial + +*Jump to [derive tutorial](../tutorial_derive/README.md)* + +1. [Quick Start](#quick-start) +2. [Configuring the Parser](#configuring-the-parser) +3. [Adding Arguments](#adding-arguments) + 1. [Positionals](#positionals) + 2. [Options](#options) + 3. [Flags](#flags) + 4. [Subcommands](#subcommands) + 5. [Defaults](#defaults) +4. Validation + 1. [Enumerated values](#enumerated-values) + 2. [Validated values](#validated-values) + 3. [Argument Relations](#argument-relations) + 4. [Custom Validation](#custom-validation) +5. [Tips](#tips) +6. [Contributing](#contributing) + +## Quick Start + +You can create an application with several arguments using usage strings. + +[Example:](01_quick.rs) +```console +$ 01_quick --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 01_quick[EXE] [OPTIONS] [name] [SUBCOMMAND] + +ARGS: + <name> Optional name to operate on + +OPTIONS: + -c, --config <FILE> Sets a custom config file + -d, --debug Turn debugging information on + -h, --help Print help information + -V, --version Print version information + +SUBCOMMANDS: + help Print this message or the help of the given subcommand(s) + test does testing things + +``` + +By default, the program does nothing: +```console +$ 01_quick +Debug mode is off + +``` + +But you can mix and match the various features +```console +$ 01_quick -dd test +Debug mode is on +Not printing testing lists... + +``` + +## Configuring the Parser + +You use the `Command` the start building a parser. + +[Example:](02_apps.rs) +```console +$ 02_apps --help +MyApp 1.0 +Kevin K. <kbknapp@gmail.com> +Does awesome things + +USAGE: + 02_apps[EXE] --two <VALUE> --one <VALUE> + +OPTIONS: + -h, --help Print help information + --one <VALUE> + --two <VALUE> + -V, --version Print version information + +$ 02_apps --version +MyApp 1.0 + +``` + +You can use `command!()` to fill these fields in from your `Cargo.toml` +file. **This requires the `cargo` feature flag.** + +[Example:](02_crate.rs) +```console +$ 02_crate --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 02_crate[EXE] --two <VALUE> --one <VALUE> + +OPTIONS: + -h, --help Print help information + --one <VALUE> + --two <VALUE> + -V, --version Print version information + +$ 02_crate --version +clap [..] + +``` + +You can use `Command` methods to change the application level behavior of clap. + +[Example:](02_app_settings.rs) +```console +$ 02_app_settings --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 02_app_settings[EXE] --two <VALUE> --one <VALUE> + +OPTIONS: + --two <VALUE> + --one <VALUE> + -h, --help Print help information + -V, --version Print version information + +$ 02_app_settings --one -1 --one -3 --two 10 +two: "10" +one: "-3" + +``` + +## Adding Arguments + +### Positionals + +You can have users specify values by their position on the command-line: + +[Example:](03_03_positional.rs) +```console +$ 03_03_positional --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 03_03_positional[EXE] [NAME] + +ARGS: + <NAME> + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +$ 03_03_positional +NAME: None + +$ 03_03_positional bob +NAME: Some("bob") + +``` + +### Options + +You can name your arguments with a flag: +- Order doesn't matter +- They can be optional +- Intent is clearer + +[Example:](03_02_option.rs) +```console +$ 03_02_option --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 03_02_option[EXE] [OPTIONS] + +OPTIONS: + -h, --help Print help information + -n, --name <NAME> + -V, --version Print version information + +$ 03_02_option +name: None + +$ 03_02_option --name bob +name: Some("bob") + +$ 03_02_option --name=bob +name: Some("bob") + +$ 03_02_option -n bob +name: Some("bob") + +$ 03_02_option -n=bob +name: Some("bob") + +$ 03_02_option -nbob +name: Some("bob") + +``` + +### Flags + +Flags can also be switches that can be on/off: + +[Example:](03_01_flag_bool.rs) +```console +$ 03_01_flag_bool --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 03_01_flag_bool[EXE] [OPTIONS] + +OPTIONS: + -h, --help Print help information + -v, --verbose + -V, --version Print version information + +$ 03_01_flag_bool +verbose: false + +$ 03_01_flag_bool --verbose +verbose: true + +$ 03_01_flag_bool --verbose --verbose +verbose: true + +``` + +Or counted. + +[Example:](03_01_flag_count.rs) +```console +$ 03_01_flag_count --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 03_01_flag_count[EXE] [OPTIONS] + +OPTIONS: + -h, --help Print help information + -v, --verbose + -V, --version Print version information + +$ 03_01_flag_count +verbose: 0 + +$ 03_01_flag_count --verbose +verbose: 1 + +$ 03_01_flag_count --verbose --verbose +verbose: 2 + +``` + +### Subcommands + +Subcommands are defined as `Command`s that get added via `Command::subcommand`. Each +instance of a Subcommand can have its own version, author(s), Args, and even its own +subcommands. + +[Example:](03_04_subcommands.rs) +```console +$ 03_04_subcommands help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 03_04_subcommands[EXE] <SUBCOMMAND> + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +SUBCOMMANDS: + add Adds files to myapp + help Print this message or the help of the given subcommand(s) + +$ 03_04_subcommands help add +03_04_subcommands[EXE]-add [..] +Adds files to myapp + +USAGE: + 03_04_subcommands[EXE] add [NAME] + +ARGS: + <NAME> + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +$ 03_04_subcommands add bob +'myapp add' was used, name is: Some("bob") + +``` + +Because we set `Command::arg_required_else_help`: +```console +$ 03_04_subcommands +? failed +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 03_04_subcommands[EXE] <SUBCOMMAND> + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +SUBCOMMANDS: + add Adds files to myapp + help Print this message or the help of the given subcommand(s) + +``` + +Because we set `Command::propagate_version`: +```console +$ 03_04_subcommands --version +clap [..] + +$ 03_04_subcommands add --version +03_04_subcommands[EXE]-add [..] + +``` + +### Defaults + +We've previously showed that arguments can be `required` or optional. When +optional, you work with a `Option` and can `unwrap_or`. Alternatively, you can +set `Arg::default_value`. + +[Example:](03_05_default_values.rs) +```console +$ 03_05_default_values --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 03_05_default_values[EXE] [NAME] + +ARGS: + <NAME> [default: alice] + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +$ 03_05_default_values +NAME: "alice" + +$ 03_05_default_values bob +NAME: "bob" + +``` + +## Validation + +### Enumerated values + +If you have arguments of specific values you want to test for, you can use the +`PossibleValuesParser` or `Arg::value_parser(["val1", ...])` for short. + +This allows you specify the valid values for that argument. If the user does not use one of +those specific values, they will receive a graceful exit with error message informing them +of the mistake, and what the possible valid values are + +[Example:](04_01_possible.rs) +```console +$ 04_01_possible --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 04_01_possible[EXE] <MODE> + +ARGS: + <MODE> What mode to run the program in [possible values: fast, slow] + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +$ 04_01_possible fast +Hare + +$ 04_01_possible slow +Tortoise + +$ 04_01_possible medium +? failed +error: "medium" isn't a valid value for '<MODE>' + [possible values: fast, slow] + +For more information try --help + +``` + +When enabling the `derive` feature, you can use `ValueEnum` to take care of the boiler plate for you, giving the same results. + +[Example:](04_01_enum.rs) +```console +$ 04_01_enum --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 04_01_enum[EXE] <MODE> + +ARGS: + <MODE> What mode to run the program in [possible values: fast, slow] + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +$ 04_01_enum fast +Hare + +$ 04_01_enum slow +Tortoise + +$ 04_01_enum medium +? failed +error: "medium" isn't a valid value for '<MODE>' + [possible values: fast, slow] + +For more information try --help + +``` + +### Validated values + +More generally, you can validate and parse into any data type. + +[Example:](04_02_parse.rs) +```console +$ 04_02_parse --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 04_02_parse[EXE] <PORT> + +ARGS: + <PORT> Network port to use + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +$ 04_02_parse 22 +PORT = 22 + +$ 04_02_parse foobar +? failed +error: Invalid value "foobar" for '<PORT>': invalid digit found in string + +For more information try --help + +$ 04_02_parse_derive 0 +? failed +error: Invalid value "0" for '<PORT>': 0 is not in 1..=65535 + +For more information try --help + +``` + +A custom parser can be used to improve the error messages or provide additional validation: + +[Example:](04_02_validate.rs) +```console +$ 04_02_validate --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 04_02_validate[EXE] <PORT> + +ARGS: + <PORT> Network port to use + +OPTIONS: + -h, --help Print help information + -V, --version Print version information + +$ 04_02_validate 22 +PORT = 22 + +$ 04_02_validate foobar +? failed +error: Invalid value "foobar" for '<PORT>': `foobar` isn't a port number + +For more information try --help + +$ 04_02_validate 0 +? failed +error: Invalid value "0" for '<PORT>': Port not in range 1-65535 + +For more information try --help + +``` + +### Argument Relations + +You can declare dependencies or conflicts between `Arg`s or even `ArgGroup`s. + +`ArgGroup`s make it easier to declare relations instead of having to list each +individually, or when you want a rule to apply "any but not all" arguments. + +Perhaps the most common use of `ArgGroup`s is to require one and *only* one argument to be +present out of a given set. Imagine that you had multiple arguments, and you want one of them to +be required, but making all of them required isn't feasible because perhaps they conflict with +each other. + +[Example:](04_03_relations.rs) +```console +$ 04_03_relations --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 04_03_relations[EXE] [OPTIONS] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE] + +ARGS: + <INPUT_FILE> some regular input + +OPTIONS: + -c <CONFIG> + -h, --help Print help information + --major auto inc major + --minor auto inc minor + --patch auto inc patch + --set-ver <VER> set version manually + --spec-in <SPEC_IN> some special input argument + -V, --version Print version information + +$ 04_03_relations +? failed +error: The following required arguments were not provided: + <--set-ver <VER>|--major|--minor|--patch> + +USAGE: + 04_03_relations[EXE] [OPTIONS] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE] + +For more information try --help + +$ 04_03_relations --major +Version: 2.2.3 + +$ 04_03_relations --major --minor +? failed +error: The argument '--major' cannot be used with '--minor' + +USAGE: + 04_03_relations[EXE] <--set-ver <VER>|--major|--minor|--patch> + +For more information try --help + +$ 04_03_relations --major -c config.toml +? failed +error: The following required arguments were not provided: + <INPUT_FILE|--spec-in <SPEC_IN>> + +USAGE: + 04_03_relations[EXE] -c <CONFIG> <--set-ver <VER>|--major|--minor|--patch> <INPUT_FILE|--spec-in <SPEC_IN>> + +For more information try --help + +$ 04_03_relations --major -c config.toml --spec-in input.txt +Version: 2.2.3 +Doing work using input input.txt and config config.toml + +``` + +### Custom Validation + +As a last resort, you can create custom errors with the basics of clap's formatting. + +[Example:](04_04_custom.rs) +```console +$ 04_04_custom --help +clap [..] +A simple to use, efficient, and full-featured Command Line Argument Parser + +USAGE: + 04_04_custom[EXE] [OPTIONS] [INPUT_FILE] + +ARGS: + <INPUT_FILE> some regular input + +OPTIONS: + -c <CONFIG> + -h, --help Print help information + --major auto inc major + --minor auto inc minor + --patch auto inc patch + --set-ver <VER> set version manually + --spec-in <SPEC_IN> some special input argument + -V, --version Print version information + +$ 04_04_custom +? failed +error: Can only modify one version field + +USAGE: + 04_04_custom[EXE] [OPTIONS] [INPUT_FILE] + +For more information try --help + +$ 04_04_custom --major +Version: 2.2.3 + +$ 04_04_custom --major --minor +? failed +error: Can only modify one version field + +USAGE: + 04_04_custom[EXE] [OPTIONS] [INPUT_FILE] + +For more information try --help + +$ 04_04_custom --major -c config.toml +? failed +Version: 2.2.3 +error: INPUT_FILE or --spec-in is required when using --config + +USAGE: + 04_04_custom[EXE] [OPTIONS] [INPUT_FILE] + +For more information try --help + +$ 04_04_custom --major -c config.toml --spec-in input.txt +Version: 2.2.3 +Doing work using input input.txt and config config.toml + +``` + +## Tips + +- For more complex demonstration of features, see our [examples](../README.md). +- Proactively check for bad `Command` configurations by calling `Command::debug_assert` in a test ([example](05_01_assert.rs)) + +## Contributing + +New example code: +- Please update the corresponding section in the [derive tutorial](../tutorial_derive/README.md) +- Building: They must be added to [Cargo.toml](../../Cargo.toml) with the appropriate `required-features`. +- Testing: Ensure there is a markdown file with [trycmd](https://docs.rs/trycmd) syntax (generally they'll go in here). + +See also the general [CONTRIBUTING](../../CONTRIBUTING.md). |