docopt 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +172 -0
- data/docopt.rb +116 -0
- metadata +47 -0
data/README.md
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
`docopt` – command line option parser, that will make you smile
|
2
|
+
===============================================================================
|
3
|
+
|
4
|
+
Help porting [docopt](http://docopt.org/) to Ruby!
|
5
|
+
|
6
|
+
Isn't it awesome how `optparse` and other option parsers generate help and
|
7
|
+
usage-messages based on your code?!
|
8
|
+
|
9
|
+
Hell no! You know what's awesome? It's when the option parser *is* generated
|
10
|
+
based on the help and usage-message that you write in a docstring! This way
|
11
|
+
you don't need to write this stupid repeatable parser-code, and instead can
|
12
|
+
write a beautiful usage-message (the way you want it!), which adds readability
|
13
|
+
to your code.
|
14
|
+
|
15
|
+
Now you can write an awesome, readable, clean, DRY code like *that*:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
doc = "Usage: example.rb [options] <arguments>...
|
19
|
+
|
20
|
+
Options:
|
21
|
+
-h --help show this help message and exit
|
22
|
+
--version show version and exit
|
23
|
+
-v --verbose print status messages
|
24
|
+
-q --quiet report only file names
|
25
|
+
-r --repeat show all occurrences of the same error
|
26
|
+
--exclude=patterns exclude files or directories which match these comma
|
27
|
+
separated patterns [default: .svn,CVS,.bzr,.hg,.git]
|
28
|
+
--filename=patterns when parsing directories, only check filenames matching
|
29
|
+
these comma separated patterns [default: *.rb]
|
30
|
+
--select=errors select errors and warnings (e.g. E,W6)
|
31
|
+
--ignore=errors skip errors and warnings (e.g. E4,W)
|
32
|
+
--show-source show source code for each error
|
33
|
+
--statistics count errors and warnings
|
34
|
+
--count print total number of errors and warnings to standard
|
35
|
+
error and set exit code to 1 if total is not null
|
36
|
+
--benchmark measure processing speed
|
37
|
+
--testsuite=dir run regression tests from dir
|
38
|
+
--doctest run doctest on myself"
|
39
|
+
|
40
|
+
require 'docopt'
|
41
|
+
|
42
|
+
|
43
|
+
if __FILE__ == $0
|
44
|
+
options = docopt(doc, '1.0.0') # parse options based on doc above
|
45
|
+
puts options.inspect
|
46
|
+
puts ARGV.inspect
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Hell yeah! The option parser is generated based on `doc` string above, that you
|
51
|
+
pass to the `docopt` function.
|
52
|
+
|
53
|
+
API `require 'docopt'`
|
54
|
+
===============================================================================
|
55
|
+
|
56
|
+
###`options = docopt(doc, version=nil, help=true)`
|
57
|
+
|
58
|
+
`docopt` takes 1 required and 2 optional arguments:
|
59
|
+
|
60
|
+
- `doc` should be a string that
|
61
|
+
describes **options** in a human-readable format, that will be parsed to create
|
62
|
+
the option parser. The simple rules of how to write such a docstring
|
63
|
+
(in order to generate option parser from it successfully) are given in the next
|
64
|
+
section. Here is a quick example of such a string:
|
65
|
+
|
66
|
+
Usage: your_program.rb [options]
|
67
|
+
|
68
|
+
-h --help Show this.
|
69
|
+
-v --verbose Print more text.
|
70
|
+
--quiet Print less text.
|
71
|
+
-o FILE Specify output file [default: ./test.txt].
|
72
|
+
|
73
|
+
- `help`, by default `true`, specifies whether the parser should automatically
|
74
|
+
print the usage-message (supplied as `doc`) in case `-h` or `--help` options
|
75
|
+
are encountered. After showing the usage-message, the program will terminate.
|
76
|
+
If you want to handle `-h` or `--help` options manually (as all other options),
|
77
|
+
set `help=false`.
|
78
|
+
|
79
|
+
- `version`, by default `nil`, is an optional argument that specifies the
|
80
|
+
version of your program. If supplied, then, if the parser encounters
|
81
|
+
`--version` option, it will print the supplied version and terminate.
|
82
|
+
`version` could be any printable object, but most likely a string,
|
83
|
+
e.g. `'2.1.0rc1'`.
|
84
|
+
|
85
|
+
Note, when `docopt` is set to automatically handle `-h`, `--help` and
|
86
|
+
`--version` options, you still need to mention them in the options description
|
87
|
+
(`doc`) for your users to know about them.
|
88
|
+
|
89
|
+
The **return** value is a hash with option values
|
90
|
+
(giving long options precedence), e.g:
|
91
|
+
|
92
|
+
{"--benchmark"=>true,
|
93
|
+
"--count"=>true,
|
94
|
+
"--doctest"=>false,
|
95
|
+
"--exclude"=>".svn,CVS,.bzr,.hg,.git",
|
96
|
+
"--filename"=>"*.rb",
|
97
|
+
"--help"=>false,
|
98
|
+
"--ignore"=>false,
|
99
|
+
"--quiet"=>false,
|
100
|
+
"--repeat"=>false,
|
101
|
+
"--select"=>"*.rb",
|
102
|
+
"--show-source"=>true,
|
103
|
+
"--statistics"=>true,
|
104
|
+
"--testsuite"=>false,
|
105
|
+
"--verbose"=>true,
|
106
|
+
"--version"=>false}
|
107
|
+
|
108
|
+
You can access positional arguments in `ARGV`.
|
109
|
+
|
110
|
+
`doc` string format for your usage-message
|
111
|
+
===============================================================================
|
112
|
+
|
113
|
+
The main idea behind `docopt` is that a good usage-message (that describes
|
114
|
+
options and defaults unambiguously) is enough to generate an option parser.
|
115
|
+
|
116
|
+
Here are the simple rules (that you probably already follow) for your
|
117
|
+
usage-message to be parsable:
|
118
|
+
|
119
|
+
- Every line that starts with `-` or `--` (not counting spaces) is treated
|
120
|
+
as an option description, e.g.:
|
121
|
+
|
122
|
+
Options:
|
123
|
+
--verbose # GOOD
|
124
|
+
-o FILE # GOOD
|
125
|
+
Other: --bad # BAD, line does not start with dash "-"
|
126
|
+
|
127
|
+
- To specify that an option has an argument, put a word describing that
|
128
|
+
argument after space (or equals `=` sign) as shown below.
|
129
|
+
You can use comma if you want to separate options. In the example below both
|
130
|
+
lines are valid, however you are recommended to stick to a single style.
|
131
|
+
|
132
|
+
-o FILE --output=FILE # without comma, with "=" sign
|
133
|
+
-i <file>, --input <file> # with comma, wihtout "=" sing
|
134
|
+
|
135
|
+
- Use two spaces to separate options with their informal description.
|
136
|
+
|
137
|
+
--verbose More text. # BAD, will be treated as if verbose option had
|
138
|
+
# an argument "More", so use 2 spaces instead
|
139
|
+
-q Quit. # GOOD
|
140
|
+
-o FILE Output file. # GOOD
|
141
|
+
--stdout Use stdout. # GOOD, 2 spaces
|
142
|
+
|
143
|
+
- If you want to set a default value for an option with an argument, put it
|
144
|
+
into the option description, in form `[default: <my-default-value>]`.
|
145
|
+
|
146
|
+
-i INSTANCE Instance of something [default: 1]
|
147
|
+
--coefficient=K The K coefficient [default: 2.95]
|
148
|
+
--output=FILE Output file [default: test.txt]
|
149
|
+
--directory=DIR Some directory [default: ./]
|
150
|
+
|
151
|
+
Something missing? Help porting [docopt](http://docopt.org/) to Ruby!
|
152
|
+
===============================================================================
|
153
|
+
|
154
|
+
Compatibility notice:
|
155
|
+
===============================================================================
|
156
|
+
|
157
|
+
In order to maintain your program's compatibility with future versions
|
158
|
+
of `docopt.rb` (as porting more features continues) you are recommended to
|
159
|
+
keep the following in the begining of `doc` argument:
|
160
|
+
|
161
|
+
Usage: my_program.rb [options] <arguments>...
|
162
|
+
|
163
|
+
or
|
164
|
+
|
165
|
+
Usage: my_program.rb [options] <argument>
|
166
|
+
|
167
|
+
or
|
168
|
+
|
169
|
+
Usage: my_program.rb [options]
|
170
|
+
|
171
|
+
(followed by an empty line), where you are free to change `my_program.rb`
|
172
|
+
and `argument(s)` name inside of `<...>`.
|
data/docopt.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'getoptlong'
|
2
|
+
|
3
|
+
|
4
|
+
class Option
|
5
|
+
|
6
|
+
attr_reader :short, :long, :argcount, :value
|
7
|
+
|
8
|
+
def initialize(short=nil, long=nil, argcount=0, value=false)
|
9
|
+
@short, @long, @argcount, @value = short, long, argcount, value
|
10
|
+
end
|
11
|
+
|
12
|
+
def getopt
|
13
|
+
[@long, @short, @argcount].compact
|
14
|
+
end
|
15
|
+
|
16
|
+
def inspect
|
17
|
+
"Option.new(#{@short}, #{@long}, #{@argcount}, #{@value})"
|
18
|
+
end
|
19
|
+
|
20
|
+
def == other
|
21
|
+
self.inspect == other.inspect
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def option parse
|
28
|
+
options, _, description = parse.strip.partition(' ')
|
29
|
+
options = options.sub(',', ' ').sub('=', ' ')
|
30
|
+
short, long, argcount, value = nil, nil, 0, false
|
31
|
+
for s in options.split
|
32
|
+
if s.start_with? '--'
|
33
|
+
long = s
|
34
|
+
elsif s.start_with? '-'
|
35
|
+
short = s
|
36
|
+
else
|
37
|
+
argcount = 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
if argcount == 1
|
41
|
+
matched = description.scan(/\[default: (.*)\]/)[0]
|
42
|
+
value = matched ? matched[0] : false
|
43
|
+
end
|
44
|
+
Option.new(short, long, argcount, value)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
class MyHash < Hash
|
49
|
+
def inspect
|
50
|
+
"{#{self.to_a.sort.map {|i| "%p=>%p" % i}.join(",\n ")}}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def docopt(doc, version=nil, help=true)
|
56
|
+
ret = MyHash.new
|
57
|
+
docopts = []
|
58
|
+
doc.split(/^ *-|\n *-/)[1..-1].each do |s|
|
59
|
+
docopt = option('-' + s)
|
60
|
+
docopts += [docopt]
|
61
|
+
ret[(docopt.long or docopt.short)] = docopt.value
|
62
|
+
end
|
63
|
+
begin
|
64
|
+
GetoptLong.new(*docopts.map {|e| e.getopt}).each do |opt, arg|
|
65
|
+
if help and (opt == '--help' or opt == '-h')
|
66
|
+
puts doc.strip
|
67
|
+
exit
|
68
|
+
elsif version and opt == '--version'
|
69
|
+
puts version
|
70
|
+
exit
|
71
|
+
elsif (docopts.select {|d|(d.long or d.short)==opt})[0].argcount==0
|
72
|
+
ret[opt] = true
|
73
|
+
else
|
74
|
+
ret[opt] = arg
|
75
|
+
end
|
76
|
+
end
|
77
|
+
rescue
|
78
|
+
exit 1
|
79
|
+
end
|
80
|
+
ret
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
if __FILE__ == $0
|
85
|
+
|
86
|
+
def assert cond
|
87
|
+
print cond ? '.' : 'F'
|
88
|
+
end
|
89
|
+
|
90
|
+
assert option('-h') == Option.new('-h', nil)
|
91
|
+
assert option('--help') == Option.new(nil, '--help')
|
92
|
+
assert option('-h --help') == Option.new('-h', '--help')
|
93
|
+
assert option('-h, --help') == Option.new('-h', '--help')
|
94
|
+
|
95
|
+
assert option('-h TOPIC') == Option.new('-h', nil, 1)
|
96
|
+
assert option('--help TOPIC') == Option.new(nil, '--help', 1)
|
97
|
+
assert option('-h TOPIC --help TOPIC') == Option.new('-h', '--help', 1)
|
98
|
+
assert option('-h TOPIC, --help TOPIC') == Option.new('-h', '--help', 1)
|
99
|
+
assert option('-h TOPIC, --help=TOPIC') == Option.new('-h', '--help', 1)
|
100
|
+
|
101
|
+
assert option('-h Description...') == Option.new('-h', nil)
|
102
|
+
assert option('-h --help Description...') == Option.new('-h', '--help')
|
103
|
+
assert option('-h TOPIC Description...') == Option.new('-h', nil, 1)
|
104
|
+
|
105
|
+
assert option(' -h') == Option.new('-h', nil)
|
106
|
+
|
107
|
+
assert option('-h TOPIC Descripton... [default: 2]') ==
|
108
|
+
Option.new('-h', nil, 1, '2')
|
109
|
+
assert option('-h TOPIC Descripton... [default: topic-1]') ==
|
110
|
+
Option.new('-h', nil, 1, 'topic-1')
|
111
|
+
assert option('--help=TOPIC ... [default: 3.14]') ==
|
112
|
+
Option.new(nil, '--help', 1, '3.14')
|
113
|
+
assert option('-h, --help=DIR ... [default: ./]') ==
|
114
|
+
Option.new('-h', '--help', 1, "./")
|
115
|
+
|
116
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docopt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Vladimir Keleshev
|
9
|
+
- Alex Speller
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-06-03 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: A command line option parser, that will make you smile.
|
16
|
+
email:
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- docopt.rb
|
23
|
+
homepage: http://github.com/alexspeller/docopt.rb
|
24
|
+
licenses: []
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 1.8.23
|
44
|
+
signing_key:
|
45
|
+
specification_version: 3
|
46
|
+
summary: A command line option parser, that will make you smile.
|
47
|
+
test_files: []
|