Rust 48 🦀 Command-Line Interface Parsing (clap crate)
Every command-line tool has an interface. The user types the program name, the options, the positional arguments, and the subcommands, and the program must parse the input, validate it, and produce a helpful error message when something is wrong. Hand-writing this parsing is tedious and error-prone. The argument order, the short and long forms, the default values, the required fields, and the help text are all the details that the developer must get right. The clap crate is the standard library for building command-line interfaces in Rust. It generates the parser from the declarative definition, validates the input, and produces the polished help messages automatically.
The crate has two APIs: the builder API and the derive API. The builder API constructs the parser programmatically with the method calls, and it is the flexible and the explicit. The derive API defines the parser with the struct and the attributes, and it is the concise and the type-safe. The derive API is the recommended approach for most applications, because the struct documents the interface, and the compiler enforces the types. The builder API is the fallback for the dynamic interfaces and the cases the derive cannot express.
The derive API maps the struct fields to the command-line arguments. A field with the String type and the #[arg(short, long)] attribute becomes the option --name with the short form -n. A field with the bool type becomes the flag. A field without the short or the long becomes the positional argument. The Option<T> makes the argument optional, and the Vec<T> makes it repeatable. The #[command] attribute configures the program-level metadata, and the #[arg] attribute configures the individual arguments.
This chapter covers three areas. First, why clap exists — the parsing problem and the derive-versus-builder trade-off. Second, how to use the derive API — the Parser, the Args, the Subcommand, the #[arg], the #[command], the options, the flags, and the positional arguments. Third, the patterns and the advanced features — the subcommands, the validation, the ValueEnum, the custom parsers, the environment variables, and the configuration files. The chapter ends with a complete example session, a quick reference, best practices, common pitfalls, real-world examples, and diagrams showing the parsing flow.
Key point: The clap crate is the standard command-line parsing library for Rust. The derive API defines the parser with the struct and the attributes, and the builder API constructs it with the method calls. The #[derive(Parser)] generates the parser, the #[arg] configures the arguments, and the #[command] configures the program. The Option<T> makes the argument optional, the Vec<T> makes it repeatable, and the ValueEnum restricts the values to the enum.
Why clap exists
The parsing problem. The command-line arguments are the strings, and the program must decide which string is the option, which is the value, and which is the positional. The --name Alice is the option with the value, the --verbose is the flag, and the input.txt is the positional. The parsing must handle the --name=Alice form, the -n Alice form, the combined -vvv form, and the -- separator. The hand-written parsing is the many edge cases, and the clap handles them.
The help problem. The --help flag should print the usage, the options, the arguments, and the descriptions. The help text must be the accurate and the formatted. The hand-written help is the maintenance burden, and the clap generates it from the definition. The help is the documentation, and the documentation is the automatic.
The validation problem. The argument must be the valid. The port must be the number, the file must exist, the enum must be the known value. The clap validates the input at the parse time, and the error message is the clear. The value_parser attribute specifies the parser, and the ValueEnum restricts the values to the enum.
The derive-versus-builder problem. The derive API is the concise and the type-safe. The struct is the single source of the definition, and the compiler checks the types. The builder API is the flexible and the dynamic. The runtime constructs the parser, and the definition is the code. The derive is the recommended for the static interfaces, and the builder is for the dynamic.
The subcommand problem. The tools with the multiple actions (the git add, the git commit, the cargo build) use the subcommands. The clap supports the subcommands with the enum, and the derive generates the parser for each variant. The match on the enum handles the dispatch, and the compiler ensures the exhaustive.
The trade-off. The clap adds the dependency and the compile time. The derive macro generates the code, and the binary grows. The alternative is the hand-written parsing, which is the smaller but the error-prone. The trade-off is between the convenience of the generated parser and the size of the dependency, and the modern Rust tools choose the clap.
a. The derive API
The derive API defines the parser with the struct and the #[derive(Parser)] attribute.
use clap::Parser;
/// A simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Name of the person to greet
#[arg(short, long)]
name: String,
/// Number of times to greet
#[arg(short, long, default_value_t = 1)]
count: u8,
}
fn main() {
let args = Args::parse();
for _ in 0..args.count {
println!("Hello, {}!", args.name);
}
}
The #[derive(Parser)] generates the parse method, and the Args::parse() reads the std::env::args and returns the struct. The #[command] attribute configures the program metadata: the author from the Cargo.toml, the version from the Cargo.toml, and the about from the doc comment. The #[arg] configures the individual fields.
The doc comment. The doc comment on the struct is the about, and the doc comment on the field is the help for the argument.
/// A simple program to greet a person
#[derive(Parser)]
struct Args {
/// Name of the person to greet
#[arg(short, long)]
name: String,
}
The --help output uses the doc comments:
A simple program to greet a person
Usage: my_tool [OPTIONS] --name <NAME>
Options:
-n, --name <NAME> Name of the person to greet
-h, --help Print help
-V, --version Print version
The parse and the try_parse. The parse exits the process on the error, and the try_parse returns the Result:
fn main() {
let args = Args::parse();
// ...
}
fn main() {
let args = match Args::try_parse() {
Ok(args) => args,
Err(e) => {
e.print().unwrap();
std::process::exit(1);
}
};
}
The parse is the convenience, and the try_parse is the testable.
b. The arguments
The positional arguments. The field without the short or the long is the positional.
#[derive(Parser)]
struct Args {
/// The input file
input: String,
/// The optional output file
output: Option<String>,
}
The input is the required positional, and the output is the optional. The usage is my_tool <INPUT> [OUTPUT].
The options. The field with the #[arg(short, long)] is the option.
#[derive(Parser)]
struct Args {
/// The configuration file
#[arg(short, long)]
config: Option<String>,
/// The port number
#[arg(short, long, default_value_t = 8080)]
port: u16,
}
The --config and the -c are the option, and the --port and the -p are the option with the default. The usage is my_tool [OPTIONS].
The flags. The bool field is the flag.
#[derive(Parser)]
struct Args {
/// Enable the verbose output
#[arg(short, long)]
verbose: bool,
/// Suppress the output
#[arg(short, long)]
quiet: bool,
}
The --verbose and the -v are the flag, and the --quiet and the -q are the flag. The flag is the false by default and the true when present.
The repeatable. The Vec<T> field is the repeatable.
#[derive(Parser)]
struct Args {
/// The files to process
#[arg(short, long)]
files: Vec<String>,
}
The --files a.txt --files b.txt collects the ["a.txt", "b.txt"].
The required. The Option<T> is the optional, and the plain type is the required.
#[derive(Parser)]
struct Args {
/// The required name
#[arg(short, long)]
name: String, // the required
/// The optional email
#[arg(short, long)]
email: Option<String>, // the optional
}
The value_enum. The enum with the ValueEnum restricts the values.
use clap::ValueEnum;
#[derive(Clone, Debug, ValueEnum)]
enum Color {
Auto,
Always,
Never,
}
#[derive(Parser)]
struct Args {
/// When to use the color
#[arg(long, value_enum, default_value_t = Color::Auto)]
color: Color,
}
The --color always accepts the always, the never, and the auto, and the invalid value is the error.
c. The subcommands
The subcommands are the enum with the Subcommand derive.
use clap::{Parser, Subcommand};
#[derive(Parser)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Add a new item
Add {
/// The item name
name: String,
},
/// Remove an item
Remove {
/// The item id
id: u32,
},
/// List all the items
List,
}
fn main() {
let cli = Cli::parse();
match cli.command {
Commands::Add { name } => println!("Adding {}", name),
Commands::Remove { id } => println!("Removing {}", id),
Commands::List => println!("Listing"),
}
}
The #[command(subcommand)] on the field makes it the subcommand. The Commands enum has the three variants: the Add, the Remove, and the List. The usage is my_tool <COMMAND>, and the my_tool add Alice runs the Add variant.
The nested subcommands. The subcommands can be nested.
#[derive(Subcommand)]
enum Commands {
/// Manage the users
User {
#[command(subcommand)]
action: UserAction,
},
}
#[derive(Subcommand)]
enum UserAction {
/// Create a user
Create { name: String },
/// Delete a user
Delete { id: u32 },
}
The my_tool user create Alice runs the nested Create variant.
The optional subcommand. The Option<Commands> makes the subcommand optional.
#[derive(Parser)]
struct Cli {
#[command(subcommand)]
command: Option<Commands>,
}
The my_tool without the subcommand runs the default behavior.
The flatten. The #[command(flatten)] includes the fields of another struct.
#[derive(Parser)]
struct Cli {
#[command(flatten)]
verbose: Verbosity,
#[command(subcommand)]
command: Commands,
}
#[derive(clap::Args)]
struct Verbosity {
/// Increase the verbosity
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
}
The Verbosity struct is flattened into the Cli, and the --verbose is the global option.
Complete Example Session
// ============================================
// PART 1: THE BASIC PARSER
// ============================================
use clap::Parser;
/// A simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Name of the person to greet
#[arg(short, long)]
name: String,
/// Number of times to greet
#[arg(short, long, default_value_t = 1)]
count: u8,
}
fn main() {
let args = Args::parse();
for _ in 0..args.count {
println!("Hello, {}!", args.name);
}
}
// ============================================
// PART 2: THE POSITIONAL AND THE OPTIONS
// ============================================
use clap::Parser;
/// A file processing tool
#[derive(Parser, Debug)]
#[command(version, about)]
struct Args {
/// The input file
input: String,
/// The output file
#[arg(short, long)]
output: Option<String>,
/// The number of the threads
#[arg(short, long, default_value_t = 4)]
threads: usize,
}
fn main() {
let args = Args::parse();
println!("Input: {}", args.input);
println!("Output: {:?}", args.output);
println!("Threads: {}", args.threads);
}
// ============================================
// PART 3: THE FLAGS
// ============================================
use clap::Parser;
#[derive(Parser, Debug)]
struct Args {
/// The input file
input: String,
/// Enable the verbose output
#[arg(short, long)]
verbose: bool,
/// Suppress the output
#[arg(short, long)]
quiet: bool,
}
fn main() {
let args = Args::parse();
if args.verbose {
println!("Verbose mode enabled");
}
if args.quiet {
println!("Quiet mode enabled");
}
}
// ============================================
// PART 4: THE REPEATABLE
// ============================================
use clap::Parser;
#[derive(Parser, Debug)]
struct Args {
/// The files to process
#[arg(short, long)]
files: Vec<String>,
}
fn main() {
let args = Args::parse();
for file in &args.files {
println!("Processing: {}", file);
}
}
// The usage: my_tool --files a.txt --files b.txt
// ============================================
// PART 5: THE VALUE ENUM
// ============================================
use clap::{Parser, ValueEnum};
#[derive(Clone, Debug, ValueEnum)]
enum Color {
Auto,
Always,
Never,
}
#[derive(Parser, Debug)]
struct Args {
/// The input file
input: String,
/// When to use the color
#[arg(long, value_enum, default_value_t = Color::Auto)]
color: Color,
}
fn main() {
let args = Args::parse();
println!("Color: {:?}", args.color);
}
// ============================================
// PART 6: THE SUBCOMMANDS
// ============================================
use clap::{Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(version, about)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// Add a new item
Add {
/// The item name
name: String,
/// The item quantity
#[arg(short, long, default_value_t = 1)]
quantity: u32,
},
/// Remove an item
Remove {
/// The item id
id: u32,
},
/// List all the items
List,
}
fn main() {
let cli = Cli::parse();
match cli.command {
Commands::Add { name, quantity } => {
println!("Adding {} x{}", name, quantity);
}
Commands::Remove { id } => {
println!("Removing {}", id);
}
Commands::List => {
println!("Listing");
}
}
}
// ============================================
// PART 7: THE NESTED SUBCOMMANDS
// ============================================
use clap::{Parser, Subcommand};
#[derive(Parser, Debug)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// Manage the users
User {
#[command(subcommand)]
action: UserAction,
},
/// Manage the items
Item {
#[command(subcommand)]
action: ItemAction,
},
}
#[derive(Subcommand, Debug)]
enum UserAction {
/// Create a user
Create {
/// The user name
name: String,
},
/// Delete a user
Delete {
/// The user id
id: u32,
},
}
#[derive(Subcommand, Debug)]
enum ItemAction {
/// Add an item
Add { name: String },
/// Remove an item
Remove { id: u32 },
}
fn main() {
let cli = Cli::parse();
match cli.command {
Commands::User { action } => match action {
UserAction::Create { name } => println!("Creating user {}", name),
UserAction::Delete { id } => println!("Deleting user {}", id),
},
Commands::Item { action } => match action {
ItemAction::Add { name } => println!("Adding item {}", name),
ItemAction::Remove { id } => println!("Removing item {}", id),
},
}
}
// ============================================
// PART 8: THE VALIDATION
// ============================================
use clap::Parser;
#[derive(Parser, Debug)]
struct Args {
/// The port number
#[arg(short, long, value_parser = clap::value_parser!(u16).range(1..=65535))]
port: u16,
/// The log level
#[arg(long, value_parser = ["debug", "info", "warn", "error"])]
log_level: String,
}
fn main() {
let args = Args::parse();
println!("Port: {}", args.port);
println!("Log level: {}", args.log_level);
}
// ============================================
// PART 9: THE ENVIRONMENT VARIABLES
// ============================================
use clap::Parser;
#[derive(Parser, Debug)]
struct Args {
/// The API key
#[arg(long, env = "API_KEY")]
api_key: String,
/// The database URL
#[arg(long, env = "DATABASE_URL", default_value = "postgres://localhost")]
database_url: String,
}
fn main() {
let args = Args::parse();
println!("API key: {}", args.api_key);
println!("Database: {}", args.database_url);
}
// The env attribute reads the environment variable.
// ============================================
// PART 10: THE COMPLETE EXAMPLE
// ============================================
use clap::{Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
/// A file management tool
#[derive(Parser, Debug)]
#[command(name = "filetool", version, about, long_about = None)]
struct Cli {
/// Increase the verbosity
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
/// The configuration file
#[arg(short, long, default_value = "config.toml")]
config: PathBuf,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// Copy a file
Copy {
/// The source file
source: PathBuf,
/// The destination
destination: PathBuf,
/// Overwrite the existing file
#[arg(short, long)]
force: bool,
},
/// Move a file
Move {
/// The source file
source: PathBuf,
/// The destination
destination: PathBuf,
},
/// List the files
List {
/// The directory
#[arg(default_value = ".")]
directory: PathBuf,
/// The output format
#[arg(long, value_enum, default_value_t = Format::Table)]
format: Format,
},
}
#[derive(Clone, Debug, ValueEnum)]
enum Format {
Table,
Json,
Plain,
}
fn main() {
let cli = Cli::parse();
match cli.verbose {
0 => {}
1 => println!("Verbose mode"),
_ => println!("Very verbose mode"),
}
println!("Config: {:?}", cli.config);
match cli.command {
Commands::Copy {
source,
destination,
force,
} => {
if force {
println!("Force copying {:?} to {:?}", source, destination);
} else {
println!("Copying {:?} to {:?}", source, destination);
}
}
Commands::Move {
source,
destination,
} => {
println!("Moving {:?} to {:?}", source, destination);
}
Commands::List { directory, format } => {
println!("Listing {:?} as {:?}", directory, format);
}
}
}
The ten parts show the basic parser, the positional and the options, the flags, the repeatable, the ValueEnum, the subcommands, the nested subcommands, the validation, the environment variables, and the complete example.
Quick Reference
The Attributes
| Attribute | Purpose |
|---|---|
#[derive(Parser)] | The derive the parser |
#[derive(Subcommand)] | The derive the subcommand |
#[derive(Args)] | The derive the args group |
#[derive(ValueEnum)] | The derive the value enum |
#[command(...)] | The program-level config |
#[arg(...)] | The argument-level config |
The Common #[arg] Options
| Option | Purpose |
|---|---|
short | The short form -n |
long | The long form --name |
default_value_t | The default value |
default_value | The default string |
value_parser | The parser |
value_enum | The enum values |
env | The environment variable |
required | The required |
action = ArgAction::Count | The repeatable counter |
action = ArgAction::SetTrue | The flag |
The Field Types
| Type | The meaning |
|---|---|
String | The required string |
Option<String> | The optional string |
Vec<String> | The repeatable |
bool | The flag |
u8 / u16 / u32 | The number |
PathBuf | The file path |
T: ValueEnum | The enum |
The Program Attributes
| Attribute | Purpose |
|---|---|
name | The program name |
version | The version |
author | The author |
about | The short description |
long_about | The long description |
The Commands
| Command | The usage |
|---|---|
my_tool --help | The help |
my_tool --version | The version |
my_tool <POSITIONAL> | The positional |
my_tool --option value | The option |
my_tool --flag | The flag |
my_tool <SUBCOMMAND> | The subcommand |
Best Practices
✅ Do This:
// Use the derive API
#[derive(Parser)]
struct Args { ... } // ✅
// Use the doc comments for the help
/// The name of the person
#[arg(short, long)]
name: String, // ✅
// Use the Option<T> for the optional
output: Option<String>, // ✅
// Use the Vec<T> for the repeatable
files: Vec<String>, // ✅
// Use the ValueEnum for the constrained values
#[arg(long, value_enum)]
color: Color, // ✅
// Use the subcommands for the multiple actions
#[command(subcommand)]
command: Commands, // ✅
// Use the env attribute for the environment
#[arg(long, env = "API_KEY")]
api_key: String, // ✅
// Use the value_parser for the validation
#[arg(long, value_parser = clap::value_parser!(u16).range(1..))]
port: u16, // ✅
❌ Don’t Do This:
// Don't hand-write the parsing
let args: Vec<String> = std::env::args().collect(); // the manual // ❌
// Don't forget the doc comment
#[arg(short, long)]
name: String, // the missing help // ❌
// Don't use the String for the optional
output: String, // the required; use the Option // ❌
// Don't use the plain String for the enum
color: String, // the invalid values possible // ❌
// Don't forget the default
#[arg(short, long)]
count: u8, // the required; add the default_value_t // ❌
// Don't parse the env var manually
let key = std::env::var("API_KEY"); // the env attribute is the better // ❌
// Don't use the builder for the static interface
// The derive is the concise and the type-safe // ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| The argument is not recognized | The missing #[arg] | Add the attribute |
| The help is empty | The missing doc comment | Add the /// |
| The optional is required | The plain type | Use the Option<T> |
| The default is ignored | The wrong attribute | Use the default_value_t |
| The enum value fails | The missing value_enum | Add the value_enum |
| The subcommand is required | The plain type | Use the Option<Commands> |
| The env var is not read | The missing env | Add the env = "NAME" |
Real-World Examples
1. The Basic Parser
#[derive(Parser)]
struct Args { #[arg(short, long)] name: String }
2. The Positional
#[derive(Parser)]
struct Args { input: String }
3. The Optional
#[derive(Parser)]
struct Args { output: Option<String> }
4. The Flag
#[derive(Parser)]
struct Args { #[arg(short, long)] verbose: bool }
5. The Repeatable
#[derive(Parser)]
struct Args { #[arg(short, long)] files: Vec<String> }
6. The ValueEnum
#[derive(ValueEnum)]
enum Color { Auto, Always, Never }
7. The Subcommand
#[derive(Subcommand)]
enum Commands { Add { name: String }, List }
8. The Validation
#[arg(long, value_parser = clap::value_parser!(u16).range(1..))]
9. The Environment
#[arg(long, env = "API_KEY")]
10. The Complete
#[derive(Parser)]
#[command(name = "tool", version, about)]
struct Cli { #[command(subcommand)] command: Commands }
Visual
The Derive API Flow
┌──────────────────────────────────────────────────────────────┐
│ THE DERIVE API FLOW │
│ │
│ The struct: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ #[derive(Parser)] │ │
│ │ struct Args { │ │
│ │ /// The name │ │
│ │ #[arg(short, long)] │ │
│ │ name: String, │ │
│ │ /// The count │ │
│ │ #[arg(short, long, default_value_t = 1)] │ │
│ │ count: u8, │ │
│ │ } │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ │ The derive macro generates the parser │
│ ▼ │
│ The generated: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ impl Args { │ │
│ │ fn parse() -> Self { ... } │ │
│ │ fn try_parse() -> Result<Self, Error> { ... } │ │
│ │ } │ │
│ │ │ │
│ │ The help generator, the validator, the error. │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ The runtime: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ let args = Args::parse(); │ │
│ │ println!("{}", args.name); │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
The Argument Types
┌──────────────────────────────────────────────────────────────┐
│ THE ARGUMENT TYPES │
│ │
│ THE POSITIONAL: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ input: String │ │
│ │ → my_tool input.txt │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ THE OPTION: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ #[arg(short, long)] │ │
│ │ config: Option<String> │ │
│ │ → my_tool --config file.toml │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ THE FLAG: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ #[arg(short, long)] │ │
│ │ verbose: bool │ │
│ │ → my_tool --verbose │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ THE REPEATABLE: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ #[arg(short, long)] │ │
│ │ files: Vec<String> │ │
│ │ → my_tool --files a.txt --files b.txt │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
The Subcommands
┌──────────────────────────────────────────────────────────────┐
│ THE SUBCOMMANDS │
│ │
│ #[derive(Subcommand)] │
│ enum Commands { │
│ Add { name: String }, │
│ Remove { id: u32 }, │
│ List, │
│ } │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ my_tool add Alice │ │
│ │ → the Commands::Add { name: "Alice" } │ │
│ │ │ │
│ │ my_tool remove 42 │ │
│ │ → the Commands::Remove { id: 42 } │ │
│ │ │ │
│ │ my_tool list │ │
│ │ → the Commands::List │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ The match on the enum dispatches the action. │
│ │
└──────────────────────────────────────────────────────────────┘
The Help Generation
┌──────────────────────────────────────────────────────────────┐
│ THE HELP GENERATION │
│ │
│ /// A simple program to greet a person │
│ #[derive(Parser)] │
│ #[command(version, about)] │
│ struct Args { │
│ /// Name of the person to greet │
│ #[arg(short, long)] │
│ name: String, │
│ } │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ $ my_tool --help │ │
│ │ │ │
│ │ A simple program to greet a person │ │
│ │ │ │
│ │ Usage: my_tool [OPTIONS] --name <NAME> │ │
│ │ │ │
│ │ Options: │ │
│ │ -n, --name <NAME> Name of the person to greet │ │
│ │ -h, --help Print help │ │
│ │ -V, --version Print version │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ The help is generated from the doc comments and the │
│ attributes. │
│ │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
clap | The command-line parsing library |
#[derive(Parser)] | The derive the parser |
#[derive(Subcommand)] | The derive the subcommand |
#[derive(ValueEnum)] | The derive the value enum |
#[arg] | The argument config |
#[command] | The program config |
Args::parse() | The parse the args |
Option<T> | The optional |
Vec<T> | The repeatable |
bool | The flag |
value_enum | The enum values |
env | The environment variable |
Key takeaways:
- The
clapcrate is the standard command-line parsing library for Rust. It handles the parsing, the validation, and the help generation. The#[derive(Parser)]generates the parser, and theArgs::parse()returns the struct . - The derive API maps the struct fields to the arguments. The field with the
#[arg(short, long)]is the option, theboolis the flag, and the field without theshortor thelongis the positional. The doc comments are the help text . - The
Option<T>is the optional, and the plain type is the required. TheVec<T>is the repeatable. Thedefault_value_tprovides the default. Thevalue_enumrestricts the values to the enum . - The
#[command]configures the program, and the#[arg]configures the arguments. The#[command]sets the name, the version, the author, and the about. The#[arg]sets the short, the long, the default, the value parser, and the environment variable . - The subcommands use the enum with the
#[derive(Subcommand)]. The#[command(subcommand)]on the field makes it the subcommand. Thematchon the enum dispatches the action, and the compiler ensures the exhaustive . - The
value_parservalidates the input. Theclap::value_parser!(u16).range(1..)validates the range, and the["debug", "info"]restricts the values. The invalid input is the clear error . - The
envattribute reads the environment variable. The#[arg(long, env = "API_KEY")]reads theAPI_KEYwhen the option is not provided. The environment variable is the fallback . - The
--helpand the--versionare generated automatically. The#[command(version, about)]enables them, and the doc comments are the content. The help is the documentation, and the documentation is the automatic .
Remember: The clap crate is the standard command-line parsing library for Rust. The derive API defines the parser with the struct and the attributes, and the builder API constructs it with the method calls. The #[derive(Parser)] generates the parser, the #[arg] configures the arguments, and the #[command] configures the program. The result is the polished command-line interface with the validation and the help, without the hand-written parsing.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!