docopt 0.0.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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