getoptions 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README +117 -0
  2. data/lib/getoptions.rb +427 -0
  3. data/test/standard.rb +250 -0
  4. metadata +48 -0
data/README ADDED
@@ -0,0 +1,117 @@
1
+ == Synopsis
2
+
3
+ GetOptions - Yet another command line argument parser for Ruby.
4
+
5
+ If you are familiar with Perl's Getopt::Long specification syntax you should
6
+ feel right at home. The following specifications are currently supported:
7
+
8
+ default -- This is the default case, the option is either there or it isn't
9
+ flag! -- You can specify either --flag or --no-flag to set true or false
10
+ name|a1|a2 -- You can use '|' to set up option aliases. In this example, the
11
+ 'name' option will be set if either 'name', 'a1', or 'a2' is
12
+ specified on the command line.
13
+
14
+ optional:x -- An argument with an optional argument of type x
15
+ required=x -- An argument with a required argument of type x
16
+ alist=@x -- An argument that takes a list of things of type x
17
+
18
+ The following types are currently supported:
19
+ s|string -- A string value
20
+ i|integer -- An integer value
21
+ f|float -- A floating point value
22
+ For integer and float, an exception will be thrown if ruby
23
+ can't find a way to convert the supplied argument string.
24
+
25
+ As with Getopt::Long, you specify the long form of the option, but it can
26
+ parse short options as well. For example, if you have an option named 'help',
27
+ both --help and -h would enable the option. You can also specify a small
28
+ portion of the long form, and if it is enough to uniquely identify the option,
29
+ it will work. For example, --he or --hel would map to --help as long as you
30
+ don't have --hell, --hello, ... as an option.
31
+
32
+ There are several ways to get the option data after parsing. Of course there
33
+ is the hash style, which could look something like:
34
+
35
+ options = GetOptions.new(%w(help verbose!))
36
+ puts "I'm going to go do stuff now..." if options['verbose']
37
+
38
+ You can also use a symbol (options[:verbose]) instead of a string if you want.
39
+ In addition, you can access fields using the .-style accessor syntax:
40
+
41
+ show_help() if options.help
42
+
43
+
44
+ == Examples
45
+
46
+ Kicking the tires:
47
+
48
+ $ cat myscript1.rb
49
+ require 'getoptions'
50
+
51
+ opt = GetOptions.new(%w(help debug! verbose+ prefix:s size=i host=@s))
52
+ p opt
53
+
54
+ $ ./myscript1.rb --help
55
+ help: true
56
+
57
+ $ ./myscript1.rb --debug
58
+ debug: true
59
+
60
+ $ ./myscript1.rb --no-debug
61
+ debug: false
62
+
63
+ $ ./myscript1.rb -vvvvv
64
+ verbose: 5
65
+
66
+ $ ./myscript1.rb -vv --verbose
67
+ verbose: 3
68
+
69
+ $ ./myscript1.rb --pre
70
+ prefix: nil
71
+
72
+ $ ./myscript1.rb --pre myprefix
73
+ prefix: "myprefix"
74
+
75
+ $ ./myscript1.rb --size 5
76
+ size: 5
77
+
78
+
79
+ Mixing arguments with non-arguments:
80
+
81
+ $ cat myscript2.rb
82
+ require 'getoptions'
83
+
84
+ opt = GetOptions.new(%w(help debug! verbose+ prefix:s size=i host=@s))
85
+ p opt
86
+ puts '--'
87
+ p ARGV
88
+
89
+ $ ./myscript2.rb --siz 10 file1 file2 file3
90
+ size: 10
91
+ --
92
+ ["file1", "file2", "file3"]
93
+
94
+ $ ./myscript2.rb --host host1 host2 -- file1 file2 file3
95
+ host: ["host1", "host2"]
96
+ --
97
+ ["file1", "file2", "file3"]
98
+
99
+
100
+ Processing your own input stream:
101
+
102
+ $ cat myscript3.rb
103
+ require 'getoptions'
104
+
105
+ input = %w(-vv -w 1 -2 -- file1)
106
+ opt = GetOptions.new(%w(verbose+ weights:@i), input)
107
+ p opt
108
+ puts '--'
109
+ p input
110
+
111
+ $ ./myscript3.rb
112
+ verbose: 2
113
+ weights: [1, -2]
114
+ --
115
+ ["file1"]
116
+
117
+
@@ -0,0 +1,427 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # == Synopsis
5
+ #
6
+ # GetOptions - Yet another command line argument parser for Ruby.
7
+ #
8
+ # If you are familiar with Perl's Getopt::Long specification syntax you should
9
+ # feel right at home. The following specifications are currently supported:
10
+ #
11
+ # default -- This is the default case, the option is either there or it isn't
12
+ # flag! -- You can specify either --flag or --no-flag to set true or false
13
+ # name|a1|a2 -- You can use '|' to set up option aliases. In this example, the
14
+ # 'name' option will be set if either 'name', 'a1', or 'a2' is
15
+ # specified on the command line.
16
+ #
17
+ # optional:x -- An argument with an optional argument of type x
18
+ # required=x -- An argument with a required argument of type x
19
+ # alist=@x -- An argument that takes a list of things of type x
20
+ #
21
+ # The following types are currently supported:
22
+ # s|string -- A string value
23
+ # i|integer -- An integer value
24
+ # f|float -- A floating point value
25
+ # For integer and float, an exception will be thrown if ruby
26
+ # can't find a way to convert the supplied argument string.
27
+ #
28
+ # As with Getopt::Long, you specify the long form of the option, but it can
29
+ # parse short options as well. For example, if you have an option named 'help',
30
+ # both --help and -h would enable the option. You can also specify a small
31
+ # portion of the long form, and if it is enough to uniquely identify the option,
32
+ # it will work. For example, --he or --hel would map to --help as long as you
33
+ # don't have --hell, --hello, ... as an option.
34
+ #
35
+ # There are several ways to get the option data after parsing. Of course there
36
+ # is the hash style, which could look something like:
37
+ #
38
+ # options = GetOptions.new(%w(help verbose!))
39
+ # puts "I'm going to go do stuff now..." if options['verbose']
40
+ #
41
+ # You can also use a symbol (options[:verbose]) instead of a string if you want.
42
+ # In addition, you can access fields using the .-style accessor syntax:
43
+ #
44
+ # show_help() if options.help
45
+ #
46
+ #
47
+ # == Examples
48
+ #
49
+ # Kicking the tires:
50
+ #
51
+ # $ cat myscript1.rb
52
+ # require 'getoptions'
53
+ #
54
+ # opt = GetOptions.new(%w(help debug! verbose+ prefix:s size=i host=@s))
55
+ # p opt
56
+ #
57
+ # $ ./myscript1.rb --help
58
+ # help: true
59
+ #
60
+ # $ ./myscript1.rb --debug
61
+ # debug: true
62
+ #
63
+ # $ ./myscript1.rb --no-debug
64
+ # debug: false
65
+ #
66
+ # $ ./myscript1.rb -vvvvv
67
+ # verbose: 5
68
+ #
69
+ # $ ./myscript1.rb -vv --verbose
70
+ # verbose: 3
71
+ #
72
+ # $ ./myscript1.rb --pre
73
+ # prefix: nil
74
+ #
75
+ # $ ./myscript1.rb --pre myprefix
76
+ # prefix: "myprefix"
77
+ #
78
+ # $ ./myscript1.rb --size 5
79
+ # size: 5
80
+ #
81
+ #
82
+ # Mixing arguments with non-arguments:
83
+ #
84
+ # $ cat myscript2.rb
85
+ # require 'getoptions'
86
+ #
87
+ # opt = GetOptions.new(%w(help debug! verbose+ prefix:s size=i host=@s))
88
+ # p opt
89
+ # puts '--'
90
+ # p ARGV
91
+ #
92
+ # $ ./myscript2.rb --siz 10 file1 file2 file3
93
+ # size: 10
94
+ # --
95
+ # ["file1", "file2", "file3"]
96
+ #
97
+ # $ ./myscript2.rb --host host1 host2 -- file1 file2 file3
98
+ # host: ["host1", "host2"]
99
+ # --
100
+ # ["file1", "file2", "file3"]
101
+ #
102
+ #
103
+ # Processing your own input stream:
104
+ #
105
+ # $ cat myscript3.rb
106
+ # require 'getoptions'
107
+ #
108
+ # input = %w(-vv -w 1 -2 -- file1)
109
+ # opt = GetOptions.new(%w(verbose+ weights:@i), input)
110
+ # p opt
111
+ # puts '--'
112
+ # p input
113
+ #
114
+ # $ ./myscript3.rb
115
+ # verbose: 2
116
+ # weights: [1, -2]
117
+ # --
118
+ # ["file1"]
119
+ #
120
+ #
121
+
122
+ require 'rdoc/usage'
123
+ require 'abbrev'
124
+
125
+ class GetOptions
126
+
127
+ class ParseError < Exception
128
+ end
129
+
130
+ # For select, reject, and other goodies
131
+ include Enumerable
132
+
133
+ # :call-seq:
134
+ # new(option_specs, input = ARGV) -> opt
135
+ #
136
+ # Parse input based on metadata in option_specs.
137
+ #
138
+ # == Examples
139
+ #
140
+ # opt = GetOptions.new(%w(help verbose! strarg=s))
141
+ # puts "I'm going to go do stuff..." if (opt.verbose)
142
+ # ...
143
+ #
144
+ def initialize(option_specs, input = ARGV)
145
+ build_dict(option_specs)
146
+
147
+ @options = {}
148
+ leftover = []
149
+ until input.empty?
150
+ arg = input.shift
151
+
152
+ case arg
153
+ # Stop if you hit --
154
+ when '--'
155
+ break
156
+
157
+ # Long form
158
+ when /^--(\S+)/
159
+ o, a = $1.split('=', 2)
160
+ input.unshift(a) if a
161
+ input = process_arguments(o, input)
162
+
163
+ # Short form
164
+ when /^-(\S+)/
165
+ o, a = $1.split('=', 2)
166
+ input.unshift(a) if a
167
+ o.scan(/./) do |c|
168
+ input = process_arguments(c, input)
169
+ end
170
+
171
+ # Not an option, leave it
172
+ else
173
+ leftover << arg
174
+ end
175
+ end
176
+
177
+ # Put what didn't parse back into input
178
+ input.concat(leftover)
179
+ end
180
+
181
+ # :call-seq:
182
+ # opt[key] -> value
183
+ #
184
+ # Returns the value of the specified option. If the option was in
185
+ # the specification but not found in the input data, nill is returned.
186
+ #
187
+ def [](k)
188
+ raise ParseError.new("`nil' cannot be an option key") if (k.nil?)
189
+ sym = k.to_sym
190
+ key = k.to_s
191
+
192
+ case
193
+ when @options.has_key?(sym); @options[sym]
194
+ when @dict.has_key?(key); nil
195
+ else raise ParseError.new("program tried to access an unknown option: #{key.inspect}")
196
+ end
197
+ end
198
+
199
+ # :call-seq:
200
+ # has_option?(key) -> true or false
201
+ #
202
+ # Returns true if the specified key exists in the option input.
203
+ #
204
+ # == Examples
205
+ #
206
+ # opt = GetOptions.new(%w(help verbose! strarg=s))
207
+ # puts "I'm going to go do stuff..." if (opt.has_option(:verbose))
208
+ # puts "I don't exist..." if (opt.has_option(:bogus))
209
+ # ...
210
+ #
211
+ def has_option?(k)
212
+ raise ParseError.new("`nil' cannot be an option key") if (k.nil?)
213
+ @options.has_key?(k.to_sym)
214
+ end
215
+
216
+ alias to_s inspect
217
+
218
+ def inspect
219
+ @options.sort_by{|k| k.to_s}.collect do |key, val|
220
+ "%s: %s" % [key.inspect, val.inspect]
221
+ end.join($/)
222
+ end
223
+
224
+ # :call-seq:
225
+ # opt.each { |key,val| block } -> Hash
226
+ #
227
+ # Iterate over each parsed option name and value.
228
+ #
229
+ # == Examples
230
+ # opt.each do |key,val|
231
+ # puts "#{key} -> #{val.inspect}"
232
+ # end
233
+ #
234
+ def each
235
+ @options.each do |key,value|
236
+ yield key.to_s, value
237
+ end
238
+ end
239
+
240
+ private
241
+
242
+ # Wrapper to hash accessor
243
+ def method_missing(method, *args) #:nodoc:
244
+ self[method]
245
+ end
246
+
247
+ # Builds a keyword dictionary based on option specification
248
+ def build_dict(option_specs) #:nodoc:
249
+ @dict = {}
250
+ keys = []
251
+ option_specs.each do |option_spec|
252
+ # Parse the specification
253
+ m, label, oper, cont, arg = *option_spec.match(/([^=:]+)(?:([=:])([@])?(\w+))?/)
254
+ raise ParseError.new("invalid option format for '#{option_spec}'") unless m
255
+
256
+ # Figure out the specification type
257
+ is_bang_arg = label.gsub!(/!$/, '')
258
+ is_increment = label.gsub!(/\+$/, '')
259
+ forms = label.split('|')
260
+ key = forms.first
261
+
262
+ # Create an instance of OptionDefinition to hold metat data
263
+ od = OptionDefinition.new(key)
264
+ od.option_type = :boolean if is_bang_arg
265
+ od.option_type = :increment if is_increment
266
+ if (arg)
267
+ od.option_type = (oper == '=') ? :required_argument : :optional_argument
268
+ od.container_type = case cont
269
+ when '@'; :array
270
+ else :scalar
271
+ end
272
+ od.argument_type = case arg
273
+ when 'f', 'float' ; :float
274
+ when 'i', 'integer'; :integer
275
+ when 's', 'string' ; :string
276
+ else raise ParseError.new("unknown argument type '#{arg}'")
277
+ end
278
+ end
279
+
280
+ # Process alternate key names
281
+ forms.each do |k|
282
+ @dict[k] = od.dup
283
+ keys << k
284
+ end
285
+
286
+ # Only support negation on long option names
287
+ if (is_bang_arg)
288
+ @dict["no-#{key}"] = od.dup
289
+ end
290
+ end
291
+
292
+ # Allow abbreviated long options
293
+ keys.abbrev.each do |ab,key|
294
+ @dict[ab] = @dict[key].dup
295
+ @dict[ab].abbreviated = true unless (ab == key)
296
+ end
297
+ end
298
+
299
+ # Parse all arguments for the current option
300
+ def process_arguments(k, input) #:nodoc:
301
+ if (opt = @dict[k])
302
+ key = opt.key
303
+ case opt.option_type
304
+ when :boolean
305
+ @options[key] = (k != "no-#{key}")
306
+ when :increment
307
+ @options[key] ||= 0
308
+ @options[key] += 1
309
+ when :optional_argument, :required_argument
310
+ args = []
311
+ loop do
312
+ break if (input.empty?)
313
+ arg = input.shift
314
+
315
+ is_arg = case arg
316
+ # If it matches a long argument name, it isn't an argument
317
+ when '--'
318
+ false
319
+ when /^--(\S+)/
320
+ o, a = $1.split('=', 2)
321
+ !@dict.has_key?(o)
322
+ # If this is a valid shorthand option string, abort
323
+ when /^-(\S+)/
324
+ o, a = $1.split('=', 2)
325
+ !o.scan(/./).all? { |c| @dict.has_key?(c) }
326
+ else
327
+ true
328
+ end
329
+
330
+ # We've hit another option, get outta here
331
+ #if (arg =~ /^-/)
332
+ unless (is_arg)
333
+ input.unshift(arg)
334
+ break
335
+ end
336
+ args << arg
337
+ # If this is a scalar type, stop after the first argument
338
+ break if opt.container_type == :scalar
339
+ end
340
+
341
+ if (args.empty?)
342
+ # No argument found, and one was required, complain about it
343
+ if (opt.option_type == :required_argument)
344
+ raise ParseError.new("missing required argument for '#{key}'")
345
+ # No argument found, but it was optional, set a default value
346
+ else
347
+ case opt.container_type
348
+ when :scalar; @options[key] = nil
349
+ when :array; @options[key] = []
350
+ end
351
+ end
352
+ else
353
+ args.each do |arg|
354
+ val = case opt.argument_type
355
+ when :float
356
+ # Try to parse float option, toss an exception if the parse failed
357
+ Float(arg) rescue
358
+ raise ParseError.new("expecting float value for option '#{key}'")
359
+ when :integer
360
+ # Try to parse integer option, toss an exception if the parse failed
361
+ Integer(arg) rescue
362
+ raise ParseError.new("expecting integer value for option '#{key}'")
363
+ else
364
+ # Assume string type (no processing needed)
365
+ arg
366
+ end
367
+ # Either set the option value (scalar) or add it to the list (array)
368
+ case opt.container_type
369
+ when :scalar; @options[key] = val
370
+ when :array; (@options[key] ||= []) << val
371
+ end
372
+ end
373
+ end
374
+ end
375
+ else
376
+ # If an exact match isn't found, try to make a suggestion
377
+ candidates = @dict.keys.select do |c|
378
+ (!@dict[c].is_abbreviated? && c =~ /^#{k}/)
379
+ end
380
+ matches = case candidates.size
381
+ when 0
382
+ nil
383
+ when 1
384
+ ", did you mean #{candidates.first}?"
385
+ else
386
+ ", close matches are: " +
387
+ candidates[0, candidates.size - 1].join(", ") +
388
+ " and " + candidates.last
389
+ end
390
+ raise ParseError.new("unknown option '#{k}'#{matches || ''}")
391
+ end
392
+
393
+ input
394
+ end
395
+
396
+
397
+ class OptionDefinition #:nodoc: all
398
+ attr_accessor :key
399
+ attr_accessor :option_type
400
+ attr_accessor :argument_type
401
+ attr_accessor :container_type
402
+ attr_accessor :abbreviated
403
+
404
+ def initialize(key)
405
+ @key = key.to_sym
406
+ @option_type = :boolean
407
+ @abbreviated = false
408
+ end
409
+
410
+ def is_abbreviated?
411
+ @abbreviated
412
+ end
413
+ end
414
+
415
+ end
416
+
417
+
418
+ # Spit out usage if --help is specified
419
+ if __FILE__ == $0
420
+ begin
421
+ RDoc::usage if GetOptions.new(%w(help)).help
422
+ rescue
423
+ warn $!
424
+ exit 1
425
+ end
426
+ end
427
+
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Unit test for GetOptions
4
+
5
+ require File.join(File.dirname(__FILE__), '../lib/getoptions')
6
+ require 'spec'
7
+
8
+
9
+ describe GetOptions do
10
+
11
+ # String tests
12
+ it "should parse strings, short type name" do
13
+ opt = GetOptions.new(%w(string=s), %w(--str test))
14
+ opt.string.should eql('test')
15
+ end
16
+ it "should parse strings, long type name" do
17
+ opt = GetOptions.new(%w(string=string), %w(--str test))
18
+ opt.string.should eql('test')
19
+ end
20
+
21
+ # Integer tests
22
+ it "should parse integers, short type name" do
23
+ opt = GetOptions.new(%w(int=i), %w(--int 5))
24
+ opt.int.should eql(5)
25
+ end
26
+ it "should parse integers, long type name" do
27
+ opt = GetOptions.new(%w(int=integer), %w(--int 5))
28
+ opt.int.should eql(5)
29
+ end
30
+ it "should throw an exception on non integers" do
31
+ lambda {
32
+ GetOptions.new(%w(int=i), %w(--int NaN))
33
+ }.should raise_error(GetOptions::ParseError, /expecting integer value/)
34
+ end
35
+
36
+ # Float tests
37
+ it "should parse floats, short type name" do
38
+ opt = GetOptions.new(%w(float=f), %w(--float 0.5))
39
+ opt.float.should eql(0.5)
40
+ end
41
+ it "should parse floats, long type name" do
42
+ opt = GetOptions.new(%w(float=float), %w(--float 0.5))
43
+ opt.float.should eql(0.5)
44
+ end
45
+ it "should throw an exception on non floats" do
46
+ lambda {
47
+ GetOptions.new(%w(float=f), %w(--float NaN))
48
+ }.should raise_error(GetOptions::ParseError, /expecting float value/)
49
+ end
50
+
51
+ # Flag tests
52
+ it "should parse flags set to true" do
53
+ opt = GetOptions.new(%w(flag!), %w(--flag))
54
+ opt.flag.should eql(true)
55
+ end
56
+ it "should parse flags set to false" do
57
+ opt = GetOptions.new(%w(flag!), %w(--no-flag))
58
+ opt.flag.should eql(false)
59
+ end
60
+
61
+ # List tests
62
+ it "should parse a list of strings" do
63
+ opt = GetOptions.new(%w(list=@s), %w(--list foo bar --li baz -l qux))
64
+ opt.list.should eql(%w(foo bar baz qux))
65
+ end
66
+ it "should parse a list of integers" do
67
+ opt = GetOptions.new(%w(list=@i), %w(--list 1 2 --li 3 -l 4))
68
+ opt.list.should eql([1,2,3,4])
69
+ end
70
+ it "should parse a list of integers w/ negative numbers" do
71
+ opt = GetOptions.new(%w(list=@i), %w(--list 1 -2 --li 3 -l -4))
72
+ opt.list.should eql([1,-2,3,-4])
73
+ end
74
+ it "should not parse a list of non-integers" do
75
+ lambda {
76
+ GetOptions.new(%w(list=@i), %w(--list 1 2 oops 3))
77
+ }.should raise_error(GetOptions::ParseError, /expecting integer value/)
78
+ end
79
+ it "should parse a list of floats" do
80
+ opt = GetOptions.new(%w(list=@f), %w(--list 0.1 0.2 --li 0.3 -l 0.4))
81
+ opt.list.should eql([0.1,0.2,0.3,0.4])
82
+ end
83
+ it "should parse a list of floats w/ negative numbers" do
84
+ opt = GetOptions.new(%w(list=@f), %w(--list 0.1 -0.2 --li -0.3 -l 0.4))
85
+ opt.list.should eql([0.1,-0.2,-0.3,0.4])
86
+ end
87
+ it "should not parse a list of non-floats" do
88
+ lambda {
89
+ GetOptions.new(%w(list=@f), %w(--list 0.1 0.2 oops 0.3))
90
+ }.should raise_error(GetOptions::ParseError, /expecting float value/)
91
+ end
92
+
93
+ # Optional argument tests
94
+ it "should parse an optional string argument" do
95
+ opt = GetOptions.new(%w(string:s), %w(--str))
96
+ opt.string.should eql(nil)
97
+ end
98
+ it "should parse an optional integer argument" do
99
+ opt = GetOptions.new(%w(int:i), %w(--int))
100
+ opt.int.should eql(nil)
101
+ end
102
+ it "should parse an optional float argument" do
103
+ opt = GetOptions.new(%w(float:f), %w(--float))
104
+ opt.float.should eql(nil)
105
+ end
106
+ it "should parse an optional list argument" do
107
+ opt = GetOptions.new(%w(list:@s), %w(--list))
108
+ opt.list.should eql([])
109
+ end
110
+
111
+ # has_option test
112
+ it "should check option presence" do
113
+ opt = GetOptions.new(%w(string:s), %w(--string))
114
+ opt.has_option?(:string).should eql(true)
115
+ end
116
+ it "should fail on invalid option presence" do
117
+ opt = GetOptions.new(%w(string:s), %w(--string))
118
+ opt.has_option?(:blah).should_not eql(true)
119
+ end
120
+ it "should fail on `nil' key option check" do
121
+ lambda {
122
+ opt = GetOptions.new(%w(string:s), %w(--string))
123
+ opt.has_option?(nil).should_not eql(true)
124
+ }.should raise_error(GetOptions::ParseError, /`nil' cannot be an option key/)
125
+ end
126
+
127
+ # input array tests
128
+ it "should retain non-options in input list (no option)" do
129
+ input = %w(--flag x1 x2 x3)
130
+ opt = GetOptions.new(%w(flag), input)
131
+ input.should eql(%w(x1 x2 x3))
132
+ end
133
+ it "should retain non-options in input list (required option)" do
134
+ input = %w(--string test x1 x2 x3)
135
+ opt = GetOptions.new(%w(string=s), input)
136
+ input.should eql(%w(x1 x2 x3))
137
+ end
138
+ it "should retain non-options in input list (optional option)" do
139
+ input = %w(--string x1 x2 x3)
140
+ opt = GetOptions.new(%w(string:s), input)
141
+ input.should eql(%w(x2 x3))
142
+ end
143
+ it "should stop options parsing on --" do
144
+ input = %w(--list x1 x2 x3 -- x4 x5 x6)
145
+ opt = GetOptions.new(%w(list=@s), input)
146
+ input.should eql(%w(x4 x5 x6))
147
+ end
148
+
149
+ # Accessor tests
150
+ it "should be accessed as a hash (string key)" do
151
+ opt = GetOptions.new(%w(flag!), %w(--flag))
152
+ opt['flag'].should eql(true)
153
+ end
154
+ it "should be accessed as a hash (symbol key)" do
155
+ opt = GetOptions.new(%w(flag!), %w(--flag))
156
+ opt[:flag].should eql(true)
157
+ end
158
+ it "should fail on nil key" do
159
+ lambda {
160
+ opt = GetOptions.new(%w(flag!), %w(--flag))
161
+ opt[nil]
162
+ }.should raise_error(GetOptions::ParseError, /`nil' cannot be an option key/)
163
+ end
164
+ it "should fail on unknown key (string key)" do
165
+ lambda {
166
+ opt = GetOptions.new(%w(flag!), %w(--flag))
167
+ opt['notanoption']
168
+ }.should raise_error(GetOptions::ParseError, /program tried to access/)
169
+ end
170
+ it "should fail on unknown key (symbol key)" do
171
+ lambda {
172
+ opt = GetOptions.new(%w(flag!), %w(--flag))
173
+ opt[:notanoption]
174
+ }.should raise_error(GetOptions::ParseError, /program tried to access/)
175
+ end
176
+
177
+ # shorthand tests
178
+ it "shorthand test, multiple flags" do
179
+ opt = GetOptions.new(%w(aflag bflag cflag), %w(-ac))
180
+ opt.aflag.should eql(true)
181
+ opt.bflag.should eql(nil)
182
+ opt.cflag.should eql(true)
183
+ end
184
+ it "shorthand test, multiple arguments" do
185
+ opt = GetOptions.new(%w(astr=s bstr=s cstr=s), %w(-abc x1 x2 x3))
186
+ opt.astr.should eql('x1')
187
+ opt.bstr.should eql('x2')
188
+ opt.cstr.should eql('x3')
189
+ end
190
+ it "shorthand test, list interoperability" do
191
+ opt = GetOptions.new(%w(aflag bflag cflag list=@s), %w(--list foo -bar -ac))
192
+ opt.aflag.should eql(true)
193
+ opt.bflag.should eql(nil)
194
+ opt.cflag.should eql(true)
195
+ opt.list.should eql(%w(foo -bar))
196
+ end
197
+ it "shorthand test, list interoperability with invalid option" do
198
+ lambda {
199
+ GetOptions.new(%w(aflag bflag cflag list=@s), %w(--list foo -bar -ac -q))
200
+ }.should raise_error(GetOptions::ParseError, "unknown option 'q'")
201
+ end
202
+
203
+ # last option tests
204
+ it "last option wins (boolean), true at the end" do
205
+ opt = GetOptions.new(%w(flag!), %w(--flag --no-flag -f))
206
+ opt.flag.should eql(true)
207
+ end
208
+ it "last option wins (boolean), false at the end" do
209
+ opt = GetOptions.new(%w(flag!), %w(--flag --no-flag))
210
+ opt.flag.should eql(false)
211
+ end
212
+ it "last option wins (float)" do
213
+ opt = GetOptions.new(%w(float=f), %w(--float 0.1 -f 0.2))
214
+ opt.float.should eql(0.2)
215
+ end
216
+ it "last option wins (int)" do
217
+ opt = GetOptions.new(%w(int=i), %w(--int 1 -i 2))
218
+ opt.int.should eql(2)
219
+ end
220
+ it "last option wins (string)" do
221
+ opt = GetOptions.new(%w(string=s), %w(-s x1 --string x2))
222
+ opt.string.should eql('x2')
223
+ end
224
+
225
+ # misc make it break tests
226
+ it "should throw an exception on invalid types" do
227
+ lambda {
228
+ GetOptions.new(%w(arg=bogus), %w(--arg val))
229
+ }.should raise_error(GetOptions::ParseError, /unknown argument type/)
230
+ end
231
+ it "should throw an exception when supplying an option that doesn't exist" do
232
+ lambda {
233
+ GetOptions.new(%w(string=s), %w(--notanoption))
234
+ }.should raise_error(GetOptions::ParseError, /unknown option/)
235
+ end
236
+ it "should throw an exception when fetching an option that doesn't exist" do
237
+ lambda {
238
+ opt = GetOptions.new(%w(string=s), %w(--string test))
239
+ opt.notanoption
240
+ }.should raise_error(GetOptions::ParseError, /program tried to access an unknown/)
241
+ end
242
+
243
+ # inspect test
244
+ it "inspect method should return proper results" do
245
+ opt = GetOptions.new(%w(flag string=s int:i verbose+ list=@s),
246
+ %w(--int 5 -vvv --list 1 2 3 --flag --string test))
247
+ opt.to_s
248
+ end
249
+
250
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: getoptions
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2007-11-30 00:00:00 -08:00
8
+ summary: Yet another command line option parser in Ruby, based on Perl's Getopt::Long module.
9
+ require_paths:
10
+ - lib
11
+ email: dparker @nospam@ liveops.com
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Delaney Parker
31
+ files:
32
+ - lib/getoptions.rb
33
+ - test/standard.rb
34
+ - README
35
+ test_files:
36
+ - test/standard.rb
37
+ rdoc_options: []
38
+
39
+ extra_rdoc_files:
40
+ - README
41
+ executables: []
42
+
43
+ extensions: []
44
+
45
+ requirements: []
46
+
47
+ dependencies: []
48
+