Clap v3
After changing hands multiple times and four years of development, clap 3.0 is ready.
Rust is well known for being great at building command line programs but parsing command line arguments isn’t as easy as it first seems.
As someone new to Rustlang it’s easy to see env::args
in the standard library and think that everything you need is covered.
Dropping env::args
into your program does after all give you a list of arguments that were passed to your program.
But using the arguments list gets tricky immediately because often what we want isn’t just a raw list of the arguments passed to our program.
Did you know the first argument in the list is the name of your binary? How bizarre… and it only gets worse from here. The first element can be set to arbitrary text or might not even exist at all.
and this is only the first edge case of many you’ll run into if you try to take the minimalistic no-dependencies approach to building your cli.
On Unix systems the shell expands glob patterns, on Windows these get passed through as-is.
rg postcss *.json
Lucky for us, this is where clap comes in.
Clap is an argument parsing crate that powers tools like Cargo, ripgrep, and many more.
The short pitch
Clap v3 allows you to let someone else care about argument parsing. This of course is the pitch of most libraries, but I think it’s especially relevant when the program you’re building isn’t focused on the area in question.
That is, if argument parsing isn’t the core problem your project is solving, then offload argument parsing somewhere else.
Why clap specifically?
Clap can take us from small CLIs that accept a single argument to complex multi-subcommand user-extendable CLIs similar to git.
Two Major APIs
Clap offers two major API styles. The classic Builder style API that allows you to chain function calls and the Derive style API that was popularized by StructOpt.
Speaking of StructOpt, what’s happening to StructOpt with the release of Clap 3.0? Well Clap and StructOpt are the same project now and the StructOpt crate is in maintenance mode. The old structopt
crate name will stay as a layer over clap v2, while clap v3 has integrated the derive APIs from StructOpt.
Experimental APIs
Clap is built to support future APIs as well.
[fncmd
is an experimental API](https://github.com/yuhr/fncmd) implemented as a third party crate, much like StructOpt was originally.
The crate exposes just a single attribute macro, [fncmd
], which can only be attached to the main
function and is quite opinionated in how subcommands and multiple binaries compose into a larger CLI.
// main.rsuse fncmd::fncmd;/// Description of the command line tool#[fncmd]pub fn main(/// Argument foo#[opt(short, long)]foo: String,/// Argument bar#[opt(short, long)]bar: Option<String>,) {println!("{:?} {:?}", foo, bar);}
Why you shouldn’t use Clap
The builder API clap exposes can feel verbose, and if you don’t need most of the features Clap offers (for example, if you’re only supporting a single platform) then the deep API surface can feel daunting.
and sometimes, a particular crate just doesn’t fit your preferences. There’s plenty of space in the Rust ecosystem for argument parsers.
3.0 Highlights
#[derive(Debug, Clone, Parser)]struct Cli {#[clap(long, help_heading = "CONFIG")]isolated: bool,#[clap(long, parse(from_os_str), help_heading = "CONFIG")]config: std::path::PathBuf,#[clap(short, long, help_heading = "DEBUG")]verbose: bool,}
askj
$ cargo run -- --helptest-clapUSAGE:test-clap [OPTIONS] --config <CONFIG>OPTIONS:-h, --help Print help informationCONFIG:--config <CONFIG>--isolatedDEBUG:-v, --verbose
My take
My take is that Clap is an extremely solid piece of software that handles a complex piece of functionality that you do not want to handle yourself if it’s not the core purpose of your program.
3.0 is a long-awaited solid upgrade to Clap’s functionality that I personally have been waiting for, and this is why the workshops in Rust Adventure used StructOpt prior to Clap 3.0’s release.
From a maintainer perspective I also appreciate that the Clap project talked about long release cycles in the changelog. If you’re a maintainer of open source crates in the Rust ecosystem (or just libraries in general), I encourage you to check out the changelog as well as some of the named references, such as Bevy’s project direction documentation.
If you want to improve your CLI skills in Rust, check out Rust Adventure dot dev which covers building practical applications with config management, adding useful help messaging, error handling, and more.