How to parse arguments with clap
Short answer: Add clap with the derive feature, describe the command line as a struct, and call
Cli::parse(). The parser, the --help text, and the error messages all come from that struct.
The examples stay in the args1 project from the previous article. Make yours with cargo new args1
if you don’t have it; the usage lines below will then show your project’s name instead.
Add clap
Section titled “Add clap”cargo add clap --features deriveThat writes this into Cargo.toml:
[dependencies]clap = { version = "4.6.7", features = ["derive"] }The exact version depends on when you run it; the derive feature is the part that matters. Without
it you only get the builder API, which spells the same command line out longhand.
Describe the command line as a struct
Section titled “Describe the command line as a struct”Replace src/main.rs with the greeter from the previous article, this time with the parsing done for
you:
use clap::Parser;
#[derive(Parser)]#[command(about = "Greet someone")]struct Cli { /// Who to greet name: String,
/// How many times to greet them #[arg(short, long, default_value_t = 1)] count: u8,}
fn main() { let cli = Cli::parse();
for _ in 0..cli.count { println!("hello, {}", cli.name); }}A field with no #[arg] is a required positional argument, so name is the first one.
#[arg(short, long)] lets count be given as -c or --count. And the /// comments are not notes
for you; clap prints them in --help.
$ cargo run -q -- Adahello, Ada
$ cargo run -q -- Ada --count 2hello, Adahello, Ada-c 3 does the same as --count 3.
What clap gives you for free
Section titled “What clap gives you for free”Leave out the required argument:
$ cargo run -q --error: the following required arguments were not provided: <NAME>
Usage: args1 <NAME>
For more information, try '--help'.$ echo $?2That is the hand-written usage branch from the previous article, generated, and it exits with code 2
rather than panicking, which is what a shell script or a CI job checks for. Cli::parse() never
returns an error to your code; on a bad command line it prints the message and exits, which is why
there is no Result to unwrap.
And the help text, which nobody writes by hand:
$ cargo run -q -- --helpGreet someone
Usage: args1 [OPTIONS] <NAME>
Arguments: <NAME> Who to greet
Options: -c, --count <COUNT> How many times to greet them [default: 1] -h, --help Print helpThe about attribute is the first line, the doc comments fill the columns, and [default: 1] comes
from default_value_t. An unknown flag is caught the same way, also with exit code 2.
Shaping the help text further (longer descriptions, value names, hiding an option) is a page of its
own. Subcommands, the git-style verbs that take their own arguments, are an enum with
#[derive(Subcommand)], and they come next.
- How to pass arguments with cargo run — the hand-written parser this replaces
- Parsing arguments with clap — the same program, grown into a CLI with subcommands
- Back to Building a command-line tool