docopt 0.0.4 → 0.5.0

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/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gem 'rake'
@@ -1,4 +1,7 @@
1
- Copyright (c) 2012 Vladimir Keleshev <vladimir@keleshev.com>, Alex Speller <alex@alexspeller.com>
1
+ Copyright (c) 2012 Vladimir Keleshev <vladimir@keleshev.com>
2
+ Blake Williams <code@shabbyrobe.org>
3
+ Alex Speller <alex@alexspeller.com>
4
+ Nima Johari
2
5
 
3
6
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
7
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,72 +1,79 @@
1
- `docopt` – command line option parser, that will make you smile
1
+ `docopt.rb` – command line option parser, that will make you smile
2
2
  ===============================================================================
3
3
 
4
- [![Build Status](https://secure.travis-ci.org/alexspeller/docopt.png?branch=master)](http://travis-ci.org/alexspeller/docopt)
4
+ This is the ruby port of [`docopt`](https://github.com/docopt/docopt),
5
+ the awesome option parser written originally in python.
5
6
 
6
- Isn't it awesome how `optparse` and other option parsers generate help and
7
- usage-messages based on your code?!
7
+ > New in version 0.5.0:
8
+ >
9
+ > Repeatable flags and commands are counted if repeated (a-la ssh `-vvv`).
10
+ > Repeatable options with arguments are accumulated into list.
8
11
 
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
12
+ Isn't it awesome how `optparse` and `argparse` generate help messages
13
+ based on your code?!
14
+
15
+ *Hell no!* You know what's awesome? It's when the option parser *is* generated
16
+ based on the beautiful help message that you write yourself! This way
11
17
  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.
18
+ write only the help message--*the way you want it*.
14
19
 
15
- Now you can write an awesome, readable, clean, DRY code like *that*:
20
+ `docopt` helps you create most beautiful command-line interfaces *easily*:
16
21
 
17
22
  ```ruby
18
- doc = "Usage: example.rb [options] <arguments>...
23
+ require "docopt"
24
+ doc = <<DOCOPT
25
+ Naval Fate.
26
+
27
+ Usage:
28
+ #{__FILE__} ship new <name>...
29
+ #{__FILE__} ship <name> move <x> <y> [--speed=<kn>]
30
+ #{__FILE__} ship shoot <x> <y>
31
+ #{__FILE__} mine (set|remove) <x> <y> [--moored|--drifting]
32
+ #{__FILE__} -h | --help
33
+ #{__FILE__} --version
19
34
 
20
35
  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
36
+ -h --help Show this screen.
37
+ --version Show version.
38
+ --speed=<kn> Speed in knots [default: 10].
39
+ --moored Moored (anchored) mine.
40
+ --drifting Drifting mine.
41
+
42
+ DOCOPT
43
+
44
+ begin
45
+ require "pp"
46
+ pp Docopt::docopt(doc)
47
+ rescue Docopt::Exit => e
48
+ puts e.message
47
49
  end
48
50
  ```
49
51
 
50
- Hell yeah! The option parser is generated based on `doc` string above, that you
51
- pass to the `Docopt` function.
52
+ Beat that! The option parser is generated based on the docstring above that is
53
+ passed to `docopt` function. `docopt` parses the usage pattern
54
+ (`Usage: ...`) and option descriptions (lines starting with dash "`-`") and
55
+ ensures that the program invocation matches the usage pattern; it parses
56
+ options, arguments and commands based on that. The basic idea is that
57
+ *a good help message has all necessary information in it to make a parser*.
52
58
 
53
- ```ruby
54
- require 'docopt'
55
- doc = "Usage: your_program.rb [options]
59
+ Installation
60
+ ===============================================================================
56
61
 
57
- -h --help Show this.
58
- -v --verbose Print more text.
59
- --quiet Print less text.
60
- -o FILE Specify output file [default: ./test.txt]"
62
+ Docopt is available via rubygems:
61
63
 
62
- options = Docopt(doc, version=nil, help=true)`
64
+ gem install docopt
63
65
 
64
- options['--help'] # returns true or false depending on option given
66
+ Alternatively, you can just drop `lib/docopt.rb` file into your project--it is
67
+ self-contained. [Get source on github](http://github.com/docopt/docopt.rb).
65
68
 
66
- ```
69
+ `docopt` has been confirmed to work with 1.8.7p370 and 1.9.3p194. If you have
70
+ noticed it working (or not working) with an earlier version, please raise an
71
+ issue and we will investigate support.
67
72
 
73
+ API
74
+ ===============================================================================
68
75
 
69
- `Docopt` takes 1 required and 2 optional arguments:
76
+ `Docopt` takes 1 required and 1 optional argument:
70
77
 
71
78
  - `doc` should be a string that
72
79
  describes **options** in a human-readable format, that will be parsed to create
@@ -81,6 +88,10 @@ section. Here is a quick example of such a string:
81
88
  --quiet Print less text.
82
89
  -o FILE Specify output file [default: ./test.txt].
83
90
 
91
+
92
+ The optional second argument contains a hash of additional data to influence
93
+ docopt. The following keys are supported:
94
+
84
95
  - `help`, by default `true`, specifies whether the parser should automatically
85
96
  print the usage-message (supplied as `doc`) in case `-h` or `--help` options
86
97
  are encountered. After showing the usage-message, the program will terminate.
@@ -97,101 +108,79 @@ Note, when `docopt` is set to automatically handle `-h`, `--help` and
97
108
  `--version` options, you still need to mention them in the options description
98
109
  (`doc`) for your users to know about them.
99
110
 
100
- The **return** value is an instance of the ```Docopt``` class:
101
-
102
- ```ruby
103
- doc = "Options:
104
- --verbose
105
- -o FILE Output file [default: out.txt]"
106
-
107
- options = Docopt(doc)
108
-
109
- puts options.inspect
110
- # --verbose=nil
111
- # -o="out.txt"
112
- ```
113
-
114
- You can access the values of options like a hash:
115
-
116
- ```
117
- doc = "Options:
118
- -v, --verbose Verbose output [default: true]
119
- -o FILE Output file [default: out.txt]"
120
-
121
- options = Docopt(doc)
111
+ The **return** value is just a dictionary with options, arguments and commands,
112
+ with keys spelled exactly like in a help message
113
+ (long versions of options are given priority). For example, if you invoke
114
+ the top example as::
122
115
 
123
- # The following are equivilant:
124
-
125
- puts options['-v']
126
- puts options['--verbose']
127
- puts options[:v]
128
- puts options[:verbose]
116
+ naval_fate.rb ship Guardian move 100 150 --speed=15
129
117
 
118
+ the return dictionary will be::
130
119
 
120
+ ```ruby
121
+ {"ship"=>true,
122
+ "new"=>false,
123
+ "<name>"=>["Guardian"],
124
+ "move"=>true,
125
+ "<x>"=>"100",
126
+ "<y>"=>"150",
127
+ "--speed"=>"15",
128
+ "shoot"=>false,
129
+ "mine"=>false,
130
+ "set"=>false,
131
+ "remove"=>false,
132
+ "--moored"=>false,
133
+ "--drifting"=>false,
134
+ "--help"=>false,
135
+ "--version"=>false}
131
136
  ```
132
137
 
133
- You can access positional arguments in `ARGV`.
134
-
135
- `doc` string format for your usage-message
138
+ Help message format
136
139
  ===============================================================================
137
140
 
138
- The main idea behind `docopt` is that a good usage-message (that describes
139
- options and defaults unambiguously) is enough to generate an option parser.
140
-
141
- Here are the simple rules (that you probably already follow) for your
142
- usage-message to be parsable:
143
-
144
- - Every line that starts with `-` or `--` (not counting spaces) is treated
145
- as an option description, e.g.:
146
-
147
- Options:
148
- --verbose # GOOD
149
- -o FILE # GOOD
150
- Other: --bad # BAD, line does not start with dash "-"
141
+ docopt.rb follows the docopt help message format.
142
+ You can find more details at
143
+ [official docopt git repo](https://github.com/docopt/docopt#help-message-format)
151
144
 
152
- - To specify that an option has an argument, put a word describing that
153
- argument after space (or equals `=` sign) as shown below.
154
- You can use comma if you want to separate options. In the example below both
155
- lines are valid, however you are recommended to stick to a single style.
156
145
 
157
- -o FILE --output=FILE # without comma, with "=" sign
158
- -i <file>, --input <file> # with comma, wihtout "=" sing
146
+ Examples
147
+ -------------------------------------------------------------------------------
159
148
 
160
- - Use two spaces to separate options with their informal description.
149
+ We have an extensive list of
150
+ [examples](https://github.com/docopt/docopt.rb/tree/master/examples)
151
+ which cover every aspect of functionality of `docopt`. Try them out,
152
+ read the source if in doubt.
161
153
 
162
- --verbose More text. # BAD, will be treated as if verbose option had
163
- # an argument "More", so use 2 spaces instead
164
- -q Quit. # GOOD
165
- -o FILE Output file. # GOOD
166
- --stdout Use stdout. # GOOD, 2 spaces
154
+ Data validation
155
+ -------------------------------------------------------------------------------
167
156
 
168
- - If you want to set a default value for an option with an argument, put it
169
- into the option description, in form `[default: <my-default-value>]`.
157
+ `docopt` does one thing and does it well: it implements your command-line
158
+ interface. However it does not validate the input data. We are looking
159
+ for ruby validation libraries to make your option parsing experiene
160
+ even more awesome!
161
+ If you've got any suggestions or think your awesome schema validation gem
162
+ fits well with `docopt.rb`, open an issue on github and enjoy the eternal glory!
170
163
 
171
- -i INSTANCE Instance of something [default: 1]
172
- --coefficient=K The K coefficient [default: 2.95]
173
- --output=FILE Output file [default: test.txt]
174
- --directory=DIR Some directory [default: ./]
175
-
176
- Something missing? Help porting [docopt](http://docopt.org/) to Ruby!
177
- ===============================================================================
178
-
179
- Compatibility notice:
164
+ Contribution
180
165
  ===============================================================================
181
166
 
182
- In order to maintain your program's compatibility with future versions
183
- of `docopt.rb` (as porting more features continues) you are recommended to
184
- keep the following in the begining of `doc` argument:
167
+ We would *love* to hear what you think about `docopt.rb`.
168
+ Contribute, make pull requrests, report bugs, suggest ideas and discuss
169
+ `docopt.rb` on
170
+ [issues page](http://github.com/docopt/docopt.rb/issues).
185
171
 
186
- Usage: my_program.rb [options] <arguments>...
172
+ If you want to discuss the original `docopt` reference,
173
+ point to [it's home](http://github.com/docopt/docopt) or
174
+ drop a line directly to vladimir@keleshev.com!
187
175
 
188
- or
189
-
190
- Usage: my_program.rb [options] <argument>
191
-
192
- or
176
+ Porting `docopt` to other languages
177
+ ===============================================================================
193
178
 
194
- Usage: my_program.rb [options]
179
+ Docopt is an interlinguistic (?) effort,
180
+ and this is the ruby port of `docopt`.
181
+ We coordinate our efforts with docopt community and try our best to
182
+ keep in sync with the python reference.
195
183
 
196
- (followed by an empty line), where you are free to change `my_program.rb`
197
- and `argument(s)` name inside of `<...>`.
184
+ Docopt community *loves* to hear what you think about `docopt`, `docopt.rb`
185
+ and other sister projects on docopt's
186
+ [issues page](http://github.com/docopt/docopt/issues).
@@ -0,0 +1,150 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
30
+ end
31
+
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
39
+
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
45
+
46
+ task :default => :test
47
+
48
+ require 'rake/testtask'
49
+ Rake::TestTask.new(:test) do |test|
50
+ test.libs << 'lib' << 'test'
51
+ test.pattern = 'test/**/test_*.rb'
52
+ test.verbose = true
53
+ end
54
+
55
+ desc "Generate RCov test coverage and open in your browser"
56
+ task :coverage do
57
+ require 'rcov'
58
+ sh "rm -fr coverage"
59
+ sh "rcov test/test_*.rb"
60
+ sh "open coverage/index.html"
61
+ end
62
+
63
+ require 'rdoc/task'
64
+ Rake::RDocTask.new do |rdoc|
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = "#{name} #{version}"
67
+ rdoc.rdoc_files.include('README*')
68
+ rdoc.rdoc_files.include('lib/**/*.rb')
69
+ end
70
+
71
+ desc "Open an irb session preloaded with this library"
72
+ task :console do
73
+ sh "irb -rubygems -r ./lib/#{name}.rb"
74
+ end
75
+
76
+ #############################################################################
77
+ #
78
+ # Custom tasks (add your own tasks here)
79
+ #
80
+ #############################################################################
81
+
82
+
83
+
84
+ #############################################################################
85
+ #
86
+ # Packaging tasks
87
+ #
88
+ #############################################################################
89
+
90
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
91
+ task :release => :build do
92
+ unless `git branch` =~ /^\* master$/
93
+ puts "You must be on the master branch to release!"
94
+ exit!
95
+ end
96
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
97
+ sh "git tag v#{version}"
98
+ sh "git push origin master"
99
+ sh "git push origin v#{version}"
100
+ sh "gem push pkg/#{name}-#{version}.gem"
101
+ end
102
+
103
+ desc "Build #{gem_file} into the pkg directory"
104
+ task :build => :gemspec do
105
+ sh "mkdir -p pkg"
106
+ sh "gem build #{gemspec_file}"
107
+ sh "mv #{gem_file} pkg"
108
+ end
109
+
110
+ desc "Generate #{gemspec_file}"
111
+ task :gemspec => :validate do
112
+ # read spec file and split out manifest section
113
+ spec = File.read(gemspec_file)
114
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
115
+
116
+ # replace name version and date
117
+ replace_header(head, :name)
118
+ replace_header(head, :version)
119
+ replace_header(head, :date)
120
+ #comment this out if your rubyforge_project has a different name
121
+ replace_header(head, :rubyforge_project)
122
+
123
+ # determine file list from git ls-files
124
+ files = `git ls-files`.
125
+ split("\n").
126
+ sort.
127
+ reject { |file| file =~ /^\./ }.
128
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
129
+ map { |file| " #{file}" }.
130
+ join("\n")
131
+
132
+ # piece file back together and write
133
+ manifest = " s.files = %w[\n#{files}\n ]\n"
134
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
135
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
136
+ puts "Updated #{gemspec_file}"
137
+ end
138
+
139
+ desc "Validate #{gemspec_file}"
140
+ task :validate do
141
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
142
+ unless libfiles.empty?
143
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
144
+ exit!
145
+ end
146
+ unless Dir['VERSION*'].empty?
147
+ puts "A `VERSION` file at root level violates Gem best practices."
148
+ exit!
149
+ end
150
+ end