diff --git a/src/cli/arguments/clap-basic.md b/src/cli/arguments/clap-basic.md index 0dbcafa1..bcce1dd9 100644 --- a/src/cli/arguments/clap-basic.md +++ b/src/cli/arguments/clap-basic.md @@ -6,39 +6,55 @@ This application describes the structure of its command-line interface using `clap`'s builder style. The [documentation] gives two other possible ways to instantiate an application. -In the builder style, `with_name` is the unique identifier that `value_of` will -use to retrieve the value passed. The `short` and `long` options control the +The code here requires `clap` version 4. Use `clap = "4"` in +your `Cargo.toml` to get the correct version. + +In the builder style, each possible argument is described by an `Arg` +struct. The string given to `Arg::new()` is the internal +name of the argument. The `short` and `long` options control the flag the user will be expected to type; short flags look like `-f` and long flags look like `--file`. +The `get_one()` method is used to get an argument's value. +It returns `Some(&`value`)` if the argument was supplied by +the user, else `None`. + +The use of `PathBuf` is to allow file paths which are legal +in Linux and MacOS, but not in Rust UTF-8 strings. This is +best practice: one encounters such paths quite rarely in +practice, but when it happens it is really frustrating +without this. + ```rust,edition2018 -use clap::{Arg, App}; +use std::path::PathBuf; + +use clap::{Arg, Command, builder::PathBufValueParser}; fn main() { - let matches = App::new("My Test Program") + let matches = Command::new("My Test Program") .version("0.1.0") - .author("Hackerman Jones ") .about("Teaches argument parsing") - .arg(Arg::with_name("file") - .short("f") + .arg(Arg::new("file") + .short('f') .long("file") - .takes_value(true) - .help("A cool file")) - .arg(Arg::with_name("num") - .short("n") + .help("A cool file") + .value_parser(PathBufValueParser::default())) + .arg(Arg::new("num") + .short('n') .long("number") - .takes_value(true) .help("Five less than your favorite number")) .get_matches(); - let myfile = matches.value_of("file").unwrap_or("input.txt"); - println!("The file passed is: {}", myfile); + let default_file = PathBuf::from("input.txt"); + let myfile: &PathBuf = matches.get_one("file").unwrap_or(&default_file); + println!("The file passed is: {}", myfile.display()); - let num_str = matches.value_of("num"); + let num_str: Option<&String> = matches.get_one("num"); match num_str { None => println!("No idea what your favorite number is."), Some(s) => { - match s.parse::() { + let parsed: Result = s.parse(); + match parsed { Ok(n) => println!("Your favorite number must be {}.", n + 5), Err(_) => println!("That's not a number! {}", s), } @@ -47,24 +63,19 @@ fn main() { } ``` -Usage information is generated by `clap`. The usage for the example application -looks like this. +Usage information is generated by `clap -h`. The usage for +the example application looks like this. ``` -My Test Program 0.1.0 -Hackerman Jones Teaches argument parsing -USAGE: - testing [OPTIONS] - -FLAGS: - -h, --help Prints help information - -V, --version Prints version information +Usage: clap-cookbook [OPTIONS] -OPTIONS: - -f, --file A cool file - -n, --number Five less than your favorite number +Options: + -f, --file A cool file + -n, --number Five less than your favorite number + -h, --help Print help + -V, --version Print version ``` We can test the application by running a command like the following.