Command line argument parsing with Clap
Add this crate to your own project:
cargo add clap --features derive
Clap (derive style)
This application describes the structure of its command-line interface using
clap's Derive API. The documentation gives information on the Builder API
as well.
In the Derive API, a struct is declared which will contain the data
for all the command line options. The clap macros then create all the parsing,
validation logic and help for those options automatically. The short
and long options control the flag the user will be expected to type; short
flags look like -c and long flags look like --count.
use clap::Parser; /// Simple program to greet a person #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Args { /// Name of the person to greet #[clap(short, long)] name: Option<String>, // Make 'name' required by removing Option<> /// Number of times to greet #[clap(short, long, default_value_t = 1)] count: u8, } fn main() { let args = Args::parse(); let users_name = match args.name { Some(name) => name, None => "Mysterious User".to_string(), }; for _ in 0..args.count { println!("Hello {}!", users_name) } }
An argument can be made optional by either providing a default value to clap
(as is the case for the --count option), or by declaring that argument to
be of the Option<> type, such as Option<String> as used with
name. In that case, the args.name will be either Some() which
holds a String value, or None, so the match expression is used to
assign a default name if none was provided.
Usage information is generated by clap macro. The usage for the
example application looks like this. Run on the command line:
cargo run --example clap_basic -- --help
The --example argument is used to select the clap_basic program
in the examples directory to be run. The -- is needed to separate the
arguments passed to the cargo run command from the arguments passed to
clap_basic command.
arguments 0.1.0
Simple program to greet a person
USAGE:
clap_basic [OPTIONS]
OPTIONS:
-c, --count <COUNT> Number of times to greet [default: 1]
-h, --help Print help information
-n, --name <NAME> Name of the person to greet
-V, --version Print version information
We can test the application by running a command like the following.
cargo run --example clap_basic -- --name Zoo -c 3
The output is:
Hello Zoo!
Hello Zoo!
Hello Zoo!
Clap (builder style)
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.
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.
use std::path::PathBuf; use clap::{Arg, Command, builder::PathBufValueParser}; fn main() { let matches = Command::new("My Test Program") .version("0.1.0") .about("Teaches argument parsing") .arg(Arg::new("file") .short('f') .long("file") .help("A cool file") .value_parser(PathBufValueParser::default())) .arg(Arg::new("num") .short('n') .long("number") .help("Five less than your favorite number")) .get_matches(); 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: Option<&String> = matches.get_one("num"); match num_str { None => println!("No idea what your favorite number is."), Some(s) => { let parsed: Result<i32, _> = s.parse(); match parsed { Ok(n) => println!("Your favorite number must be {}.", n + 5), Err(_) => println!("That's not a number! {}", s), } } } }
Usage information is generated by clap -h. The usage for
the example application looks like this.
Teaches argument parsing
Usage: clap-cookbook [OPTIONS]
Options:
-f, --file <file> A cool file
-n, --number <num> 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.
$ cargo run --example clap_with_pathbuf.rs -- -f myfile.txt -n 251
The output is:
The file passed is: myfile.txt
Your favorite number must be 256.