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.