cli 0.4.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +87 -15
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/cli.gemspec +4 -4
- data/lib/cli.rb +11 -6
- data/lib/cli/dsl.rb +6 -5
- data/spec/argument_spec.rb +41 -0
- data/spec/cli_spec.rb +4 -0
- metadata +6 -6
data/README.md
CHANGED
@@ -1,25 +1,12 @@
|
|
1
1
|
# CLI
|
2
2
|
|
3
|
-
Command Line Interface gem allows you to quickly specify command argument parser that will automatically
|
4
|
-
|
5
|
-
CLI supports following specifiers:
|
6
|
-
|
7
|
-
* switch - (`--verbose` or `-v`) binary operators, by default set to nil, when specified set to true
|
8
|
-
* option - (`--name John` or `-n John`) switches that take value; default value can be specified, otherwise defaults to nil
|
9
|
-
* options - (`-n John -n Frank`) like option but can be used multiple times on command line; default value or array of values can be given, otherwise defaults to empty array
|
10
|
-
* argument - (`John`) capture single command; default value can be specified; raises error if not given
|
11
|
-
* arguments - (`John Frank`) capture multiple command arguments; defaults to empty array
|
12
|
-
* stdin - if standard input is to be handled it can be mentioned in usage output; also stdin data casting is supported
|
13
|
-
|
14
|
-
Each element can have description that will be visible in the usage output.
|
15
|
-
|
16
|
-
See examples and specs for more info.
|
3
|
+
Command Line Interface gem allows you to quickly specify command argument parser that will automatically generate usage, handle stdin, switches, options and arguments with default values and value casting.
|
17
4
|
|
18
5
|
## Installing
|
19
6
|
|
20
7
|
gem install cli
|
21
8
|
|
22
|
-
##
|
9
|
+
## Examples
|
23
10
|
|
24
11
|
### Sinatra server example
|
25
12
|
|
@@ -273,6 +260,91 @@ Prints:
|
|
273
260
|
501:20 pkg/cli-0.0.2.gem
|
274
261
|
...
|
275
262
|
|
263
|
+
## Usage
|
264
|
+
|
265
|
+
`CLI.new` takes a block where you specify parser behavior. The returned object is a parser that has `#parse` and `#parse!` methods.
|
266
|
+
|
267
|
+
### `#parse` method
|
268
|
+
|
269
|
+
It will take argument array (defaults to ARGV), standard input IO (defaults to STDIO) and standard error IO (defaults to STDERR).
|
270
|
+
|
271
|
+
The method will parse argument array and cast standard input IO according to parser specification and return OpenStruct kind of object with resulting values.
|
272
|
+
|
273
|
+
The returned object will have `help` attribute set if `--help` or `-h` switch was found in argument array or `version` attribute if `--version` argument was found.
|
274
|
+
In other case all the attributes will be set to appropriate values depending on argument array and parser specification.
|
275
|
+
In case of parsing error `CLI::ParsingError` kind of exception will be raised.
|
276
|
+
|
277
|
+
### `#parse!` method
|
278
|
+
|
279
|
+
This is higher level version of `#parse` method that will exit the program and print out usage if there was parsing error. Also it will display usage on `--help` or `-h` switch and version string on `--version` switch found in argument array.
|
280
|
+
|
281
|
+
In other case it will return OpenStruct object from `#parse` method.
|
282
|
+
|
283
|
+
Additionally this method can be called with a block that will get the OpenStruct like object before returning it. This block should contain additional value verifications and if it raises RuntimeError (via `fail` method for instance) the error message will be displayed followed by usage and the program will exit.
|
284
|
+
|
285
|
+
### Parser behavior specifiers
|
286
|
+
|
287
|
+
#### description 'string'
|
288
|
+
The *string* will be displayed in usage output as your program short description.
|
289
|
+
|
290
|
+
#### version 'string'
|
291
|
+
The *string* representing program version that will be displayed when `--version` switch is used
|
292
|
+
|
293
|
+
#### switch :name [, options hash]
|
294
|
+
|
295
|
+
When switch is specified in the command argument list the object returned by `#parse` or `#parse!` will contain argument of same name set to `true`. Otherwise the argument value will be `nil`.
|
296
|
+
|
297
|
+
*:name* should be a symbol that will map to long switch (`--name`) where underscore (`_`) will be replaced with minus (`-`). Name has to be unique.
|
298
|
+
|
299
|
+
Option hash can contain following pairs:
|
300
|
+
|
301
|
+
* **:short => :symbol** - where *:symbol* is a single letter symbol that will represent short switch name (`-n`). Short name has to be unique.
|
302
|
+
* **:description => 'string'** - switch description string that will be displayed in the usage output
|
303
|
+
|
304
|
+
#### option :name [, options hash]
|
305
|
+
|
306
|
+
Same as *switch* but additionally it has to be followed by a value on the command argument list.
|
307
|
+
The value after casting (if used) will be available from the `#parse` or `#parse!` returned object as argument of the same name.
|
308
|
+
|
309
|
+
In addition to *switch*, option hash can have following pairs:
|
310
|
+
|
311
|
+
* **:default => value** - use default value of *value* if the option was not specified on the command argument list. The *value* will firstly be casted to string (with `#to_s`) and then it will be casted if casting is specified.
|
312
|
+
* **:cast => cast specifier** - cast the provided value (or default) with given *cast specifier*.
|
313
|
+
The specifier can be a class constant (like `Integer` or `Float`); the value will be provided to `#new` method of the class and resulting object used as option value. When provided constant does not respond to `#new` (i.e. it is a module) the `#load` method will be tried. If provided specifier is a Proc (or `lambda {}`) the Proc will be called with the value and resulting value will be used. Otherwise `CLI::ParsingError::CastError` will be raised.
|
314
|
+
* **:required => true** - if used and no *default* value is specified the `#parse` method will fail with `CLI::ParsingError::MissingOptionValueError` if the option was not specified in the command argument list. If `#parse!` method was used the program will exit with appropriate message.
|
315
|
+
|
316
|
+
#### options :name [, options hash]
|
317
|
+
|
318
|
+
Same as *option* but can be specified multiple times in the command argument list.
|
319
|
+
The resulting `#parse` or `#parse!` returned object will contain an argument with the same name that will always be an array.
|
320
|
+
The array may be empty if the option was not used and *required* option was not set, otherwise it will contain casted values in order of specification in the command argument list.
|
321
|
+
|
322
|
+
#### argument :name [,options hash]
|
323
|
+
|
324
|
+
After the parser encounters command line argument that is not a *switch* or *option* or it is literally `--` string it will start matching arguments.
|
325
|
+
|
326
|
+
Each argument will be matched to argument specifications in order and their value after optional casting will be available as `#parse` or `#parse!` returned object argument with the same name.
|
327
|
+
|
328
|
+
Options hash can contain the same pairs as *option* expect of **:short => :symbol**.
|
329
|
+
|
330
|
+
If defaults are used the parser will keep using default values until it has enough command line arguments available to fill all mandatory arguments.
|
331
|
+
Arguments are required by default, use **:required => false** option pair to use `nil` value if argument is not specified on the command line argument list.
|
332
|
+
|
333
|
+
#### arguments :name [,options hash]
|
334
|
+
|
335
|
+
Same as *argument* but will match one or more arguments and provide them in array of casted values.
|
336
|
+
If argument is not required and not specified in command argument list then its value will be an empty array.
|
337
|
+
|
338
|
+
When used with *argument* specifiers that use default values the parser will try to assign at least one value to this specifier, but not more values so that all mandatory (that have no default and are required) arguments will be assigned.
|
339
|
+
|
340
|
+
#### stdin :name, [options hash]
|
341
|
+
|
342
|
+
Used once to specify that stdin should be handled.
|
343
|
+
When used the `#parse` or `#parse!` returned object will have `stdin` argument that by default will contain stdin IO object.
|
344
|
+
|
345
|
+
As with *switch* specifier the **:description => 'string'** can be used.
|
346
|
+
Also **:cast => cast specifier** option pair can be used but the value will be an IO object and not string.
|
347
|
+
|
276
348
|
## Contributing to CLI
|
277
349
|
|
278
350
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
data/Rakefile
CHANGED
@@ -17,8 +17,8 @@ Jeweler::Tasks.new do |gem|
|
|
17
17
|
gem.name = "cli"
|
18
18
|
gem.homepage = "http://github.com/jpastuszek/cli"
|
19
19
|
gem.license = "MIT"
|
20
|
-
gem.summary = %Q{
|
21
|
-
gem.description = %Q{
|
20
|
+
gem.summary = %Q{Command line argument parser with stdin handling and usage generator}
|
21
|
+
gem.description = %Q{Command Line Interface gem allows you to quickly specify command argument parser that will automatically generate usage, handle stdin, switches, options and arguments with default values and value casting}
|
22
22
|
gem.email = "jpastuszek@gmail.com"
|
23
23
|
gem.authors = ["Jakub Pastuszek"]
|
24
24
|
# dependencies defined in Gemfile
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0
|
data/cli.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "cli"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "1.0.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jakub Pastuszek"]
|
12
|
-
s.date = "2011-12-
|
13
|
-
s.description = "
|
12
|
+
s.date = "2011-12-31"
|
13
|
+
s.description = "Command Line Interface gem allows you to quickly specify command argument parser that will automatically generate usage, handle stdin, switches, options and arguments with default values and value casting"
|
14
14
|
s.email = "jpastuszek@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE.txt",
|
@@ -51,7 +51,7 @@ Gem::Specification.new do |s|
|
|
51
51
|
s.licenses = ["MIT"]
|
52
52
|
s.require_paths = ["lib"]
|
53
53
|
s.rubygems_version = "1.8.10"
|
54
|
-
s.summary = "
|
54
|
+
s.summary = "Command line argument parser with stdin handling and usage generator"
|
55
55
|
|
56
56
|
if s.respond_to? :specification_version then
|
57
57
|
s.specification_version = 3
|
data/lib/cli.rb
CHANGED
@@ -181,7 +181,7 @@ class CLI
|
|
181
181
|
end
|
182
182
|
|
183
183
|
if @version and arg == '--version'
|
184
|
-
values.version = "#{name} version \"#{@version}\"\n"
|
184
|
+
values.version = "#{CLI.name} version \"#{@version}\"\n"
|
185
185
|
return values
|
186
186
|
end
|
187
187
|
end
|
@@ -234,10 +234,15 @@ class CLI
|
|
234
234
|
# process arguments
|
235
235
|
arguments = @arguments.dup
|
236
236
|
while argument = arguments.shift
|
237
|
-
value = if arguments.mandatory.length >= argv.length
|
238
|
-
argument.
|
237
|
+
value = if arguments.mandatory.length >= argv.length
|
238
|
+
if argument.has_default?
|
239
|
+
argument.default
|
240
|
+
elsif not argument.mandatory?
|
241
|
+
argument.multiple? ? [] : nil
|
242
|
+
else
|
243
|
+
raise ParsingError::MandatoryArgumentNotSpecifiedError.new(argument) if argv.empty?
|
244
|
+
end
|
239
245
|
else
|
240
|
-
raise ParsingError::MandatoryArgumentNotSpecifiedError.new(argument) if argv.empty?
|
241
246
|
arg = argv.shift
|
242
247
|
|
243
248
|
if argument.multiple?
|
@@ -285,14 +290,14 @@ class CLI
|
|
285
290
|
end
|
286
291
|
end
|
287
292
|
|
288
|
-
def name
|
293
|
+
def self.name
|
289
294
|
File.basename $0
|
290
295
|
end
|
291
296
|
|
292
297
|
def usage(msg = nil)
|
293
298
|
out = StringIO.new
|
294
299
|
out.puts msg if msg
|
295
|
-
out.print "Usage: #{name}"
|
300
|
+
out.print "Usage: #{CLI.name}"
|
296
301
|
out.print ' [switches|options]' if not @switches.empty? and not @options.empty?
|
297
302
|
out.print ' [switches]' if not @switches.empty? and @options.empty?
|
298
303
|
out.print ' [options]' if @switches.empty? and not @options.empty?
|
data/lib/cli/dsl.rb
CHANGED
@@ -62,7 +62,7 @@ class CLI
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def mandatory?
|
65
|
-
not has_default?
|
65
|
+
not has_default? and @options[:required]
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -87,6 +87,11 @@ class CLI
|
|
87
87
|
include DSL::Cast
|
88
88
|
include DSL::Description
|
89
89
|
|
90
|
+
def initialize(name, options = {})
|
91
|
+
super
|
92
|
+
@options[:required] = true unless @options.member?(:required)
|
93
|
+
end
|
94
|
+
|
90
95
|
def to_s
|
91
96
|
name.to_s.tr('_', '-')
|
92
97
|
end
|
@@ -148,10 +153,6 @@ class CLI
|
|
148
153
|
include DSL::Value
|
149
154
|
include DSL::Cast
|
150
155
|
|
151
|
-
def mandatory?
|
152
|
-
not has_default? and @options[:required]
|
153
|
-
end
|
154
|
-
|
155
156
|
def multiple?
|
156
157
|
false
|
157
158
|
end
|
data/spec/argument_spec.rb
CHANGED
@@ -150,6 +150,16 @@ describe CLI do
|
|
150
150
|
}.should raise_error CLI::ParserError::MultipleArgumentsSpecifierError, "only one 'arguments' specifier can be used, got: test1, test3"
|
151
151
|
end
|
152
152
|
|
153
|
+
it "should not require non mandatory argument" do
|
154
|
+
ps = CLI.new do
|
155
|
+
argument :log, :cast => Pathname
|
156
|
+
argument :test, :required => false
|
157
|
+
end.parse(['/tmp'])
|
158
|
+
ps.log.should be_a Pathname
|
159
|
+
ps.log.to_s.should == '/tmp'
|
160
|
+
ps.test.should be_nil
|
161
|
+
end
|
162
|
+
|
153
163
|
describe "with defaults" do
|
154
164
|
it "when not enought arguments given it should fill required arguments only with defaults" do
|
155
165
|
ps = CLI.new do
|
@@ -180,6 +190,19 @@ describe CLI do
|
|
180
190
|
ps.magick.should == 'word'
|
181
191
|
ps.test.should == 'hello'
|
182
192
|
ps.code.should == 123
|
193
|
+
|
194
|
+
ps = CLI.new do
|
195
|
+
argument :log, :cast => Pathname
|
196
|
+
argument :magick, :default => 'word'
|
197
|
+
argument :test0, :required => false
|
198
|
+
argument :test
|
199
|
+
argument :code, :cast => Integer, :default => '123'
|
200
|
+
end.parse(['/tmp', 'hello'])
|
201
|
+
ps.log.to_s.should == '/tmp'
|
202
|
+
ps.magick.should == 'word'
|
203
|
+
ps.test0.should be_nil
|
204
|
+
ps.test.should == 'hello'
|
205
|
+
ps.code.should == 123
|
183
206
|
end
|
184
207
|
|
185
208
|
it "should fill defaults form the beginning if more than required arguments are given" do
|
@@ -248,6 +271,24 @@ describe CLI do
|
|
248
271
|
ps.test2.should == 'test2'
|
249
272
|
ps.code.should == 123
|
250
273
|
end
|
274
|
+
|
275
|
+
it "should use empty array of values for multiple arguments argument when not enought arguments given" do
|
276
|
+
ps = CLI.new do
|
277
|
+
argument :log, :cast => Pathname
|
278
|
+
argument :magick, :default => 'word'
|
279
|
+
argument :test
|
280
|
+
arguments :words, :required => false
|
281
|
+
argument :test2
|
282
|
+
argument :code, :cast => Integer, :default => '123'
|
283
|
+
end.parse(['/tmp', 'test', 'test2'])
|
284
|
+
|
285
|
+
ps.log.to_s.should == '/tmp'
|
286
|
+
ps.magick.should == 'word'
|
287
|
+
ps.test.should == 'test'
|
288
|
+
ps.words.should == []
|
289
|
+
ps.test2.should == 'test2'
|
290
|
+
ps.code.should == 123
|
291
|
+
end
|
251
292
|
end
|
252
293
|
end
|
253
294
|
end
|
data/spec/cli_spec.rb
CHANGED
@@ -28,6 +28,10 @@ describe CLI do
|
|
28
28
|
ps.debug.should be_true
|
29
29
|
end
|
30
30
|
|
31
|
+
it "provides name method that provides current program name" do
|
32
|
+
CLI.name.should == 'rspec'
|
33
|
+
end
|
34
|
+
|
31
35
|
describe "parse!" do
|
32
36
|
it "should return value structure with all the values on successful parsing" do
|
33
37
|
ps = CLI.new do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 1.0.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jakub Pastuszek
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-12-
|
18
|
+
date: 2011-12-31 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
type: :development
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
prerelease: false
|
124
124
|
name: ruby-ip
|
125
125
|
version_requirements: *id007
|
126
|
-
description:
|
126
|
+
description: Command Line Interface gem allows you to quickly specify command argument parser that will automatically generate usage, handle stdin, switches, options and arguments with default values and value casting
|
127
127
|
email: jpastuszek@gmail.com
|
128
128
|
executables: []
|
129
129
|
|
@@ -194,6 +194,6 @@ rubyforge_project:
|
|
194
194
|
rubygems_version: 1.8.10
|
195
195
|
signing_key:
|
196
196
|
specification_version: 3
|
197
|
-
summary:
|
197
|
+
summary: Command line argument parser with stdin handling and usage generator
|
198
198
|
test_files: []
|
199
199
|
|