CLI - Command line Interface with clap
In this book we are going to learn how to use Clap, the Command Line Argument Parser for Rust.
There are two main ways to use Clap. Using the manual Builder and the Derive mode. In these example we'll learn about using the Builder
First example: One parameter
In order to get started we need to add clap to the depenedencies. We can do so either by running cargo add clap
or by editing the Cargo.toml
file
manually adding the [dependencies]
section if it isn't there and the row with clap
.
The cargo add clap
command will use the latest version number of clap. By the time your read this book this number will probably have a higher value
than what you see here.
This is the Cargo.toml
in my example:
[package]
name = "demo"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = "4.5.29"
use clap::{Arg, Command}; fn main() { let command = Command::new("My app") .arg(Arg::new("name")); let matches = command.get_matches(); match matches.get_one::<String>("name") { Some(name) => println!("name: {:?}", name), None => println!("No name provided"), } }
$ cargo run -q
No name provided
$ cargo run -q Foo
name: "Foo"
$ cargo run -q "Foo Bar"
name: "Foo Bar"
cargo build --release
$ ./target/release/demo
No name provided
$ ./target/release/demo Foo
name: "Foo"
If the user does not understand what parameters are expected by this program she can run the command proving the --help
flag or
the shorter -h
flag and Clap will print some explanation on how to use this command line tool:
$ ./target/release/demo --help
Usage: demo [name]
Arguments:
[name]
Options:
-h, --help Print help
We can achieve the same even without using the compiled binary using cargo build
, but in that case we need to supply the --help
flag
after a --
.
cargo run -q -- --help
The above might look strange, but if forget to proveide the --
separator and we write this:
cargo run -q --help
then we'll see the help of the cargo command itself. That was not our intention.
Positional parameters
use clap::{Arg, Command}; fn main() { let command = Command::new("My app") .arg(Arg::new("fname")) .arg(Arg::new("lname")); let matches = command.get_matches(); match matches.get_one::<String>("fname") { Some(name) => println!("fname: {:?}", name), None => println!("No fname provided"), } match matches.get_one::<String>("lname") { Some(name) => println!("lname: {:?}", name), None => println!("No lname provided"), } }
Named parameter
use clap::{Arg, Command}; fn main() { let command = Command::new("My app") .arg(Arg::new("fname").long("fanme")) .arg(Arg::new("lname").long("lanme")); let matches = command.get_matches(); match matches.get_one::<String>("fname") { Some(name) => println!("fname: {:?}", name), None => println!("No fname provided"), } match matches.get_one::<String>("lname") { Some(name) => println!("lname: {:?}", name), None => println!("No lname provided"), } }