Crate docopt [] [src]

Docopt for Rust. This implementation conforms to the official description of Docopt and passes its test suite.

This library is on GitHub.

Fundamentally, Docopt is a command line argument parser. The detail that distinguishes it from most parsers is that the parser is derived from the usage string. Here's a simple example:

use docopt::Docopt;

// Write the Docopt usage string.
const USAGE: &'static str = "
Usage: cp [-a] <source> <dest>
       cp [-a] <source>... <dir>

Options:
    -a, --archive  Copy everything.
";

// The argv. Normally you'd just use `parse` which will automatically
// use `std::env::args()`.
let argv = || vec!["cp", "-a", "file1", "file2", "dest/"];

// Parse argv and exit the program with an error message if it fails.
let args = Docopt::new(USAGE)
                  .and_then(|d| d.argv(argv().into_iter()).parse())
                  .unwrap_or_else(|e| e.exit());

// Now access your argv values. Synonyms work just fine!
assert!(args.get_bool("-a") && args.get_bool("--archive"));
assert_eq!(args.get_vec("<source>"), vec!["file1", "file2"]);
assert_eq!(args.get_str("<dir>"), "dest/");
assert_eq!(args.get_str("<dest>"), "");

Type based decoding

Often, command line values aren't just strings or booleans---sometimes they are integers, or enums, or something more elaborate. Using the standard Docopt interface can be inconvenient for this purpose, because you'll need to convert all of the values explicitly. Instead, this crate provides a Decoder that converts an ArgvMap to your custom struct. Here is the same example as above using type based decoding:

#[macro_use]
extern crate serde_derive;
use docopt::Docopt;

// Write the Docopt usage string.
const USAGE: &'static str = "
Usage: cp [-a] <source> <dest>
       cp [-a] <source>... <dir>

Options:
    -a, --archive  Copy everything.
";

#[derive(Deserialize)]
struct Args {
    arg_source: Vec<String>,
    arg_dest: String,
    arg_dir: String,
    flag_archive: bool,
}

let argv = || vec!["cp", "-a", "file1", "file2", "dest/"];
let args: Args = Docopt::new(USAGE)
                        .and_then(|d| d.argv(argv().into_iter()).deserialize())
                        .unwrap_or_else(|e| e.exit());

// Now access your argv values.
fn s(x: &str) -> String { x.to_string() }
assert!(args.flag_archive);
assert_eq!(args.arg_source, vec![s("file1"), s("file2")]);
assert_eq!(args.arg_dir, s("dest/"));
assert_eq!(args.arg_dest, s(""));

Command line arguments for rustc

Here's an example with a subset of rustc's command line arguments that shows more of Docopt and some of the benefits of type based decoding.

#[macro_use]
extern crate serde_derive;
extern crate serde;
use docopt::Docopt;
use std::fmt;

// Write the Docopt usage string.
const USAGE: &'static str = "
Usage: rustc [options] [--cfg SPEC... -L PATH...] INPUT
       rustc (--help | --version)

Options:
    -h, --help         Show this message.
    --version          Show the version of rustc.
    --cfg SPEC         Configure the compilation environment.
    -L PATH            Add a directory to the library search path.
    --emit TYPE        Configure the output that rustc will produce.
                       Valid values: asm, ir, bc, obj, link.
    --opt-level LEVEL  Optimize with possible levels 0-3.
";

#[derive(Deserialize)]
struct Args {
    arg_INPUT: String,
    flag_emit: Option<Emit>,
    flag_opt_level: Option<OptLevel>,
    flag_cfg: Vec<String>,
    flag_L: Vec<String>,
    flag_help: bool,
    flag_version: bool,
}

// This is easy. The decoder will automatically restrict values to
// strings that match one of the enum variants.
#[derive(Deserialize)]
enum Emit { Asm, Ir, Bc, Obj, Link }

// This one is harder because we want the user to specify an integer,
// but restrict it to a specific range. So we implement `Deserialize`
// ourselves.
enum OptLevel { Zero, One, Two, Three }
struct OptLevelVisitor;

impl<'de> serde::de::Visitor<'de> for OptLevelVisitor {
    type Value = OptLevel;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a number from range 0..3")
    }

    fn visit_u8<E>(self, n: u8) -> Result<Self::Value, E>
        where E: serde::de::Error
    {
        Ok(match n {
            0 => OptLevel::Zero, 1 => OptLevel::One,
            2 => OptLevel::Two, 3 => OptLevel::Three,
            n => {
                let err = format!(
                    "Could not deserialize '{}' as opt-level.", n);
                return Err(E::custom(err));
            }
        })
    }
}

impl<'de> serde::de::Deserialize<'de> for OptLevel {
    fn deserialize<D>(d: D) -> Result<OptLevel, D::Error>
        where D: serde::de::Deserializer<'de>
    {
        d.deserialize_u8(OptLevelVisitor)
    }
}

let argv = || vec!["rustc", "-L", ".", "-L", "..", "--cfg", "a",
                            "--opt-level", "2", "--emit=ir", "docopt.rs"];
let args: Args = Docopt::new(USAGE)
                        .and_then(|d| d.argv(argv().into_iter()).deserialize())
                        .unwrap_or_else(|e| e.exit());

// Now access your argv values.
fn s(x: &str) -> String { x.to_string() }
assert_eq!(args.arg_INPUT, "docopt.rs".to_string());
assert_eq!(args.flag_L, vec![s("."), s("..")]);
assert_eq!(args.flag_cfg, vec![s("a")]);
assert_eq!(args.flag_opt_level, Some(OptLevel::Two));
assert_eq!(args.flag_emit, Some(Emit::Ir));

The docopt! macro

This package comes bundled with an additional crate, docopt_macros, which provides a docopt! syntax extension. Its purpose is to automate the creation of a Rust struct from a Docopt usage string. In particular, this provides a single point of truth about the definition of command line arguments in your program.

Another advantage of using the macro is that errors in your Docopt usage string will be caught at compile time. Stated differently, your program will not compile with an invalid Docopt usage string.

The example above using type based decoding can be simplified to this:

Be careful when using this code, it's not being tested!
#![feature(plugin)]
#![plugin(docopt_macros)]

extern crate serde;

extern crate docopt;

// Write the Docopt usage string with the `docopt!` macro.
docopt!(Args, "
Usage: cp [-a] <source> <dest>
       cp [-a] <source>... <dir>

Options:
    -a, --archive  Copy everything.
")

fn main() {
    let argv = || vec!["cp", "-a", "file1", "file2", "dest/"];

    // Your `Args` struct has a single static method defined on it,
    // `docopt`, which will return a normal `Docopt` value.
    let args: Args = Args::docopt().deserialize().unwrap_or_else(|e| e.exit());

    // Now access your argv values.
    fn s(x: &str) -> String { x.to_string() }
    assert!(args.flag_archive);
    assert_eq!(args.arg_source, vec![s("file1"), s("file2")]);
    assert_eq!(args.arg_dir, s("dest/"));
    assert_eq!(args.arg_dest, s(""));
}

Structs

ArgvMap

A map containing matched values from command line arguments.

Deserializer

Deserializer for ArgvMap into your own Deserializeable types.

Docopt

The main Docopt type, which is constructed with a Docopt usage string.

Enums

Error

Represents the different types of Docopt errors.

Value

A matched command line value.