Parse command line argument by defining a struct.
Rust
Latest commit 52d2550 Feb 11, 2017 @TeXitoi committed on GitHub Update README.md

README.md

StructOpt Build status

Parse command line argument by defining a struct. It combines clap with custom derive.

Documentation

Find it on Docs.rs: structopt-derive and structopt.

Example

Add structopt and structop-derive to your dependencies of your Cargo.toml:

[dependencies]
structopt = "0.0.3"
structopt-derive = "0.0.3"

And then, in your rust file:

extern crate structopt;
#[macro_use]
extern crate structopt_derive;

use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name = "example", about = "An example of StructOpt usage.")]
struct Opt {
    /// A flag, true if used in the command line.
    #[structopt(short = "d", long = "debug", help = "Activate debug mode")]
    debug: bool,

    /// An argument of type float, with a default value.
    #[structopt(short = "s", long = "speed", help = "Set speed", default_value = "42")]
    speed: f64,

    /// Needed parameter, the first on the command line.
    #[structopt(help = "Input file")]
    input: String,

    /// An optional parameter, will be `None` if not present on the
    /// command line.
    #[structopt(help = "Output file, stdout if not present")]
    output: Option<String>,
}

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

Using this example:

$ ./example
error: The following required arguments were not provided:
    <input>

USAGE:
    example [FLAGS] [OPTIONS] <input> [ARGS]

For more information try --help
$ ./example --help
example 0.0.0
Guillaume Pinot <texitoi@texitoi.eu>
An example of StructOpt usage.

USAGE:
    example [FLAGS] [OPTIONS] <input> [ARGS]

FLAGS:
    -d, --debug      Activate debug mode
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -s, --speed <speed>    Set speed [default: 42]

ARGS:
    <input>     Input file
    <output>    Output file, stdout if not present
$ ./example foo
Opt { debug: false, speed: 42, input: "foo", output: None }
$ ./example -ds 1337 foo bar
Opt { debug: true, speed: 1337, input: "foo", output: Some("bar") }

Why

I use docopt since a long time (pre rust 1.0). I really like the fact that you have a structure with the parsed argument: no need to convert String to f64, no useless unwrap. But on the other hand, I don't like to write by hand the usage string. That's like going back to the golden age of WYSIWYG editors. Field naming is also a bit artificial.

Today, the new standard to read command line arguments in Rust is clap. This library is so feature full! But I think there is one downside: even if you can validate argument and expressing that an argument is required, you still need to transform something looking like a hashmap of string vectors to something useful for your application.

Now, there is stable custom derive. Thus I can add to clap the automatic conversion that I miss. Here is the result.