Coder Social home page Coder Social logo

docopt.rs's Introduction

See docopt-ng

Please see docopt-ng for a compatible, updated fork of the original Python docopt.

This project is no longer maintained.

docopt creates beautiful command-line interfaces

image

image

Video introduction to docopt: PyCon UK 2012: Create *beautiful* command-line interfaces with Python

New in version 0.6.1:

  • Fix issue #85 which caused improper handling of [options] shortcut if it was present several times.

New in version 0.6.0:

  • New argument options_first, disallows interspersing options and arguments. If you supply options_first=True to docopt, it will interpret all arguments as positional arguments after first positional argument.
  • If option with argument could be repeated, its default value will be interpreted as space-separated list. E.g. with [default: ./here ./there] will be interpreted as ['./here', './there'].

Breaking changes:

  • Meaning of [options] shortcut slightly changed. Previously it meant "any known option". Now it means "any option not in usage-pattern". This avoids the situation when an option is allowed to be repeated unintentionally.
  • argv is None by default, not sys.argv[1:]. This allows docopt to always use the latest sys.argv, not sys.argv during import time.

Isn't it awesome how optparse and argparse generate help messages based on your code?!

Hell no! You know what's awesome? It's when the option parser is generated based on the beautiful help message that you write yourself! This way you don't need to write this stupid repeatable parser-code, and instead can write only the help message--the way you want it.

docopt helps you create most beautiful command-line interfaces easily:

Beat that! The option parser is generated based on the docstring above that is passed to docopt function. docopt parses the usage pattern ("Usage: ...") and option descriptions (lines starting with dash "-") and ensures that the program invocation matches the usage pattern; it parses options, arguments and commands based on that. The basic idea is that a good help message has all necessary information in it to make a parser.

Also, PEP 257 recommends putting help message in the module docstrings.

Installation

Use pip or easy_install:

pip install docopt==0.6.2

Alternatively, you can just drop docopt.py file into your project--it is self-contained.

docopt is tested with Python 2.7, 3.4, 3.5, and 3.6.

Testing

You can run unit tests using the command:

python setup.py test

API

docopt takes 1 required and 4 optional arguments:

  • doc could be a module docstring (__doc__) or some other string that contains a help message that will be parsed to create the option parser. The simple rules of how to write such a help message are given in next sections. Here is a quick example of such a string:
  • argv is an optional argument vector; by default docopt uses the argument vector passed to your program (sys.argv[1:]). Alternatively you can supply a list of strings like ['--verbose', '-o', 'hai.txt'].
  • help, by default True, specifies whether the parser should automatically print the help message (supplied as doc) and terminate, in case -h or --help option is encountered (options should exist in usage pattern, more on that below). If you want to handle -h or --help options manually (as other options), set help=False.
  • version, by default None, is an optional argument that specifies the version of your program. If supplied, then, (assuming --version option is mentioned in usage pattern) when parser encounters the --version option, it will print the supplied version and terminate. version could be any printable object, but most likely a string, e.g. "2.1.0rc1".

    Note, when docopt is set to automatically handle -h, --help and --version options, you still need to mention them in usage pattern for this to work. Also, for your users to know about them.

  • options_first, by default False. If set to True will disallow mixing options and positional argument. I.e. after first positional argument, all arguments will be interpreted as positional even if the look like options. This can be used for strict compatibility with POSIX, or if you want to dispatch your arguments to other programs.

The return value is a simple dictionary with options, arguments and commands as keys, spelled exactly like in your help message. Long versions of options are given priority. For example, if you invoke the top example as:

naval_fate.py ship Guardian move 100 150 --speed=15

the return dictionary will be:

Help message format

Help message consists of 2 parts:

  • Usage pattern, e.g.:

    Usage: my_program.py [-hso FILE] [--quiet | --verbose] [INPUT ...]
  • Option descriptions, e.g.:

    -h --help    show this
    -s --sorted  sorted output
    -o FILE      specify output file [default: ./test.txt]
    --quiet      print less text
    --verbose    print more text

Their format is described below; other text is ignored.

Usage pattern format

Usage pattern is a substring of doc that starts with usage: (case insensitive) and ends with a visibly empty line. Minimum example:

The first word after usage: is interpreted as your program's name. You can specify your program's name several times to signify several exclusive patterns:

Each pattern can consist of the following elements:

  • <arguments>, ARGUMENTS. Arguments are specified as either upper-case words, e.g. my_program.py CONTENT-PATH or words surrounded by angular brackets: my_program.py <content-path>.
  • --options. Options are words started with dash (-), e.g. --output, -o. You can "stack" several of one-letter options, e.g. -oiv which will be the same as -o -i -v. The options can have arguments, e.g. --input=FILE or -i FILE or even -iFILE. However it is important that you specify option descriptions if you want your option to have an argument, a default value, or specify synonymous short/long versions of the option (see next section on option descriptions).
  • commands are words that do not follow the described above conventions of --options or <arguments> or ARGUMENTS, plus two special commands: dash "-" and double dash "--" (see below).

Use the following constructs to specify patterns:

  • [ ] (brackets) optional elements. e.g.: my_program.py [-hvqo FILE]
  • ( ) (parens) required elements. All elements that are not put in [ ] are also required, e.g.: my_program.py --path=<path> <file>... is the same as my_program.py (--path=<path> <file>...). (Note, "required options" might be not a good idea for your users).
  • | (pipe) mutually exclusive elements. Group them using ( ) if one of the mutually exclusive elements is required: my_program.py (--clockwise | --counter-clockwise) TIME. Group them using [ ] if none of the mutually-exclusive elements are required: my_program.py [--left | --right].
  • ... (ellipsis) one or more elements. To specify that arbitrary number of repeating elements could be accepted, use ellipsis (...), e.g. my_program.py FILE ... means one or more FILE-s are accepted. If you want to accept zero or more elements, use brackets, e.g.: my_program.py [FILE ...]. Ellipsis works as a unary operator on the expression to the left.
  • [options] (case sensitive) shortcut for any options. You can use it if you want to specify that the usage pattern could be provided with any options defined below in the option-descriptions and do not want to enumerate them all in usage-pattern.
  • "[--]". Double dash "--" is used by convention to separate positional arguments that can be mistaken for options. In order to support this convention add "[--]" to your usage patterns.
  • "[-]". Single dash "-" is used by convention to signify that stdin is used instead of a file. To support this add "[-]" to your usage patterns. "-" acts as a normal command.

If your pattern allows to match argument-less option (a flag) several times:

Usage: my_program.py [-v | -vv | -vvv]

then number of occurrences of the option will be counted. I.e. args['-v'] will be 2 if program was invoked as my_program -vv. Same works for commands.

If your usage patterns allows to match same-named option with argument or positional argument several times, the matched arguments will be collected into a list:

Usage: my_program.py <file> <file> --path=<path>...

I.e. invoked with my_program.py file1 file2 --path=./here --path=./there the returned dict will contain args['<file>'] == ['file1', 'file2'] and args['--path'] == ['./here', './there'].

Option descriptions format

Option descriptions consist of a list of options that you put below your usage patterns.

It is necessary to list option descriptions in order to specify:

  • synonymous short and long options,
  • if an option has an argument,
  • if option's argument has a default value.

The rules are as follows:

  • Every line in doc that starts with - or -- (not counting spaces) is treated as an option description, e.g.:

    Options:
      --verbose   # GOOD
      -o FILE     # GOOD
    Other: --bad  # BAD, line does not start with dash "-"
  • To specify that option has an argument, put a word describing that argument after space (or equals "=" sign) as shown below. Follow either <angular-brackets> or UPPER-CASE convention for options' arguments. You can use comma if you want to separate options. In the example below, both lines are valid, however you are recommended to stick to a single style.:

    -o FILE --output=FILE       # without comma, with "=" sign
    -i <file>, --input <file>   # with comma, without "=" sign
  • Use two spaces to separate options with their informal description:

    --verbose More text.   # BAD, will be treated as if verbose option had
                           # an argument "More", so use 2 spaces instead
    -q        Quit.        # GOOD
    -o FILE   Output file. # GOOD
    --stdout  Use stdout.  # GOOD, 2 spaces
  • If you want to set a default value for an option with an argument, put it into the option-description, in form [default: <my-default-value>]:

    --coefficient=K  The K coefficient [default: 2.95]
    --output=FILE    Output file [default: test.txt]
    --directory=DIR  Some directory [default: ./]
  • If the option is not repeatable, the value inside [default: ...] will be interpreted as string. If it is repeatable, it will be splited into a list on whitespace:

    Usage: my_program.py [--repeatable=<arg> --repeatable=<arg>]
                         [--another-repeatable=<arg>]...
                         [--not-repeatable=<arg>]
    
    # will be ['./here', './there']
    --repeatable=<arg>          [default: ./here ./there]
    
    # will be ['./here']
    --another-repeatable=<arg>  [default: ./here]
    
    # will be './here ./there', because it is not repeatable
    --not-repeatable=<arg>      [default: ./here ./there]

Examples

We have an extensive list of examples which cover every aspect of functionality of docopt. Try them out, read the source if in doubt.

Subparsers, multi-level help and huge applications (like git)

If you want to split your usage-pattern into several, implement multi-level help (with separate help-screen for each subcommand), want to interface with existing scripts that don't use docopt, or you're building the next "git", you will need the new options_first parameter (described in API section above). To get you started quickly we implemented a subset of git command-line interface as an example: examples/git

Data validation

docopt does one thing and does it well: it implements your command-line interface. However it does not validate the input data. On the other hand there are libraries like python schema which make validating data a breeze. Take a look at validation_example.py which uses schema to validate data and report an error to the user.

Using docopt with config-files

Often configuration files are used to provide default values which could be overriden by command-line arguments. Since docopt returns a simple dictionary it is very easy to integrate with config-files written in JSON, YAML or INI formats. config_file_example.py provides and example of how to use docopt with JSON or INI config-file.

Development

We would love to hear what you think about docopt on our issues page

Make pull requests, report bugs, suggest ideas and discuss docopt. You can also drop a line directly to <[email protected]>.

Porting docopt to other languages

We think docopt is so good, we want to share it beyond the Python community! All official docopt ports to other languages can be found under the docopt organization page on GitHub.

If your favourite language isn't among then, you can always create a port for it! You are encouraged to use the Python version as a reference implementation. A Language-agnostic test suite is bundled with Python implementation.

Porting discussion is on issues page.

Changelog

docopt follows semantic versioning. The first release with stable API will be 1.0.0 (soon). Until then, you are encouraged to specify explicitly the version in your dependency tools, e.g.:

pip install docopt==0.6.2
  • 0.6.2 Bugfix release.
  • 0.6.1 Bugfix release.
  • 0.6.0 options_first parameter. Breaking changes: Corrected [options] meaning. argv defaults to None.
  • 0.5.0 Repeated options/commands are counted or accumulated into a list.
  • 0.4.2 Bugfix release.
  • 0.4.0 Option descriptions become optional, support for "--" and "-" commands.
  • 0.3.0 Support for (sub)commands like git remote add. Introduce [options] shortcut for any options. Breaking changes: docopt returns dictionary.
  • 0.2.0 Usage pattern matching. Positional arguments parsing based on usage patterns. Breaking changes: docopt returns namespace (for arguments), not list. Usage pattern is formalized.
  • 0.1.0 Initial release. Options-parsing only (based on options description).

docopt.rs's People

Contributors

ajweiss avatar alexcrichton avatar andars avatar anka-213 avatar apanatshka avatar birkenfeld avatar bkoropoff avatar brandonson avatar burntsushi avatar crazysacx avatar crumblingstatue avatar debris avatar dguo avatar dns2utf8 avatar eh2406 avatar gchp avatar ianbollinger avatar ignatenkobrain avatar jauhien avatar kinghajj avatar ktossell avatar leighlondon avatar leonkunert avatar netvl avatar ordian avatar simonask avatar steveklabnik avatar tgkokk avatar yuttie avatar zsiciarz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

docopt.rs's Issues

Docopt causes nil value panic when called with no arguments.

The following minimal docopt program, which takes no parameters, panics when called without any arguments:

#![feature(plugin, core)]

extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;
#[plugin] #[no_link] extern crate docopt_macros;

docopt!(Args derive Debug, "
Usage: misc [options]

Options:
  -h, --help        Show this message.
");

fn main() {
    let _ = Args::docopt().decode().unwrap_or_else(|e| e.exit());
}

The panic message is:

thread '<main>' panicked at 'I don't know how to read into a nil value.', ~/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.33/src/lib.rs:944
An unknown error occurred

This should not happen, because it makes it impossible to have a program take no arguments and read from stdin, with '[-]'.

-- is removed from commands

With the usage pattern cmd <args>..., a literal "--" passed to args does not appear in the final Vec returned by Docopt for the <args>.

From my reading of the docopt standard, I think this is incorrect behaviour (but I'm no docopt expert).

cargo.rs problem

Hi,
i try to compile cargo.rs (from examples dir) - everything is ok, but on attempt to run app without any argument i see error

Could not match '' with any of the allowed variants: ["Build", "Clean", "Doc", "New", "Run", "Test", "Bench", "Update"]

Whats wrong? I'm newbie in rust and i hope you can explain me how to solve my stupid issue :)

generate auto-complete binaries for Windows/Mac/Linux

As mentioned in the main docopt brach:

If I were to ship my application [that uses docopt_wordlist], I would have to include Rust, cargo and build the tab completion tool on the target system. All that with no guaratee that it works and a lot of overhead.
[Source: https://github.com/docopt/docopt/issues/261]

An easier way to install the auto completion features on any system might be good. Also I'd like to see an option that generates a static wordlist (bash) scripts for use e.g., in /etc/bash_completion.d/myscript.py.sh. One could ship/include them in packages, where dynamic generation is not required.

Compilaton error on Rust nightly in docopt_macros

I'm getting this error trying to use docopt_macros with today's Rust nightly, I tried to fix it myself but I don't know enough about Rust macros to do it 🐼

src/macro.rs:300:17: 303:6 error: missing field: `bindings` [E0063]
src/macro.rs:300     let tystr = ast::AngleBracketedParameterData {
src/macro.rs:301         lifetimes: vec![],
src/macro.rs:302         types: OwnedSlice::from_vec(vec![cx.ty_ident(sp, ident("String"))]),
src/macro.rs:303     };

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;
                                                                                        ^~~~~~~~~~~~~~~~~~~

making Args public

The macro generates the Args struct, but is there any way to make it public?

cli.rs:

docopt!(Args, "...")
pub fn parse() -> Args {
    return FlagParser::parse().unwrap_or_else(|e| e.exit());
}

main.rs:

mod cli;
fn main() {
    let args: cli::Args = cli::parse();
}

error: type Args is private

New to Rust so sorry if I'm missing something obvious here.

docopt fails to compile under cargo

Hi, I'm trying to compile the first example, but it fails:

   Compiling docopt_test v0.1.0 (file:[...]/docopt_test)
[...]/src/main.rs:3:18: 3:45 error: libdocopt-7cf8b9f71ffa1094.so: cannot open shared object file: No such file or directory
[...]/src/main.rs:3 #[phase(plugin)] extern crate docopt_macros;
                                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~
Could not compile `docopt_test`.

My Cargo.toml:

$ cat Cargo.toml 
[package]

name = "docopt_test"
version = "0.1.0"
authors = [ ]

[dependencies.docopt]
git = "https://github.com/BurntSushi/docopt.rs.git"
[dependencies.docopt_macros]
git = "https://github.com/BurntSushi/docopt.rs.git"

I'm running newest nighly versions of rustc (217f1fbfc) and cargo (88e17c6).

Thanks in advance.

flag repetitions inside option are quirky

Usage: xorfile [-h | -r SECTOR | -n NAME ...]

Invoking gives:

[andrew@Serval docopt.rs] ./xorfile -n hi 
Names: [hi], Resume: None
[andrew@Serval docopt.rs] ./xorfile -r 5
Names: [], Resume: Some(5)
[andrew@Serval docopt.rs] ./xorfile -n hi -r 5
Invalid arguments.

Usage: xorfile [-h | -r SECTOR | -n NAME ...]

The last one should work. If you change the usage to [-h | -r SECTOR] [-n NAME ...], then it works.

subcommand stripped of program name

I am not sure if I used it right, but here is my code,

extern crate docopt;
use docopt::Docopt;

static USAGE: &'static str = "
t

Usage:
  t add <name>
  t list
  t rm <name>
  t init
  t (-h | --help)
  t --version

Options:
  -h --help   Print help message.
  --version   Print version.
";

fn main() {
    let args = Docopt::new(USAGE)
                .and_then(|opt| opt.parse())
                .unwrap_or_else(|e| e.exit());

    println!("args {}", args);
    println!("todo {}", args.get_vec("<name>"));
}

when I ran this with only t, it gave the args as below

args -h, --help => Switch(false)
--version => Switch(false)
<name> => Plain(None)
add => Switch(false)
ini => Switch(false)
lis => Switch(false)
rm => Switch(false)
todo []

as you can see that the t of init was stripped, left ini, same for list. My guess is it removes the part which matches the program name?

Thanks.

error: attempt to implement a nonexistent trait 'xyz'

I saw so many such errors while building cargo/master on windows for target 'x86_64-w64-mingw32
' . I am using rust/master to build.

C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\lib.rs:581:6: 581:16 error: attempt to implement a nonexistent trait Collection
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\lib.rs:581 impl Collection for ValueMap {
^~~~~~~~~~
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\lib.rs:585:10: 585:29 error: attempt to implement a nonexistent trait Map
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\lib.rs:585 impl<'k> Map<&'k str, Value> for ValueMap {
^~~~~~~~~~~~~~~~~~~
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:56:23: 56:33 error: attempt to implement a nonexistent trait Collection
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:56 impl<K: Eq + Hash, V> Collection for SynonymMap<K, V> {
^~~~~~~~~~
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:60:23: 60:30 error: attempt to implement a nonexistent trait Mutable
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:60 impl<K: Eq + Hash, V> Mutable for SynonymMap<K, V> {
^~~~~~~
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:64:23: 64:32 error: attempt to implement a nonexistent trait Map
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:64 impl<K: Eq + Hash, V> Map<K, V> for SynonymMap<K, V> {
^~~~~~~~~
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:73:31: 73:47 error: attempt to implement a nonexistent trait MutableMap
C:\msys64\home\test.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\synonym.rs:73 impl<K: Eq + Hash + Clone, V> MutableMap<K, V> for SynonymMap<K, V> {
^~~~~~~~~~~~~~~~
error: aborting due to 6 previous errors

Latest docopt fails as a dependency

Fails due to recent hyphen changes on cargo.

cargo build
Unable to get packages from source

Caused by:
  failed to parse manifest at `/Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.55/Cargo.toml`

Caused by:
  target names cannot contain hyphens: docopt-wordlist

add auto suggest for commands/flags that don't match

E.g., given Usage: cargo [--release] with invocation cargo --rlease, a nice error message might:

Invalid flag '--rlease'. Did you mean '--release'?

Something like Levenshtein or trigram distance should make this easy.

macro undefined: 'panic!'

rustc 0.12.0 (ba4081a5a 2014-10-07 13:44:41 -0700)
cargo 0.0.1-pre-nightly (041d14e 2014-10-29 19:32:55 +0000)
win7x64

cargo build -v
    Updating git repository `git://github.com/docopt/docopt.rs`
   Compiling docopt v0.6.5 (git://github.com/docopt/docopt.rs#6db6dc01)
     Running `rustc C:\Users\User\.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\lib.rs --crate-name docopt --crate-type lib -g -C metadata=09f4b5d29dab1787 -C extra-filename=-09f4b5d29dab1787 
C:\Users\User\.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\lib.rs:215:25: 215:30 error: macro undefined: 'panic!'
C:\Users\User\.cargo\git\checkouts\docopt.rs-643e15305361a76f\master\src\lib.rs:215             Err(err) => panic!("{}", err),
                                                                                                            ^~~~~
error: aborting due to previous error
Could not compile `docopt`.

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?

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

make failure modes better when struct names are wrong

The following is supposed to allow IPv4 and/or IPv6 while restricting ip/port to -4 and ip6/port6 to -6. I would like it to catch the case where -4 and -6 are both missing, but I can do that elsewhere in the code. Here is an example of syntax that works on try.docopt.org, but fails with docopt.rs:

extern crate docopt;
extern crate "rustc-serialize" as rustc_serialize;

use docopt::Docopt;

static USAGE: &'static str = "
Usage: rtracker [(-4 [--port=<port> --ip=<ip>])] [(-6 [--port6=<port6> --ip6=<ip6>])]
       rtracker (--help)

Options:
    -h,  --help      Show this message
    -4               Enable listening on an IPv4 address
    --ip=<ip>        IP (v4) address to listen on [default: 127.0.0.1]
    --port=<port>    Port number to listen on [default: 6969]
    -6               Enable listening on an IPv6 address
    --ip6=<ip6>      IP (v6) address to listen on [default: ::1]
    --port6=<port6>  Port number to listen on [default: 6969]
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_4:     bool,
    arg_ip:     String,
    arg_port:   u16,
    flag_6:     bool,
    arg_ip6:    String,
    arg_port6:  u16,
}

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

try.docopt.org shows that the reference implementation is ok with this syntax. docopt (0.6.38) chokes with correct parameters by resulting in:

Could not find argument '<ip>' (from struct field 'arg_ip').

And when the arguments are incorrect (this behaves as expected):

./rtracker -6 --port 55
Invalid arguments.

Usage: rtracker [(-4 [--port=<port> --ip=<ip>]) (-6 [--port6=<port6> --ip6=<ip6>])]
       rtracker (--help)

Outdated macro instructions

I haven't been following Rust for a while so I'm not sure if that is the correct syntax, but this is how I got it working again:

#![feature(plugin)]

#![plugin(docopt_macros)]
extern crate docopt_macros;

automatically generate static wordlist bash scripts

From #104:

Also I'd like to see an option that generates a static wordlist (bash) scripts for use e.g., in /etc/bash_completion.d/myscript.py.sh. One could ship/include them in packages, where dynamic generation is not required.

Error compiling with latest nightly

   Compiling docopt v0.6.23 (file:///home/gchp/github.com/gchp/docopt.rs)
/home/gchp/github.com/gchp/docopt.rs/src/synonym.rs:51:38: 51:39 error: obsolete syntax: `|uint| -> bool` closure type syntax
/home/gchp/github.com/gchp/docopt.rs/src/synonym.rs:51     fn with_key<T>(&self, k: &K, with: |&K| -> T) -> T {
                                                                                            ^
note: use unboxed closures instead, no type annotation needed
error: aborting due to previous error
Could not compile `docopt`.

Unfortunately, I don't have enough experience with unboxed closures to be able to fix this.

Upper-case conventions

When using the UPPERCASE convention instead of the <angle> bracket convention for arguments, rust complains warning: structure field 'arg_UPPERCASE' should have a snake case name such as 'arg_u_p_p_e_r_c_a_s_e', #[warn(non_snake_case)] on by default.

In my opinion, this crate should address that, possibly by either 1) having the documentation for this crate mention this and encourage the <angle> convention, or 2) silencing that warning. As it stands right now, its too tempting to simply turn off that warning globally...

Arguments are not parsed if equal to keywords

Check this docopt:

docopt!(Args, "
Usage: backup file <file>
")

and invoke with $ backup file file, args.arg_file will be empty and cmd_file true.

It's not the same as here. Note the <name> argument parsed correctly.

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.

Rustc can't find docopt_macros crate

So I'm not sure how to include this in my project.
Do I clone and just cp all the files to src?
Or Is there a way to leverage cargo?

Simply following the README.md results in a "can't find crate for 'docopt_macros'" compiler error so more info on that would be welcome.

automate subcommand dispatching (case analysis)

I don't think there's any case where several of the boolean flags can be true at the same time is there? With Struct variants being un-feature-gated recently, wouldn't they be a rather nice option?

docopt!(Args deriving Show, "
Usage:
  partners list
  partners set <nick> [--local]
")

would generate something like:

enum Args {
  List,
  Set { arg_nick: String }
}

This would make pattern matching on the parsed arguments very nice:

match args {
  List => list(),
  Set { arg_nick: nick } => set(nick.as_slice())
}

If arguments and options should be namespaced, we could do something like:

struct SetArguments { nick: String }
struct SetOptions { local: bool }
enum Args {
  List,
  Set { arguments: SetArguments, options: SetOptions }
}

But this wouldn't lead to nearly as nice pattern matching.

Just an idea, no idea if this is feasible or not.

Syntax error when building docopt

Tried to build iota, a rust editor and got the following error:

$ cargo build --release
   Compiling termbox-sys v0.0.2 (https://github.com/gchp/termbox-sys#e8352762)
   Compiling docopt v0.6.16
/Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45:34: 45:40 error: unresolved import `std::collections::hash_map::Vacant`. There is no `Vacant` in `std::collections::hash_map`
/Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45 use std::collections::hash_map::{Vacant, Occupied};
                                                                                                                                 ^~~~~~
/Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45:42: 45:50 error: unresolved import `std::collections::hash_map::Occupied`. There is no `Occupied` in `std::collections::hash_map`
/Users/ruipacheco/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.16/src/parse.rs:45 use std::collections::hash_map::{Vacant, Occupied};
                                                                                                                                         ^~~~~~~~
error: aborting due to 2 previous errors
Build failed, waiting for other jobs to finish...
Could not compile `docopt`.

To learn more, run the command again with --verbose.

Error compiling docopt

I'm trying to build a program that uses docopt but it fails with the following error message:

$ cargo build
   Compiling docopt v0.6.36
/Users/hesk/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.36/src/lib.rs:565:46: 565:59     error: type `collections::string::String` does not implement any method in scope named `into_string`
/Users/hesk/.cargo/registry/src/github.com-1ecc6299db9ec823/docopt-0.6.36/src/lib.rs:565         ::std::env::args().skip(1).map(|v| v.into_string().unwrap()).collect()
                                                                                                                                  ^~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `docopt`.

`--` should work independently of `options_first`

As it stands now, -- is interpreted as a command and therefore, when options_first is enabled, the presence of -- guarantees that all subsequent flags are treated as positional arguments.

However, when options_first is not enabled (the default), then -- is just another command and flags are allowed after it.

In short, the argv parser must be made aware of the special -- and treat all subsequent flags as positional arguments. This should be a very small change.

When working properly, it should pass tests like this when options_first is disabled (I don't think such a test does not exist in the reference test suite):

Usage: [-a] [--] [<arg>...]

Invocation and expected output:

program -a
{-a: True, <arg>: [], --: False}

program --
{-a: False, <arg>: [], --: True}

program -a -- -b
{-a: True, <arg>: [-b], --: True}

program -a -- -a
{-a: True, <arg>: [-a], --: True}

program -- -a
{-a: False, <arg>: [-a], --: True}

Currently, I think the last three tests will fail when options_first is false but will succeed when options_first is true.

More readable struct fields

I don't know Rust, but for the C implementation the strategy was similar—to generate a struct. However, the idea was to either generate struct under one "namespace":

-g       => args.g     # unless --group is a synonym
--group  => args.group
FILE     => args.file
<file>   => args.file
build    => args.build

Or have separate nested structs for options, arguments and commands:

-g       => args.options.g       # unless --group is a synonym
--group  => args.options.group
FILE     => args.positional.file
<file>   => args.positional.file
build    => args.commands.build

I would prefer any of the two better than the current scheme.

Unable to build with rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-20)

0.6.38 is unable to build:

commit e54579e64d13e8a39946d964980554bd6b77350a (HEAD, tag: 0.6.38, origin/master, origin/HEAD, master)
~/repos/docopt.rs (master) $ cargo build
   Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling regex v0.1.15
   Compiling rustc-serialize v0.2.15
   Compiling docopt v0.6.38 (file:///home/chaos/repos/docopt.rs)

src/synonym.rs:2:34: 2:40 error: unresolved import `std::collections::hash_map::Hasher`. There is no `Hasher` in `std::collections::hash_map`
src/synonym.rs:2 use std::collections::hash_map::{Hasher, Iter, Keys};
                                                  ^~~~~~
error: aborting due to previous error
Could not compile `docopt`.

To learn more, run the command again with --verbose.

Tag completition doesn't return filelist and does not honor argument number or directories

I'm using the docopt-wordlist utility with a python script of mine. It does not return filenames as suggestions. Here is an example:

#!/usr/bin/python
"""
Minimal demonstration of docopt-wordlist not giving file names, repeating
arguments, where it shouldn't and failing to offer file and dir completion.

Usage:
  exfl.py --help
  exfl.py ([--test=<arg>] FILE)
"""
from docopt import docopt
arguments = docopt(__doc__)

Expected behavior in bash shell session:

confus@confusion:~$ exfl.py                 # [TAB][TAB]
--help  --test  file1.txt  file2.txt  dir1/
confus@confusion:~$ exfl.py --test          # [TAB][TAB]
file1.txt  file2.txt  dir1/
confus@confusion:~$ exfl.py --test --       # [TAB][TAB] no completion expected

confus@confusion:~$ exfl.py --test di       # [TAB] 
confus@confusion:~$ exfl.py --test dir1/    # [TAB][TAB]
subdir1  subdir2  subfile1.txt  subfile2.txt

Actual (wrong) behavior in bash shell session:

confus@confusion:~$ exfl.py                 #[TAB][TAB]
--help  --test                                  # files and dirs missing here
confus@confusion:~$ exfl.py --test          # [TAB][TAB] dir or file expected but completes to:
confus@confusion:~$ exfl.py --test --       # [TAB][TAB] allows infinite repetition of options and doesn't give a file or dir as it should
--help  --test                                  # files and dirs missing here
confus@confusion:~$ exfl.py --test di       # [TAB] completes to "dir1" as should but
confus@confusion:~$ exfl.py --test dir1     # [TAB][TAB] does not give subdirectories of "dir1" because the slash ('/') is missing
--help  --test

Also seems to print the "Usage: ..." message again, when complete -F _docopt_wordlist_commands exfl.py is set in .bash_completion instead of complete -F _docopt_wordlist exfl.py.

docopt API

I'm only opening this because the readme states the API is up for debate.

I'm quite partial to python's argparse API. It's easy to use and to the point, and to be honest in comparison the current docopt API feels a bit lacking.
Could you take a look at argparse if you haven't done so already so we can discuss pro's and cons, and perhaps even improve on that?

BTW: This is only intended as constructive criticism.

Build Error: missing fields: `super_struct`, `is_virtual`

I encountered the following error while trying to compile docopt.rs while building Cargo:

   Compiling docopt_macros v0.6.4 (https://github.com/docopt/docopt.rs#7515c10d)
Build failed, waiting for other jobs to finish...
Could not compile `docopt_macros`.

--- stderr
src/macro.rs:84:19: 87:10 error: missing fields: `super_struct`, `is_virtual` [E0063]
src/macro.rs:84         let def = ast::StructDef {
src/macro.rs:85             fields: self.struct_fields(cx),
src/macro.rs:86             ctor_id: None
src/macro.rs:87         };
error: aborting due to previous error


To learn more, run the command again with --verbose.
make: *** [cargo-x86_64-apple-darwin] Error 101

I got the same error when building docopt.rs separately using the Makefile.

I am running Rust 0.12 on OS X 10.10 Yosemite.

Attempt to bound type parameter with a nonexistent trait `StrAllocating`

On Windows 64-bit, rust-lang/rust 62fb41c32, docopt b5e9e16 I get:

$ rustc --version
rustc 0.13.0-nightly (62fb41c32 2014-12-23 02:41:48 +0000)

$ cargo run -- -d'localhost:1351' -u'localhost:1350'
   Compiling docopt v0.6.18 (https://github.com/docopt/docopt.rs.git#b5e9e163)
warning: using multiple versions of crate `regex`
C:\MinGW\msys\1.0\home\mattbw\.cargo\git\checkouts\docopt.rs-643e15305361a76f\ma
ster\src\lib.rs:217:1: 217:24 note: used here
C:\MinGW\msys\1.0\home\mattbw\.cargo\git\checkouts\docopt.rs-643e15305361a76f\ma
ster\src\lib.rs:217 extern crate serialize;
                    ^~~~~~~~~~~~~~~~~~~~~~~
note: crate name: regex
C:\MinGW\msys\1.0\home\mattbw\.cargo\git\checkouts\docopt.rs-643e15305361a76f\ma
ster\src\lib.rs:216:1: 216:20 note: used here
C:\MinGW\msys\1.0\home\mattbw\.cargo\git\checkouts\docopt.rs-643e15305361a76f\ma
ster\src\lib.rs:216 extern crate regex;
                    ^~~~~~~~~~~~~~~~~~~
note: crate name: regex
C:\MinGW\msys\1.0\home\mattbw\.cargo\git\checkouts\docopt.rs-643e15305361a76f\ma
ster\src\lib.rs:486:41: 486:54 error: attempt to bound type parameter with a non
existent trait `StrAllocating`
C:\MinGW\msys\1.0\home\mattbw\.cargo\git\checkouts\docopt.rs-643e15305361a76f\ma
ster\src\lib.rs:486                where I: Iterator<S>, S: StrAllocating {
                                                            ^~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `docopt`.

To learn more, run the command again with --verbose.

While the regex issues are #65, the StrAllocating error seems to be a new one, caused by this prq.

Mention `rust-serialize` as dependency

I think you should mention that people have also to add rustc-serialize = "*" to their dependencies in Cargo.toml in order to get the examples running. Perhaps also explain in one sentence why that's needed.

Quick example does not compile with rust master

When attempting to compile the quick example in the readme with the latest rust as of today, I get this error:

/.../src/main.rs:1:1: 1:1 error: `Args` is a structure name, but this expression uses it like a function name
/.../src/main.rs:1 #![feature(phase)]
                   ^
note: in expansion of #[deriving]
/.../src/main.rs:1:1: 1:1 note: expansion site
/.../src/main.rs:1:1: 15:1 note: in expansion of docopt!
/.../src/main.rs:8:1: 10:3 note: expansion site
/.../src/main.rs:1:1: 1:1 note: Did you mean to write: `Args { /* fields */ }`?
/.../src/main.rs:1 #![feature(phase)]
                   ^
note: in expansion of #[deriving]
/.../src/main.rs:1:1: 1:1 note: expansion site
/.../src/main.rs:1:1: 15:1 note: in expansion of docopt!
/.../src/main.rs:8:1: 10:3 note: expansion site
error: aborting due to previous error

Tries to decode argument which is not present

I got a sub-command based docopt

docopt!(Args deriving Show, "
Usage: app cmd1 [options] <a> <b>...
       app cmd2 [options] <a> <c>

Options:
    -h, --help         Show this message.
    --version          Show the version.
", arg_a: AArg, arg_c: CArg)

which has custom decoders for a and c.

The problem is, that the decoder for c is also called, when I issue the sub-command cmd1, which doesn't have a c arg. The decoder fails cause the arg is empty.

I think the decoder for c should never be called, if I issue the cmd1 sub-command that doesn't have a c-type argument. Is it a bug or am I missing something?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.