I really like Rust’s StructOpt crate

April 30th, 2019

I’ve been playing around with Rust for a while now and recently wrote a little tool that I wanted to run via the CLI. The Command Line Applications in Rust book written by the Rust CLI Working Group pointed me towards StructOpt which I liked using so I thought I’d put a little overview here.

What is it

StructOpt is a set of macros that wraps the clap crate to make configuring and parsing a CLI interface into a configuration struct easy.

So far I’ve found it nice to use and I like how the resulting code looks. I usually try and avoid “magic” macros that aren’t essential but in this case I think they make something readable and are worth the extra level of indirection.

It’s not that plain clap is bad, it isn’t, but I prefer the more declarative style of StructOpt in this case.

An example

Here’s a trivial example that show just some of what I like about the crate.

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name = "Some CLI tool")]
struct Options {
    // normal comments are just comments
    /// doc comments get turned into help
    #[structopt(short = "e", long = "example")]
    example: bool,

    // The number of occurrences of the `v/verbose` flag
    /// Verbose mode (-v, -vv, -vvv, etc.)
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: u8,
}

fn main() {
    let options = Options::from_args();
    println!("{:?}", options);
}

Building and running this shows how StructOpt makes a good help screen:

./target/debug/sopt --help
Some CLI tool 0.1.0
Chris McGrath <chris@chrismcg.com>

USAGE:
    sopt [FLAGS]

FLAGS:
    -e, --example    doc comments get turned into help
    -h, --help       Prints help information
    -V, --version    Prints version information
    -v, --verbose    Verbose mode (-v, -vv, -vvv, etc.)

It picks up author and version information from the Cargo.toml file but allows for overriding via the attributes.

Running with the actual options:

./target/debug/sopt -vvvv -e
Options { example: true, verbose: 4 }

You can see that the Options struct is populated without having to write very much code yourself.

Summary

This post just scratches the surface of what’s possible with StructOpt and clap. I’ve not showing parsing number, paths, handling sub commands etc. which are all possible.

It’s also worth pointing out that the in progress version 3.0 of clap intends to incorporate StructOpt so in the future you won’t need two separate crates.