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.
Files changed (3) hide show
  1. data/README.md +172 -0
  2. data/docopt.rb +116 -0
  3. metadata +47 -0
@@ -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 `<...>`.
@@ -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: []