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.rs
use 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 -- --help
test-clap
USAGE:
test-clap [OPTIONS] --config <CONFIG>
OPTIONS:
-h, --help Print help information
CONFIG:
--config <CONFIG>
--isolated
DEBUG:
-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.