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 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 handle usage rendering, casting, default values and other stuff for you.
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
- ## Usage
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{Helps writing Command-line interface program}
21
- gem.description = %Q{Provides DSL for command-line options, switches and arguments parser and stdin handling with generated usage printer}
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.4.0
1
+ 1.0.0
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cli"
8
- s.version = "0.4.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-30"
13
- s.description = "Provides DSL for command-line options, switches and arguments parser and stdin handling with generated usage printer"
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 = "Helps writing Command-line interface program"
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 and argument.has_default?
238
- argument.default
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?
@@ -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
@@ -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
@@ -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: 15
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 4
9
9
  - 0
10
- version: 0.4.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-30 00:00:00 Z
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: Provides DSL for command-line options, switches and arguments parser and stdin handling with generated usage printer
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: Helps writing Command-line interface program
197
+ summary: Command line argument parser with stdin handling and usage generator
198
198
  test_files: []
199
199