Skip to content

Commit

Permalink
Merge pull request #8 from njoh/experimental
Browse files Browse the repository at this point in the history
catch up with docopt v0.5.0
  • Loading branch information
johari committed Sep 1, 2012
2 parents 057d9a0 + 48217a0 commit b095a7c
Show file tree
Hide file tree
Showing 16 changed files with 624 additions and 430 deletions.
37 changes: 3 additions & 34 deletions .gitignore
@@ -1,34 +1,3 @@
*.py[co]

# Vim
*.swp

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox
nosetests.xml

#Translations
*.mo

#Mr Developer
.mr.developer.cfg

# Sphinx
docs/_*
pkg/*
*.gem
.bundle
1 change: 1 addition & 0 deletions LICENSE-MIT → LICENSE
@@ -1,6 +1,7 @@
Copyright (c) 2012 Vladimir Keleshev <vladimir@keleshev.com>
Blake Williams <code@shabbyrobe.org>
Alex Speller <alex@alexspeller.com>
Nima Johari

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
291 changes: 86 additions & 205 deletions README.md
@@ -1,6 +1,14 @@
`docopt` – command line option parser, that will make you smile
`docopt.rb` – command line option parser, that will make you smile
===============================================================================

This is the ruby port of [`docopt`](https://github.com/docopt/docopt),
the awesome option parser written originally in python.

> New in version 0.5.0:
>
> Repeatable flags and commands are counted if repeated (a-la ssh `-vvv`).
> Repeatable options with arguments are accumulated into list.
Isn't it awesome how `optparse` and `argparse` generate help messages
based on your code?!

Expand All @@ -12,78 +20,56 @@ write only the help message--*the way you want it*.
`docopt` helps you create most beautiful command-line interfaces *easily*:

```ruby
doc = "Usage: example.rb [options] <arguments>...
require "docopt"
doc = <<DOCOPT
Naval Fate.
Usage:
#{__FILE__} ship new <name>...
#{__FILE__} ship <name> move <x> <y> [--speed=<kn>]
#{__FILE__} ship shoot <x> <y>
#{__FILE__} mine (set|remove) <x> <y> [--moored|--drifting]
#{__FILE__} -h | --help
#{__FILE__} --version
Options:
-h --help show this help message and exit
--version show version and exit
-v --verbose print status messages
-q --quiet report only file names
-r --repeat show all occurrences of the same error
--exclude=patterns exclude files or directories which match these comma
separated patterns [default: .svn,CVS,.bzr,.hg,.git]
--filename=patterns when parsing directories, only check filenames matching
these comma separated patterns [default: *.rb]
--select=errors select errors and warnings (e.g. E,W6)
--ignore=errors skip errors and warnings (e.g. E4,W)
--show-source show source code for each error
--statistics count errors and warnings
--count print total number of errors and warnings to standard
error and set exit code to 1 if total is not null
--benchmark measure processing speed
--testsuite=dir run regression tests from dir
--doctest run doctest on myself"

require 'docopt'

if __FILE__ == $0
options = Docopt(doc, {:version => '1.0.0'})
puts options.inspect
puts ARGV.inspect
-h --help Show this screen.
--version Show version.
--speed=<kn> Speed in knots [default: 10].
--moored Moored (anchored) mine.
--drifting Drifting mine.
DOCOPT

begin
require "pp"
pp Docopt::docopt(doc)
rescue Docopt::Exit => e
puts e.message
end
```

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
(`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*.

```ruby
require 'docopt'
doc = "Usage: your_program.rb [options]
-h --help Show this.
-v --verbose Print more text.
--quiet Print less text.
-o FILE Specify output file [default: ./test.txt]"

options = Docopt(doc, { :version => nil, :help => true })`
options['--help'] # returns true or false depending on option given
```


Installation
===============================================================================

~~Docopt is available through rubygems:~~
Docopt is available via rubygems:

gem install docopt

*Please note: the gem provides an out of date version. We are working on getting
it updated.*

Alternatively, you can just drop `docopt.rb` file into your project--it is
Alternatively, you can just drop `lib/docopt.rb` file into your project--it is
self-contained. [Get source on github](http://github.com/docopt/docopt.rb).

`docopt` has been confirmed to work with 1.8.7p370 and 1.9.3p194. If you have
noticed it working (or not working) with an earlier version, please raise an
issue and we will investigate support.


API
===============================================================================

Expand Down Expand Up @@ -127,179 +113,74 @@ with keys spelled exactly like in a 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
naval_fate.rb ship Guardian move 100 150 --speed=15

the return dictionary will be::

```python
{'--drifting' => False, 'mine' => False,
'--help' => False, 'move' => True,
'--moored' => False, 'new' => False,
'--speed' => '15', 'remove' => False,
'--version' => False, 'set' => False,
'<name>' => ['Guardian'], 'ship' => True,
'<x>' => '100', 'shoot' => False,
'<y>' => '150'}
```ruby
{"ship"=>true,
"new"=>false,
"<name>"=>["Guardian"],
"move"=>true,
"<x>"=>"100",
"<y>"=>"150",
"--speed"=>"15",
"shoot"=>false,
"mine"=>false,
"set"=>false,
"remove"=>false,
"--moored"=>false,
"--drifting"=>false,
"--help"=>false,
"--version"=>false}
```

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.::
docopt.rb follows the docopt help message format.
You can find more details at
[official docopt git repo](https://github.com/docopt/docopt#help-message-format)

-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.
Also, take a look at the
[beautiful examples](https://github.com/docopt/docopt/tree/master/examples>).

Usage pattern format
Examples
-------------------------------------------------------------------------------

**Usage pattern** is a substring of `doc` that starts with
`usage:` (case-*in*sensitive) and ends with a *visibly* empty line.
Minimum example::

```python
"""Usage: my_program.py
"""
```

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::

```python
"""Usage: my_program.py FILE
my_program.py COUNT FILE
"""
```
We have an extensive list of
[examples](https://github.com/docopt/docopt.rb/tree/master/examples)
which cover every aspect of functionality of `docopt`. Try them out,
read the source if in doubt.

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 for option to have an argument, a
default value, or specify synonymous short/long versions of 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) **mutualy exclussive** elements. Group them using **( )** if
one of the mutually exclussive 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 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 you usage patterns.
- "`[-]`". Single dash "`-`" is used by convention to signify that
`stdin` is used instead of a file. To support this add "`[-]`" to
you usage patterns. "`-`" act 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 occurences 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
Data validation
-------------------------------------------------------------------------------

**Option descriptions** consist of a list of options that you put below your
usage patterns.
`docopt` does one thing and does it well: it implements your command-line
interface. However it does not validate the input data. We are looking
for ruby validation libraries to make your option parsing experiene
even more awesome!
If you've got any suggestions or think your awesome schema validation gem
fits well with `docopt.rb`, open an issue on github and enjoy the eternal glory!

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, wihtout "=" sing
Contribution
===============================================================================

- Use two spaces to separate options with their informal description.
We would *love* to hear what you think about `docopt.rb`.
Contribute, make pull requrests, report bugs, suggest ideas and discuss
`docopt.rb` on
[issues page](http://github.com/docopt/docopt.rb/issues).

--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 discuss the original `docopt` reference,
point to [it's home](http://github.com/docopt/docopt) or
drop a line directly to vladimir@keleshev.com!

- 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>]`.
Porting `docopt` to other languages
===============================================================================

--coefficient=K The K coefficient [default: 2.95]
--output=FILE Output file [default: test.txt]
--directory=DIR Some directory [default: ./]
Docopt is an interlinguistic (?) effort,
and this is the ruby port of `docopt`.
We coordinate our efforts with docopt community and try our best to
keep in sync with the python reference.

Docopt community *loves* to hear what you think about `docopt`, `docopt.rb`
and other sister projects on docopt's
[issues page](http://github.com/docopt/docopt/issues).

0 comments on commit b095a7c

Please sign in to comment.