Docopt for Rust (command line argument parser).

Overview

THIS CRATE IS UNMAINTAINED

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.

Note that this crate has some significant bugs. The two biggest ones are the lack of OsStr support and some severe performance problems in not-uncommon edge cases.

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.

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
  • Relicense under dual MIT/Apache-2.0

    Relicense under dual MIT/Apache-2.0

    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
    opened by emberian 45
  • Use a working license instead of UNLICENSE

    Use a working license instead of UNLICENSE

    [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.

    opened by Valloric 27
  • use serde

    use serde

    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.

    opened by BurntSushi 15
  • very slow on large argument string

    very slow on large argument string

    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

    opened by BurntSushi 14
  • Add initial implementation of suggestions

    Add initial implementation of suggestions

    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

    opened by andars 10
  • Migrate from rustc-serialize to serde 1.0

    Migrate from rustc-serialize to serde 1.0

    This is a breaking change.

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

    Fixes #128, #213

    opened by ordian 9
  • Docopt can cause a process to block when used before random pool is initialized

    Docopt can cause a process to block when used before random pool is initialized

    Docopt can cause a process to block if the /dev/urandom pool has not yet been initialized.

    Background

    On more recent kernels (>3.17), the getrandom syscall has been introduced. This syscall is used by OsRng when getting a random number. The current syscall args cause it to block until the /dev/urandom pool has been initialized. The default implementation of HashMap uses RandomState for its default hasher. RandomState uses the rand crate which blocks until the /dev/urandom pool has been initialized.

    System Setup

    Ubuntu 15.10 Rust 1.7.0

    GDB Backtrace

    Catchpoint 1 (call to syscall 318), syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
    38  ../sysdeps/unix/sysv/linux/x86_64/syscall.S: No such file or directory.
    (gdb) bt
    #0  syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
    #1  0x00005555558190f5 in rand::StdRng::new::h7f6f37b37bd8a656XMy ()
    #2  0x0000555555819446 in rand::thread_rng::THREAD_RNG_KEY::__init::hee923a4dca76e52cqQy ()
    #3  0x0000555555801fee in rand::thread_rng::hf965b6c3dc392e76dQy ()
    #4  0x0000555555629888 in docopt::collections::hash::map::RandomState::new () at ../src/libstd/collections/hash/map.rs:1638
    #5  0x0000555555629864 in docopt::collections::hash::map::RandomState.Default::default () at ../src/libstd/collections/hash/map.rs:1656
    #6  0x000055555562ee6f in docopt::collections::hash::map::HashMap<K, V, S>.Default::default () at ../src/libstd/collections/hash/map.rs:1261
    #7  0x000055555562ee44 in docopt::collections::hash::map::HashMap<K, V, RandomState>::new () at ../src/libstd/collections/hash/map.rs:512
    #8  0x000055555562edef in docopt::synonym::SynonymMap<K, V>::new () at /root/.cargo/registry/src/github.com-88ac128001ac3a9a/docopt-0.6.78/src/synonym.rs:17
    #9  0x000055555562e704 in docopt::parse::Parser::new (doc=...) at /root/.cargo/registry/src/github.com-88ac128001ac3a9a/docopt-0.6.78/src/parse.rs:78
    #10 0x00005555555cb238 in myprog::dopt::Docopt::new<&str> (usage=...) at /root/.cargo/registry/src/github.com-88ac128001ac3a9a/docopt-0.6.78/src/dopt.rs:177
    #11 0x00005555555c7dc2 in myprog::main () at src/main.rs:101
    #12 0x0000555555818505 in sys_common::unwind::try::try_fn::h9896872240422604242 ()
    #13 0x00005555558157a9 in __rust_try ()
    #14 0x0000555555818191 in rt::lang_start::h0d9dcd8707a91319Uoy ()
    #15 0x00005555555f518a in main () at ../src/libcollections/string.rs:1734
    
    

    This may be solved by using a hasher that does not rely on the random pool being initialized.

    opened by derekstraka 8
  • Compiling tests fails

    Compiling tests fails

    After cloning the repository, I tried to run cargo test, but it fails with

    docopt.rs/examples/macro.rs:4:18: 4:45 error: can't find crate for `docopt_macros`
    docopt.rs/examples/macro.rs:4 #[phase(plugin)] extern crate docopt_macros;
                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    docopt.rs/examples/cp.rs:3:18: 3:45 error: can't find crate for `docopt_macros`
    docopt.rs/examples/cp.rs:3 #[phase(plugin)] extern crate docopt_macros;
                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    error: aborting due to previous error
    error: aborting due to previous error
    Build failed, waiting for other jobs to finish...
    docopt.rs/examples/rustc.rs:3:18: 3:45 error: can't find crate for `docopt_macros`
    docopt.rs/examples/rustc.rs:3 #[phase(plugin)] extern crate docopt_macros;
                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    error: aborting due to previous error
    docopt.rs/examples/add.rs:4:18: 4:45 error: can't find crate for `docopt_macros`
    docopt.rs/examples/add.rs:4 #[phase(plugin)] extern crate docopt_macros;
                                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    The same problem occurs while running directly rustc: rustc -L ./build examples/add.rs

    examples/add.rs:4:18: 4:45 error: can't find crate for `docopt_macros`
    examples/add.rs:4 #[phase(plugin)] extern crate docopt_macros;
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    error: aborting due to previous error
    
    opened by eliovir 8
  • Examples don't compile any more

    Examples don't compile any more

    This is the one I tried: https://github.com/docopt/docopt.rs/blob/master/examples/cargo.rs

    Rustc says that the trait rustc-serialize::serialize::Decodable is not implemented for the type Args.

    opened by marcusklaas 7
  • Multiple regex crates warnings

    Multiple regex crates warnings

    Building on the latest nightly gives some warnings about multiple versions of the regex crate. Any ideas how to remove these?

       Compiling docopt v0.6.18
    warning: using multiple versions of crate `regex`
    /home/gchp/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.18/src/lib.rs:217:1: 217:24 note: used here
    /home/gchp/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.18/src/lib.rs:217 extern crate serialize;
                                                                                            ^~~~~~~~~~~~~~~~~~~~~~~
    note: crate name: regex
    /home/gchp/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.18/src/lib.rs:216:1: 216:20 note: used here
    /home/gchp/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.18/src/lib.rs:216 extern crate regex;
                                                                                            ^~~~~~~~~~~~~~~~~~~
    
    opened by gchp 7
  • remove regex! (replace with Regex::new)

    remove regex! (replace with Regex::new)

    It's my understanding that with Rust 1.0, syntax extensions will be disabled, which means no more regex!. Therefore, for Docopt to work with Rust 1.0, it cannot use regex!.

    @alexcrichton Is my understanding right here?

    opened by BurntSushi 6
  • [Issue] Optional arguments in final array

    [Issue] Optional arguments in final array

    Describe the bug Found a bug with optional arguments and final array.

    To Reproduce Define a docopt like this one in a shell script:

    #!/usr/bin/env bash
    ##? Install a package
    ##?
    ##? Usage:
    ##?    $0 [--pkgmgr <package_manager>] <packages_names>...
    eval "$(docpars -h "$(grep "^##?" "$0" | cut -c 5-)" : "$@")"
    echo "pkgmgr: $pkgmgr"
    echo "package_manager: $package_manager"
    echo "packages: ${package_names[*]}"
    echo
    

    Call the script with arguments:

    --pkgmgr cargo docpars deno bashdoc
    

    Show output:

    pkgmgr: true
    package_manager: cargo
    packages: docpars deno bashdoc
    

    Fail 1

    All went well, but if you call with arguments:

    docpars deno bashdoc
    

    Will show you:

    pkgmgr: false
    package_manager: docpars
    packages: deno bashdoc
    
    

    The docpars value is in package_manager and not in the final array.

    Fail 2

    And finally if you call the script with arguments:

    --pkgmgr cargo
    

    It will output:

    pkgmgr: true
    package_manager:
    packages: cargo
    

    cargo is in packages_names instead of package_manager.

    Expected behavior

    Case fail 1

    pkgmgr: false
    package_manager:
    packages: docpars deno bashdoc
    

    Case fail 2

    pkgmgr: true
    package_manager: cargo
    packages: 
    

    Screenshots Screenshot 2021-07-14 at 16 58 16

    Versions:

    • OS: macos 11.4 Big Sur
    • Shell Version [replace this text with the output of sh --version]
    > $SHELL --version
    zsh 5.8 (x86_64-apple-darwin20.0)
    
    • docpars: v0.2.0

    Additional context The script is dot package add of my Dotly fork, see it here:

    • https://github.com/gtrabanco/sloth/blob/master/scripts/package/add
    opened by gtrabanco 1
  • Positional arguments are misparsed as --required arguments

    Positional arguments are misparsed as --required arguments

    const MAIN_USAGE: &str = "
    Usage:
        cargo deadlinks [--dir <directory>]
    ";
    
    fn main() {
        let args: MainArgs = Docopt::new(MAIN_USAGE)
            .and_then(|d| {
                d.version(Some(env!("CARGO_PKG_VERSION").to_owned()))
                    .deserialize()
            })
            .unwrap_or_else(|e| e.exit());
        dbg!(&args);
    
    $ /home/joshua/.local/lib/cargo/target/debug/cargo-deadlinks deadlinks -- --document-private
    [src/bin/cargo-deadlinks.rs:46] &args = MainArgs {
        arg_directory: Some(
            "--document-private",
        ),
    }
    

    This is wrong - docopt should either exit with an error or ignore the flag altogether (my preference is to exit with an error).

    opened by jyn514 4
  • get_vec and the borrow checker play badly together

    get_vec and the borrow checker play badly together

    get_vec returns Vec<&str>. Unfortunately the borrow checker interprets this to make the first argument to get_vec also have static scope, ala https://stackoverflow.com/questions/58436950/argument-requires-that-is-borrowed-for-static-how-do-i-work-round-this.

    There do not seem to be any good workarounds other than changing the type of the function.

    opened by wbl 1
  • 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

    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") }
    
    opened by mrowqa 0
  • -h in priority

    -h in priority

    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.

    opened by nilgoyette 0
  • Allow Overlapping Option and Usage Flags for Documentation

    Allow Overlapping Option and Usage Flags for Documentation

    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?

    opened by nixpulvis 0
Owner
null
A full featured, fast Command Line Argument Parser for Rust

clap Command Line Argument Parser for Rust It is a simple-to-use, efficient, and full-featured library for parsing command line arguments and subcomma

Ed Page 0 Jun 16, 2022
A simple, lightweight and extensible command line argument parser for rust codebases

A simple, lightweight and extensible command line argument parser for rust codebases. This crate aims to provide you with an easy-to-use and extensibl

Victor Ndaba 20 Nov 12, 2022
A minimal argument parser

Pieces An argument parser built with control in mind. Parsing The results you get are dependent on what order you parse in. If you want to say only pa

ibx34 3 Sep 30, 2021
argmax is a library that allows Rust applications to avoid Argument list too long errors (E2BIG) by providing a std::process::Command wrapper with a

argmax argmax is a library that allows Rust applications to avoid Argument list too long errors (E2BIG) by providing a std::process::Command wrapper w

David Peter 22 Nov 20, 2022
Rust derive-based argument parsing optimized for code size

Argh Argh is an opinionated Derive-based argument parser optimized for code size Derive-based argument parsing optimized for code size and conformance

Google 1.3k Dec 28, 2022
Argument parsing for the future 🚀

argi Argument parsing for the future ?? Features Macro-based approach, providing an intuitive way to layout a cli Rich auto-help generation, styling b

Owez 132 Oct 23, 2022
Small command-line tool to switch monitor inputs from command line

swmon Small command-line tool to switch monitor inputs from command line Installation git clone https://github.com/cr1901/swmon cargo install --path .

William D. Jones 5 Aug 20, 2022
Simple command line flag parser for rust.

easy_flag Simple command line flag parser for rust. use easy_flag::FlagSet; fn main() -> Result<(), String>{ let mut help = false; let mut my

BillyfBrain 3 Oct 20, 2021
A language parser tool to build recursive descent top down parser.

lang-pt A language parser tool to generate recursive descent top down parser. Overview Parsers written for the languages like Javascript are often cus

Creative Forest 7 Jan 4, 2023
Command-line HTTP client for sending a POST request to specified URI on each stdin line.

line2httppost Simple tool to read lines from stdin and post each line as separate POST request to a specified URL (TCP connection is reused though). G

Vitaly Shukela 3 Jan 3, 2023
Pink is a command-line tool inspired by the Unix man command.

Pink is a command-line tool inspired by the Unix man command. It displays custom-formatted text pages in the terminal using a subset of HTML-like tags.

null 3 Nov 2, 2023
FTL Rust Demangler is a command-line tool for demangling symbol names that are mangled with the Rust convention

FTL Rust Demangler is a command-line tool for demangling symbol names that are mangled with the Rust convention. It takes a mangled symbol name as input and returns the demangled name

timetravel3 7 Mar 30, 2023
Checkline: checkbox line picker for stdin line input

checkline is a Unix command line interface (CLI) terminal user interface (TUI) that prompts you to check each line of stdin, to pick each line to output to stdout

SixArm 4 Dec 4, 2022
A command line progress reporting library for Rust

indicatif Documentation A Rust library for indicating progress in command line applications to users. This currently primarily provides progress bars

Armin Ronacher 3.2k Dec 30, 2022
Low-level Rust library for implementing terminal command line interface, like in embedded systems.

Terminal CLI Need to build an interactive command prompt, with commands, properties and with full autocomplete? This is for you. Example, output only

HashMismatch 47 Nov 25, 2022
⚡️ Lightning-fast and minimal calendar command line. Written in Rust 🦀

⚡️ Lightning-fast and minimal calendar command line. It's similar to cal. Written in Rust ??

Arthur Henrique 36 Jan 1, 2023
A small command-line application to view images from the terminal written in Rust.

A small command-line application to view images from the terminal written in Rust. It is basically the front-end of viuer

Atanas Yankov 1.9k Jan 3, 2023
A tool crate to quickly build rust command line application.

Falsework A tool crate to quickly build rust command line application.

Leon Ding 103 Dec 12, 2022