How to get a good --help for free
Short answer: clap builds --help from three things already in the code: the /// doc comments, the default_value_t values, and whether a field is String or Option<String>. Keep those three honest and the help text looks after itself.
The examples stay in the args1 project from the previous article, so the usage lines below say args1; a project with another name prints that name instead.
Replace src/main.rs
Section titled “Replace src/main.rs”[dependencies]clap = { version = "4.6.7", features = ["derive"] }Replace src/main.rs with the greeter from the previous article, with three edits that change what --help prints:
use clap::{Parser, Subcommand};
/// A small tool with two commands#[derive(Parser)]struct Cli { #[command(subcommand)] command: Command,
/// Print the parsed command as well #[arg(short, long, global = true)] verbose: bool,}
#[derive(Debug, Subcommand)]enum Command { /// Greet someone Greet { /// Who to greet name: String,
/// How many times to greet them #[arg(short, long, default_value_t = 1)] count: u8, }, /// Say goodbye to someone, or to everyone Bye { /// Who to say goodbye to; leave it out to say goodbye to everyone name: Option<String>, },}
fn main() { let cli = Cli::parse();
if cli.verbose { eprintln!("verbose: {:?}", cli.command); }
match cli.command { Command::Greet { name, count } => { for _ in 0..count { println!("hello, {name}"); } } Command::Bye { name } => { let name = name.unwrap_or_else(|| "everyone".to_string()); println!("bye, {name}"); } }}The help text is the doc comments
Section titled “The help text is the doc comments”$ cargo run -q -- --helpA small tool with two commands
Usage: args1 [OPTIONS] <COMMAND>
Commands: greet Greet someone bye Say goodbye to someone, or to everyone help Print this message or the help of the given subcommand(s)
Options: -v, --verbose Print the parsed command as well -h, --help Print helpThree doc comments write that page. The one above struct Cli is the first line; it does the same job as the about = "…" attribute the previous article used, and it sits directly above the struct it describes. The comment above each field is the text in that field’s row, and each variant’s comment is its line under Commands. One level down, the same comments appear again:
$ cargo run -q -- greet --helpGreet someone
Usage: args1 greet [OPTIONS] <NAME>
Arguments: <NAME> Who to greet
Options: -c, --count <COUNT> How many times to greet them [default: 1] -v, --verbose Print the parsed command as well -h, --help Print helpNothing on that page was typed twice: Greet someone, Who to greet, and the --count row are the /// lines from the file above. --verbose shows up here too because it is global, as in the previous article.
Defaults print themselves
Section titled “Defaults print themselves”The [default: 1] comes from default_value_t = 1, and it’s the only copy of that number. Change the attribute to 3 and the row follows:
-c, --count <COUNT> How many times to greet them [default: 3]The default is also what makes the option optional. Remove the attribute and clap makes --count required instead: the usage line grows a --count <COUNT>, and omitting the flag is an error with exit code 2.
$ cargo run -q -- greet Adaerror: the following required arguments were not provided: --count <COUNT>
Usage: args1 greet --count <COUNT> <NAME>
For more information, try '--help'.Required or optional is the type
Section titled “Required or optional is the type”For a positional argument the switch is the type, not an attribute. greet’s name is a String, so the usage line reads <NAME> and clap refuses to run without it:
$ cargo run -q -- greeterror: the following required arguments were not provided: <NAME>
Usage: args1 greet <NAME>
For more information, try '--help'.bye’s name is an Option<String>, so the usage line reads [NAME] and the argument may be left out. The cost is the branch in main that says what absent means:
$ cargo run -q -- bye --helpSay goodbye to someone, or to everyone
Usage: args1 bye [OPTIONS] [NAME]
Arguments: [NAME] Who to say goodbye to; leave it out to say goodbye to everyone
Options: -v, --verbose Print the parsed command as well -h, --help Print help$ cargo run -q -- byebye, everyone
$ cargo run -q -- bye Bobbye, Bob- How to add subcommands with clap — the enum this page grows
- How to parse arguments with clap — where the
args1project starts - Parsing arguments with clap — the same program in the CLI track
- Back to Building a command-line tool