Rust-Docopt.rs: docopt — A Rust implementation of DocOpt

Docopt for Rust with automatic type based decoding (i.e., data validation). This implementation conforms to the official description of Docopt and passes its test suite.

Build status

Dual-licensed under MIT or the UNLICENSE.

Current status

This crate is unlikely to see significant future evolution. The primary reason to choose this crate for a new project is if you're specifically interested in using docopt syntax for your project. However, the wider docopt project is mostly unmaintained at this point.

Consider using clap or possibly structopt instead.

Documentation

https://docs.rs/docopt

Installation

This crate is fully compatible with Cargo. Just add it to your Cargo.toml:

[dependencies]
docopt = "1"
serde = { version = "1", features = ["derive"] }

Quick example

Here is a full working example. Notice that you can specify the types of each of the named values in the Docopt usage string. Values will be automatically converted to those types (or an error will be reported).

use docopt::Docopt;
use serde::Deserialize;

const USAGE: &'static str = "
Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.
";

#[derive(Debug, Deserialize)]
struct Args {
    flag_speed: isize,
    flag_drifting: bool,
    arg_name: Vec<String>,
    arg_x: Option<i32>,
    arg_y: Option<i32>,
    cmd_ship: bool,
    cmd_mine: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());
    println!("{:?}", args);
}

Struct field name mapping

The field names of the struct map like this:

-g            => flag_g
--group       => flag_group
--group <arg> => flag_group
FILE          => arg_FILE
<file>        => arg_file
build         => cmd_build

Traditional Docopt API

The reference implementation of Docopt returns a Python dictionary with names like <arg> or --flag. If you prefer this access pattern, then you can use docopt::ArgvMap. The disadvantage is that you have to do all of your type conversion manually. Here's the canonical Docopt example with a hash table:

use docopt::Docopt;

const USAGE: &'static str = "
Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.
";

fn main() {
    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());
    println!("{:?}", args);

    // You can conveniently access values with `get_{bool,count,str,vec}`
    // functions. If the key doesn't exist (or if, e.g., you use `get_str` on
    // a switch), then a sensible default value is returned.
    println!("\nSome values:");
    println!("  Speed: {}", args.get_str("--speed"));
    println!("  Drifting? {}", args.get_bool("--drifting"));
    println!("  Names: {:?}", args.get_vec("<name>"));
}

Tab completion support

This particular implementation bundles a command called docopt-wordlist that can be used to automate tab completion. This repository also collects some basic completion support for various shells (currently only bash) in the completions directory.

You can use them to setup tab completion on your system. It should work with any program that uses Docopt (or rather, any program that outputs usage messages that look like Docopt). For example, to get tab completion support for Cargo, you'll have to install docopt-wordlist and add some voodoo to your $HOME/.bash_completion file (this may vary for other shells).

Here it is step by step:

# Download and build `docopt-wordlist` (as part of the Docopt package)
$ git clone git://github.com/docopt/docopt.rs
$ cd docopt.rs
$ cargo build --release

# Now setup tab completion (for bash)
$ echo "DOCOPT_WORDLIST_BIN=\"$(pwd)/target/release/docopt-wordlist\"" >> $HOME/.bash_completion
$ echo "source \"$(pwd)/completions/docopt-wordlist.bash\"" >> $HOME/.bash_completion
$ echo "complete -F _docopt_wordlist_commands cargo" >> $HOME/.bash_completion

My CSV toolkit is supported too:

# shameless plug...
$ echo "complete -F _docopt_wordlist_commands xsv" >> $HOME/.bash_completion

Note that this is emphatically a first pass. There are several improvements that I'd like to make:

  1. Take context into account when completing. For example, it should be possible to only show completions that can lead to a valid Docopt match. This may be hard. (i.e., It may require restructuring Docopt's internals.)
  2. Support more shells. (I'll happily accept pull requests on this one. I doubt I'll venture outside of bash any time soon.)
  3. Make tab completion support more seamless. The way it works right now is pretty hacky by intermingling file/directory completion.

Comments

  • When repeated short and long =value flags are aliases, only one is deserialised
    When repeated short and long =value flags are aliases, only one is deserialised

    Sep 3, 2018

    Sorry for the title... essentially when [-a... | --long-a=<val>] the value is only deserialised for the one specified in the struct. Contrast [-b | --bee] as Boolean flags, when the value of whichever is given is available as e.g. flag_bee; flag_b need not be specified.


    Here's a reproduction:

    [dependencies]
    docopt = { version = "1.0.1"}
    log = {version = "0.4.5"}
    serde = { version = "1.0.76" }
    serde_derive = { version = "1.0.76" }
    stderrlog = { version = "0.4.1"}
    
    extern crate docopt;
    #[macro_use]
    extern crate log;
    #[macro_use]
    extern crate serde_derive;
    extern crate stderrlog;
    
    use docopt::Docopt;
    
    const USAGE: &'static str = "
    Reproduction.
    
    Usage:
      repro [-q | --quiet | -v... | --verbosity=<v>]
    
    Options:
      -q --quiet                Disable stderr logging.
      -v... --verbosity=<v>     Verbosity of stderr logging.
    ";
    
    #[derive(Debug, Deserialize)]
    struct Args {
        flag_quiet: bool,
        flag_verbosity: usize,
    }
    
    fn main() {
       let args: Args = Docopt::new(USAGE)
            .and_then(|d| d.deserialize())
            .unwrap_or_else(|e| e.exit());
    
        println!("{:?}", args);
    
        stderrlog::new()
                .module(module_path!())
                .quiet(args.flag_quiet)
                .timestamp(stderrlog::Timestamp::Second)
                .verbosity(args.flag_verbosity)
                .init()
                .unwrap();
        trace!("trace message");
        debug!("debug message");
        info!("info message");
        warn!("warn message");
        error!("error message");
    }
    

    Then:

    $ cargo run -- --verbosity=2
    Args { flag_quiet: false, flag_verbosity: 2 }
    2018-09-03T20:50:56+01:00 - INFO - info message
    2018-09-03T20:50:56+01:00 - WARN - warn message
    2018-09-03T20:50:56+01:00 - ERROR - error message
    

    so far so good.

    $ cargo run -- -vvv
    Args { flag_quiet: false, flag_verbosity: 0 }
    2018-09-03T20:51:43+01:00 - ERROR - error message
    

    Not so good. I thought maybe the issue was using the short while deserialising the long name, but:

    $ cargo run -- -q
    Args { flag_quiet: true, flag_verbosity: 0 }
    

    so it does appear to be the interaction between ... and =<v>.


    Less-than-ideal workaround with particular respect to integer flags, just in case someone stumbles here with a similar use case:

    • separate lines in Options
    • add flag_v: usize, toArgs
    • .verbosity(args.flag_verbosity + args.flag_v) (since docopt takes care of at most one being non-zero)
    Reply
  • trouble with argument lists split over multiple lines
    trouble with argument lists split over multiple lines

    Sep 20, 2018

    The following works in Python:

    import docopt
    
    __doc__ = """\
    Usage: test.py [--flag]
                   [--another]
    """
    
    args = docopt.docopt(__doc__)
    print(args)
    
    $ ./test.py --flag          
    {'--another': False,
     '--flag': True}
    $ ./test.py --another
    {'--another': True,
     '--flag': False}
    $ ./test.py --flag --another
    {'--another': True,
     '--flag': True}
    

    The equivalent has trouble in docopt.rs:

    #[macro_use]
    extern crate serde_derive;
    extern crate docopt;
    
    const USAGE: &str = "\
    Usage: test [--flag]
                [--another]
    ";
    
    #[derive(Debug, Deserialize)]
    struct Args {
        flag_flag: bool,
        flag_another: bool,
    }
    
    fn main() {
        let args: Args = docopt::Docopt::new(USAGE)
            .and_then(|d| d.deserialize())
            .unwrap_or_else(|e| e.exit());
        println!("{:?}", args);
    }
    
    $ ./test --flag
    Args { flag_flag: true, flag_another: false }
    $ ./test --another
    Args { flag_flag: false, flag_another: true }
    $ ./test --flag --another
    Invalid arguments.
    
    Usage: test [--flag]
                [--another]
    

    It seems like the Rust implementation is interpreting those two lines as two separate argument lists (where the second one is allowed to omit the executable name?), rather than combining them into one. Does that sound like the right interpretation? Do you know of any workarounds currently, besides just avoiding newlines in the docstring?

    Reply
  • update strsim to 0.8
    update strsim to 0.8

    Oct 7, 2018

                                                                                                                                                                                                           
    Reply
  • Allow Overlapping Option and Usage Flags for Documentation
    Allow Overlapping Option and Usage Flags for Documentation

    Mar 24, 2019

    I'm trying to write the following doc string to have a form for the -s flag, and also provide it documentation.

    Usage:
        oursh -c [options] <command_string> [<command_name> [<arguments>...]]
    
    Options:
        -c  read commands from the `command_string` operand. set the value of
            special parameter 0 (see section 2.5.2, special parameters) from the
            value of the `command_name` operand and the positional parameters
            ($2, $2, and so on) in sequence from the remaining `arguments`
            operands. no commands shall be read from the standard input.
    

    Is this possible?

    Reply
  • -h in priority
    -h in priority

    Jun 27, 2019

    When calling a binary, some users forget how some arguments work and simply add a -h to see the help again, without removing all parameters.

    job a/long/path.gz another/long/path.gz a/long/path/again.gz -h
    

    In some libs, like argparse, this prints the complete help message, as if you used job -h. With docopt-rs, it does print the usage message, but doesn't actually care about the -h. It would print the same thing with a non-existing parameter.

    Invalid arguments.
    
    Usage:
        job ...
    

    tl;rd it would be nice to print the whole help message with -h, even if there are other args.

    Reply
  • Optional argument parsed as None instead of Some(_) if using '_' in option name
    Optional argument parsed as None instead of Some(_) if using '_' in option name

    Jul 26, 2019

    The following example:

    use docopt::Docopt;
    use serde::Deserialize;
    
    const USAGE: &'static str = "
    Test.
    
    Usage:
      test [--cache_dir=<cache_dir>]
    
    Options:
      --cache_dir=<cache_dir>  enables cache
    ";
    
    #[derive(Debug, Deserialize)]
    struct Args {
        flag_cache_dir: Option<String>,
    }
    
    fn main() {
        let args: Args = Docopt::new(USAGE)
            .and_then(|d| d.deserialize())
            .unwrap_or_else(|e| e.exit());
        println!("{:?}", args);
    }
    

    Gives result:

    $ cargo run -- --cache_dir=abc
        Finished dev [unoptimized + debuginfo] target(s) in 0.03s
         Running `target\debug\docopt-test.exe --cache_dir=abc`
    Args { flag_cache_dir: None }
    

    If option name is changed to --cache-dir, then it parses the optional argument correctly:

    Test.
    
    Usage:
      test [--cache-dir=<cache_dir>]
    
    Options:
      --cache-dir=<cache_dir>  enables cache
    
    $ cargo run -- --cache-dir=abc
        Finished dev [unoptimized + debuginfo] target(s) in 0.04s
         Running `target\debug\docopt-test.exe --cache-dir=abc`
    Args { flag_cache_dir: Some("abc") }
    
    Reply
  • Migrate from rustc-serialize to serde 1.0
    Migrate from rustc-serialize to serde 1.0

    May 30, 2017

    This is a breaking change.

    • decode() is renamed to deserialize() for consistency with serde
    • docopt_macros is updated to latest nightly

    Fixes #128, #213

    Reply
  • Add initial implementation of suggestions
    Add initial implementation of suggestions

    Feb 21, 2015

    Initial implementation of suggestions for unknown flags.

    Given Usage: testing [--release], docopt will behave like this:

    $ testing --rlease
    Unknown flag: '--rlease'. Did you mean '--release'?
    
    Usage: testing [--release]
    

    Closes #98

    Reply
  • very slow on large argument string
    very slow on large argument string

    Aug 31, 2016

    Rust program:

    extern crate docopt;
    extern crate rustc_serialize;
    
    const USAGE: &'static str = "
    Usage:
        bindgen [options] \
            [--link=<lib>...] \
            [--static-link=<lib>...] \
            [--framework-link=<framework>...] \
            [--match=<name>...] \
            [--raw-line=<raw>...] \
            [--dtor-attr=<attr>...] \
            [--opaque-type=<type>...] \
            [--blacklist-type=<type>...] \
            <input-header> \
            [-- <clang-args>...]
        bindgen (-h | --help)
    Options:
        -h, --help                    Display this help message.
        -l=<lib>, --link=<lib>        Link to a dynamic library, can be provided
                                      multiple times.
        --static-link=<lib>           Link to a static library, can be provided
                                      multiple times.
        --framework-link=<framework>  Link to a framework.
        -o=<outputrustfile>           Write bindings to <output-rust-file>
        --match=<name>                Only output bindings for definitions from
                                      files whose name contains <name>. If multiple
                                      match options are provided, files matching any
                                      rule are bound to.
        --builtins                    Output bindings for builtin definitions
        --ignore-functions            Don't generate bindings for functions and
                                      methods. This is useful when you only care
                                      about struct layouts.
        --enable-cxx-namespaces       Enable support for C++ namespaces.
        --no-type-renaming            Don't rename types.
        --allow-unknown-types         Don't fail if we encounter types we do not
                                      support, instead treat them as void
        --emit-clang-ast              Output the ast
        --use-msvc-mangling           Handle MSVC C++ ABI mangling; requires that
                                      target be set to
        --override-enum-type=<type>   Override enum type, type name could be
                                        uchar
                                        schar
                                        ushort
                                        sshort
                                        uint
                                        sint
                                        ulong
                                        slong
                                        ulonglong
                                        slonglong
        --raw-line=<raw>              TODO
        --dtor-attr=<attr>            TODO
        --no-class-constants          TODO
        --no-unstable-rust            TODO
        --no-namespaced-constants     TODO
        --no-bitfield-methods         TODO
        --ignore-methods              TODO
        --opaque-type=<type>          TODO
        --blacklist-type=<type>       TODO
        <clang-args>                  Options other than stated above are passed
                                      directly through to clang.
    ";
    
    #[derive(Debug, RustcDecodable)]
    struct Args {
        arg_input_header: String,
        flag_link: Vec<String>,
        flag_static_link: Vec<String>,
        flag_framework_link: Vec<String>,
        flag_o: Option<String>,
        flag_match: Vec<String>,
        flag_builtins: bool,
        flag_ignore_functions: bool,
        flag_enable_cxx_namespaces: bool,
        flag_no_type_renaming: bool,
        flag_allow_unknown_types: bool,
        flag_emit_clang_ast: bool,
        flag_use_msvc_mangling: bool,
        flag_override_enum_type: String,
        flag_raw_line: Vec<String>,
        flag_dtor_attr: Vec<String>,
        flag_no_class_constants: bool,
        flag_no_unstable_rust: bool,
        flag_no_namespaced_constants: bool,
        flag_no_bitfield_methods: bool,
        flag_ignore_methods: bool,
        flag_opaque_type: Vec<String>,
        flag_blacklist_type: Vec<String>,
        arg_clang_args: Vec<String>,
    }
    
    
    fn main() {
        let args: Args = docopt::Docopt::new(USAGE)
            .and_then(|d| d.decode())
            .unwrap_or_else(|e| e.exit());
        println!("{:?}", args);
    }
    

    Argv string:

    ./target/release/docopt-slow --allow-unknown-types --no-unstable-rust --no-type-renaming --no-namespaced-constants --ignore-methods --raw-line use\ heapsize::HeapSizeOf\; --match ServoBindingList.h --match ServoBindings.h --match nsStyleStructList.h --raw-line pub\ enum\ nsINode\ \{\} --raw-line pub\ enum\ nsIDocument\ \{\} --raw-line pub\ enum\ nsIPrincipal\ \{\} --raw-line pub\ enum\ nsIURI\ \{\} --blacklist-type ServoComputedValuesStrong --raw-line pub\ type\ ServoComputedValuesStrong\ =\ ::sugar::ownership::Strong\<ServoComputedValues\>\; --blacklist-type ServoComputedValuesMaybeBorrowed -raw-line pub\ type\ ServoComputedValuesMaybeBorrowed\<\'a\>\ =\ ::sugar::ownership::Borrowed\<\'a,\ ServoComputedValues\>\; -blacklist-type ServoComputedValues -raw-line pub\ enum\ ServoComputedValuesVoid\{\ \} -raw-line pub\ struct\ ServoComputedValues\(ServoComputedValuesVoid\)\; --blacklist-type RawServoStyleSheetStrong --raw-line pub\ type\ RawServoStyleSheetStrong\ =\ ::sugar::ownership::Strong\<RawServoStyleSheet\>\; --blacklist-type RawServoStyleSheetMaybeBorrowed -raw-line pub\ type\ RawServoStyleSheetMaybeBorrowed\<\'a\>\ =\ ::sugar::ownership::Borrowed\<\'a,\ RawServoStyleSheet\>\; -blacklist-type RawServoStyleSheet -raw-line pub\ enum\ RawServoStyleSheetVoid\{\ \} -raw-line pub\ struct\ RawServoStyleSheet\(RawServoStyleSheetVoid\)\; --blacklist-type ServoDeclarationBlockStrong --raw-line pub\ type\ ServoDeclarationBlockStrong\ =\ ::sugar::ownership::Strong\<ServoDeclarationBlock\>\; --blacklist-type ServoDeclarationBlockMaybeBorrowed -raw-line pub\ type\ ServoDeclarationBlockMaybeBorrowed\<\'a\>\ =\ ::sugar::ownership::Borrowed\<\'a,\ ServoDeclarationBlock\>\; -blacklist-type ServoDeclarationBlock -raw-line pub\ enum\ ServoDeclarationBlockVoid\{\ \} -raw-line pub\ struct\ ServoDeclarationBlock\(ServoDeclarationBlockVoid\)\; -blacklist-type RawGeckoNodeBorrowed --raw-line pub\ type\ RawGeckoNodeBorrowed\<\'a\>\ =\ \&\'a\ RawGeckoNode\; --blacklist-type RawGeckoNodeMaybeBorrowed --raw-line pub\ type\ RawGeckoNodeMaybeBorrowed\<\'a\>\ =\ ::sugar::ownership::Borrowed\<\'a,\ RawGeckoNode\>\; -blacklist-type RawGeckoNode -raw-line pub\ enum\ RawGeckoNodeVoid\{\ \} -raw-line pub\ struct\ RawGeckoNode\(RawGeckoNodeVoid\)\; -blacklist-type RawGeckoElementBorrowed --raw-line pub\ type\ RawGeckoElementBorrowed\<\'a\>\ =\ \&\'a\ RawGeckoElement\; --blacklist-type RawGeckoElementMaybeBorrowed --raw-line pub\ type\ RawGeckoElementMaybeBorrowed\<\'a\>\ =\ ::sugar::ownership::Borrowed\<\'a,\ RawGeckoElement\>\; -blacklist-type RawGeckoElement -raw-line pub\ enum\ RawGeckoElementVoid\{\ \} -raw-line pub\ struct\ RawGeckoElement\(RawGeckoElementVoid\)\; -blacklist-type RawGeckoDocumentBorrowed --raw-line pub\ type\ RawGeckoDocumentBorrowed\<\'a\>\ =\ \&\'a\ RawGeckoDocument\; --blacklist-type RawGeckoDocumentMaybeBorrowed --raw-line pub\ type\ RawGeckoDocumentMaybeBorrowed\<\'a\>\ =\ ::sugar::ownership::Borrowed\<\'a,\ RawGeckoDocument\>\; -blacklist-type RawGeckoDocument -raw-line pub\ enum\ RawGeckoDocumentVoid\{\ \} -raw-line pub\ struct\ RawGeckoDocument\(RawGeckoDocumentVoid\)\; --blacklist-type RawServoStyleSetBorrowed --raw-line pub\ type\ RawServoStyleSetBorrowed\<\'a\>\ =\ \&\'a\ RawServoStyleSet\; --blacklist-type RawServoStyleSetBorrowedMut --raw-line pub\ type\ RawServoStyleSetBorrowedMut\<\'a\>\ =\ \&\'a\ mut\ RawServoStyleSet\; --blacklist-type RawServoStyleSetOwned --raw-line pub\ type\ RawServoStyleSetOwned\ =\ ::sugar::ownership::Owned\<RawServoStyleSet\>\; -blacklist-type RawServoStyleSet -raw-line pub\ enum\ RawServoStyleSetVoid\{\ \} -raw-line pub\ struct\ RawServoStyleSet\(RawServoStyleSetVoid\)\; --blacklist-type ServoNodeDataMaybeBorrowed --raw-line pub\ type\ ServoNodeDataMaybeBorrowed\<\'a\>\ =\ ::sugar::ownership::Borrowed\<\'a,\ ServoNodeData\>\; --blacklist-type ServoNodeDataMaybeBorrowedMut --raw-line pub\ type\ ServoNodeDataMaybeBorrowedMut\<\'a\>\ =\ ::sugar::ownership::BorrowedMut\<\'a,\ ServoNodeData\>\; --blacklist-type ServoNodeDataMaybeOwned --raw-line pub\ type\ ServoNodeDataMaybeOwned\ =\ ::sugar::ownership::MaybeOwned\<ServoNodeData\>\; -blacklist-type ServoNodeData -raw-line pub\ enum\ ServoNodeDataVoid\{\ \} -raw-line pub\ struct\ ServoNodeData\(ServoNodeDataVoid\)\; --blacklist-type nsStyleFont --raw-line use\ structs::nsStyleFont\; --raw-line unsafe\ impl\ Send\ for\ nsStyleFont\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleFont\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleFont\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleColor --raw-line use\ structs::nsStyleColor\; --raw-line unsafe\ impl\ Send\ for\ nsStyleColor\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleColor\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleColor\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleList --raw-line use\ structs::nsStyleList\; --raw-line unsafe\ impl\ Send\ for\ nsStyleList\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleList\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleList\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleText --raw-line use\ structs::nsStyleText\; --raw-line unsafe\ impl\ Send\ for\ nsStyleText\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleText\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleText\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleVisibility --raw-line use\ structs::nsStyleVisibility\; --raw-line unsafe\ impl\ Send\ for\ nsStyleVisibility\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleVisibility\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleVisibility\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleUserInterface --raw-line use\ structs::nsStyleUserInterface\; --raw-line unsafe\ impl\ Send\ for\ nsStyleUserInterface\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleUserInterface\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleUserInterface\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleTableBorder --raw-line use\ structs::nsStyleTableBorder\; --raw-line unsafe\ impl\ Send\ for\ nsStyleTableBorder\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleTableBorder\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleTableBorder\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleSVG --raw-line use\ structs::nsStyleSVG\; --raw-line unsafe\ impl\ Send\ for\ nsStyleSVG\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleSVG\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleSVG\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleVariables --raw-line use\ structs::nsStyleVariables\; --raw-line unsafe\ impl\ Send\ for\ nsStyleVariables\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleVariables\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleVariables\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleBackground --raw-line use\ structs::nsStyleBackground\; --raw-line unsafe\ impl\ Send\ for\ nsStyleBackground\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleBackground\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleBackground\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStylePosition --raw-line use\ structs::nsStylePosition\; --raw-line unsafe\ impl\ Send\ for\ nsStylePosition\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStylePosition\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStylePosition\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleTextReset --raw-line use\ structs::nsStyleTextReset\; --raw-line unsafe\ impl\ Send\ for\ nsStyleTextReset\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleTextReset\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleTextReset\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleDisplay --raw-line use\ structs::nsStyleDisplay\; --raw-line unsafe\ impl\ Send\ for\ nsStyleDisplay\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleDisplay\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleDisplay\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleContent --raw-line use\ structs::nsStyleContent\; --raw-line unsafe\ impl\ Send\ for\ nsStyleContent\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleContent\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleContent\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleUIReset --raw-line use\ structs::nsStyleUIReset\; --raw-line unsafe\ impl\ Send\ for\ nsStyleUIReset\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleUIReset\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleUIReset\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleTable --raw-line use\ structs::nsStyleTable\; --raw-line unsafe\ impl\ Send\ for\ nsStyleTable\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleTable\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleTable\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleMargin --raw-line use\ structs::nsStyleMargin\; --raw-line unsafe\ impl\ Send\ for\ nsStyleMargin\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleMargin\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleMargin\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStylePadding --raw-line use\ structs::nsStylePadding\; --raw-line unsafe\ impl\ Send\ for\ nsStylePadding\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStylePadding\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStylePadding\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleBorder --raw-line use\ structs::nsStyleBorder\; --raw-line unsafe\ impl\ Send\ for\ nsStyleBorder\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleBorder\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleBorder\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleOutline --raw-line use\ structs::nsStyleOutline\; --raw-line unsafe\ impl\ Send\ for\ nsStyleOutline\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleOutline\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleOutline\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleXUL --raw-line use\ structs::nsStyleXUL\; --raw-line unsafe\ impl\ Send\ for\ nsStyleXUL\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleXUL\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleXUL\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleSVGReset --raw-line use\ structs::nsStyleSVGReset\; --raw-line unsafe\ impl\ Send\ for\ nsStyleSVGReset\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleSVGReset\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleSVGReset\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleColumn --raw-line use\ structs::nsStyleColumn\; --raw-line unsafe\ impl\ Send\ for\ nsStyleColumn\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleColumn\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleColumn\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleEffects --raw-line use\ structs::nsStyleEffects\; --raw-line unsafe\ impl\ Send\ for\ nsStyleEffects\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleEffects\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleEffects\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleImage --raw-line use\ structs::nsStyleImage\; --raw-line unsafe\ impl\ Send\ for\ nsStyleImage\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleImage\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleImage\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleGradient --raw-line use\ structs::nsStyleGradient\; --raw-line unsafe\ impl\ Send\ for\ nsStyleGradient\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleGradient\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleGradient\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleCoord --raw-line use\ structs::nsStyleCoord\; --raw-line unsafe\ impl\ Send\ for\ nsStyleCoord\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleCoord\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleCoord\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleGradientStop --raw-line use\ structs::nsStyleGradientStop\; --raw-line unsafe\ impl\ Send\ for\ nsStyleGradientStop\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleGradientStop\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleGradientStop\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleImageLayers --raw-line use\ structs::nsStyleImageLayers\; --raw-line unsafe\ impl\ Send\ for\ nsStyleImageLayers\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleImageLayers\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleImageLayers\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type Layer --raw-line use\ structs::nsStyleImageLayers_Layer\ as\ Layer\; --blacklist-type LayerType --raw-line use\ structs::nsStyleImageLayers_LayerType\ as\ LayerType\; --blacklist-type nsStyleUnit --raw-line use\ structs::nsStyleUnit\; --raw-line unsafe\ impl\ Send\ for\ nsStyleUnit\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleUnit\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleUnit\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type nsStyleUnion --raw-line use\ structs::nsStyleUnion\; --raw-line unsafe\ impl\ Send\ for\ nsStyleUnion\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleUnion\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleUnion\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type CalcValue --raw-line use\ structs::nsStyleCoord_CalcValue\ as\ CalcValue\; --blacklist-type Calc --raw-line use\ structs::nsStyleCoord_Calc\ as\ Calc\; --blacklist-type nsRestyleHint --raw-line use\ structs::nsRestyleHint\; --blacklist-type ServoElementSnapshot --raw-line use\ structs::ServoElementSnapshot\; --blacklist-type nsChangeHint --raw-line use\ structs::nsChangeHint\; --blacklist-type SheetParsingMode --raw-line use\ structs::SheetParsingMode\; --blacklist-type nsMainThreadPtrHandle --raw-line use\ structs::nsMainThreadPtrHandle\; --blacklist-type nsMainThreadPtrHolder --raw-line use\ structs::nsMainThreadPtrHolder\; --blacklist-type nscolor --raw-line use\ structs::nscolor\; --blacklist-type nsFont --raw-line use\ structs::nsFont\; --blacklist-type FontFamilyList --raw-line use\ structs::FontFamilyList\; --blacklist-type FontFamilyType --raw-line use\ structs::FontFamilyType\; --blacklist-type nsIAtom --raw-line use\ structs::nsIAtom\; --blacklist-type nsStyleContext --raw-line use\ structs::nsStyleContext\; --raw-line unsafe\ impl\ Send\ for\ nsStyleContext\ \{\} --raw-line unsafe\ impl\ Sync\ for\ nsStyleContext\ \{\} --raw-line impl\ HeapSizeOf\ for\ nsStyleContext\ \{\ fn\ heap_size_of_children\(\&self\)\ -\>\ usize\ \{\ 0\ \}\ \} --blacklist-type StyleClipPath --raw-line use\ structs::StyleClipPath\; --blacklist-type StyleBasicShapeType --raw-line use\ structs::StyleBasicShapeType\; --blacklist-type StyleBasicShape --raw-line use\ structs::StyleBasicShape\; --blacklist-type nsCSSShadowArray --raw-line use\ structs::nsCSSShadowArray\; -o ../gecko_bindings/bindings.rs -- -x c++ -std=c++14 -DTRACING=1 -DIMPL_LIBXUL -DMOZ_STYLO_BINDINGS=1 -DMOZILLA_INTERNAL_API -DRUST_BINDGEN -DOS_POSIX=1 -DOS_MACOSX=1 -I /Users/manishearth/mozilla/muon-central/obj-x86_64-apple-darwin15.3.0//dist/include -I /Users/manishearth/mozilla/muon-central/obj-x86_64-apple-darwin15.3.0//dist/include/nspr -I /Users/manishearth/mozilla/muon-central/obj-x86_64-apple-darwin15.3.0//../nsprpub/pr/include -include /Users/manishearth/mozilla/muon-central/obj-x86_64-apple-darwin15.3.0//mozilla-config.h /Users/manishearth/mozilla/muon-central/obj-x86_64-apple-darwin15.3.0//dist/include/mozilla/ServoBindings.h
    

    Not only does Docopt take a very long time, but it consumes a lot of memory as well.

    Originally reported in: https://github.com/servo/rust-bindgen/issues/46

    Reply
  • use serde
    use serde

    May 19, 2015

    I should start using serde for the automatic serialization component of this crate.

    I don't think this means removing support for rustc-serialize just yet though.

    Reply
  • Use a working license instead of UNLICENSE
    Use a working license instead of UNLICENSE

    Jul 7, 2014

    [I posted this in your Reddit thread, but it should be an actual issue.]

    Please don't use UNLICENSE for your license. It doesn't actually work. All uses of UNLICENSE can be replaced with uses of the Apache 2 license (which actually works); you get the same "do whatever you want with it" support without causing your users pain because your license makes no legal sense.

    Apache 2 really is what you want; unlike the MIT license, it covers the following as well:

    • Any patches you receive are also licensed under Apache 2. MIT says nothing on this and thus leaves any project using it in a weird state after merging in external contributions.
    • It gives a patent license as well.
    • Other minor useful tidbits.

    I've made the mistake of using UNLICENSE myself before; learn from my experience.

    Reply
  • Relicense under dual MIT/Apache-2.0
    Relicense under dual MIT/Apache-2.0

    Jan 10, 2016

    This issue was automatically generated. Feel free to close without ceremony if you do not agree with re-licensing or if it is not possible for other reasons. Respond to @cmr with any questions or concerns, or pop over to #rust-offtopic on IRC to discuss.

    You're receiving this because someone (perhaps the project maintainer) published a crates.io package with the license as "MIT" xor "Apache-2.0" and the repository field pointing here.

    TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that license is good for interoperation. The MIT license as an add-on can be nice for GPLv2 projects to use your code.

    Why?

    The MIT license requires reproducing countless copies of the same copyright header with different names in the copyright field, for every MIT library in use. The Apache license does not have this drawback. However, this is not the primary motivation for me creating these issues. The Apache license also has protections from patent trolls and an explicit contribution licensing clause. However, the Apache license is incompatible with GPLv2. This is why Rust is dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for GPLv2 compat), and doing so would be wise for this project. This also makes this crate suitable for inclusion and unrestricted sharing in the Rust standard distribution and other projects using dual MIT/Apache, such as my personal ulterior motive, the Robigalia project.

    Some ask, "Does this really apply to binary redistributions? Does MIT really require reproducing the whole thing?" I'm not a lawyer, and I can't give legal advice, but some Google Android apps include open source attributions using this interpretation. Others also agree with it. But, again, the copyright notice redistribution is not the primary motivation for the dual-licensing. It's stronger protections to licensees and better interoperation with the wider Rust ecosystem.

    How?

    To do this, get explicit approval from each contributor of copyrightable work (as not all contributions qualify for copyright, due to not being a "creative work", e.g. a typo fix) and then add the following to your README:

    ## License
    
    Licensed under either of
    
     * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
     * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
    
    at your option.
    
    ### Contribution
    
    Unless you explicitly state otherwise, any contribution intentionally submitted
    for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
    additional terms or conditions.
    

    and in your license headers, if you have them, use the following boilerplate (based on that used in Rust):

    // Copyright 2016 docopt.rs Developers
    //
    // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
    // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
    // http://opensource.org/licenses/MIT>, at your option. This file may not be
    // copied, modified, or distributed except according to those terms.
    

    It's commonly asked whether license headers are required. I'm not comfortable making an official recommendation either way, but the Apache license recommends it in their appendix on how to use the license.

    Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these from the Rust repo for a plain-text version.

    And don't forget to update the license metadata in your Cargo.toml to:

    license = "MIT OR Apache-2.0"
    

    I'll be going through projects which agree to be relicensed and have approval by the necessary contributors and doing this changes, so feel free to leave the heavy lifting to me!

    Contributor checkoff

    To agree to relicensing, comment with :

    I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.
    

    Or, if you're a contributor, you can check the box in this repo next to your name. My scripts will pick this exact phrase up and check your checkbox, but I'll come through and manually review this issue later as well.

    • [ ] @BurntSushi
    • [x] @CraZySacX
    • [x] @FuGangqiang
    • [x] @alex-gulyas
    • [x] @alexchandel
    • [ ] @alexcrichton
    • [x] @andars
    • [x] @birkenfeld
    • [ ] @bkoropoff
    • [x] @brandonson
    • [x] @btobolaski
    • [x] @carllerche
    • [x] @cburgdorf
    • [x] @crumblingstatue
    • [x] @dguo
    • [x] @dotdash
    • [x] @drbawb
    • [x] @eliovir
    • [x] @gchp
    • [x] @globin
    • [x] @hauleth
    • [ ] @ianbollinger
    • [x] @jauhien
    • [x] @jgillich
    • [x] @kinghajj
    • [x] @ktossell
    • [ ] @leighlondon
    • [x] @leodasvacas
    • [x] @leonkunert
    • [x] @maxsnew
    • [x] @msiemens
    • [x] @netvl
    • [x] @nixpulvis
    • [x] @nrc
    • [x] @pcn
    • [x] @renato-zannon
    • [x] @samdolt
    • [ ] @saneyuki
    • [x] @shadowmint
    • [ ] @simonask
    • [x] @steveklabnik
    • [x] @tgkokk
    • [x] @tmerr
    • [x] @wwendell
    • [x] @zsiciarz
    Reply