opt-simple 0.7.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -38,13 +38,12 @@ It is recommended to install OptSimple using RubyGems:
38
38
  == Examples
39
39
 
40
40
  === One example that shows a lot of the behavior you might use
41
+ require 'opt_simple'
41
42
 
42
- require 'opt_simple'
43
-
44
43
  min = 5
45
44
  max = 15
46
45
 
47
- options,arguments = OptSimple.new.parse_opts! do
46
+ options = OptSimple.new.parse_opts! do
48
47
  argument %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
49
48
  accumulate_opt arg
50
49
  end
@@ -54,7 +53,7 @@ It is recommended to install OptSimple using RubyGems:
54
53
  option %w[-n -num --num-values],"Number of val","VAL" do |arg|
55
54
  set_opt arg.to_i
56
55
  end
57
-
56
+
58
57
  option "--range", "range: min,max (both >0) default is #{min},#{max}" do | arg1,arg2 |
59
58
  min = arg1.to_i
60
59
  max = arg2.to_i
@@ -70,20 +69,13 @@ It is recommended to install OptSimple using RubyGems:
70
69
  end
71
70
 
72
71
  puts "Options"
73
- puts options.inspect
74
-
75
- puts "Arguments"
76
- puts arguments.inspect
77
-
78
- puts "ARGV"
79
- puts ARGV
80
-
81
- It prints out an automatic usage statement:
82
-
83
- Usage: opt_ex.rb [options]
72
+ puts options
84
73
 
74
+ Which prints out an automatic usage statement:
75
+ Usage: opt_ex.rb [options]
76
+
85
77
  MANDATORY ARGS:
86
- -i, --infile FILE Infile, multiple allowed
78
+ -i, --infile FILE Infile, multiple allowed
87
79
 
88
80
  OPTIONS:
89
81
  -p, --pattern, --glob-pattern PATTERN glob pattern
@@ -105,23 +97,16 @@ It prints out an automatic usage statement:
105
97
  'max' => 40
106
98
  }
107
99
 
108
- options,arguments = OptSimple.new(defaults).parse_opts!
100
+ options = OptSimple.new(defaults).parse_opts!
109
101
 
110
102
  puts "Options"
111
- puts options.inspect
112
-
113
- puts "Arguments"
114
- puts arguments.inspect
115
-
116
- puts "ARGV"
117
- puts ARGV
118
-
103
+ puts options
119
104
 
120
105
  === An example that provides error checking on ARGV, using all default behavior and how to specify a 'metavar'
121
106
 
122
107
  require 'opt_simple'
123
108
 
124
- options,arguments = OptSimple.new.parse_opts! do
109
+ options = OptSimple.new.parse_opts! do
125
110
  argument "-i","inFile","FILE"
126
111
  option %w[-p --pattern --glob-pattern], "glob pattern","PATTERN"
127
112
  flag "-v","Verbose"
@@ -129,14 +114,7 @@ It prints out an automatic usage statement:
129
114
  end
130
115
 
131
116
  puts "Options"
132
- puts options.inspect
133
-
134
- puts "Arguments"
135
- puts arguments.inspect
136
-
137
- puts "ARGV"
138
- puts ARGV
139
-
117
+ puts options
140
118
 
141
119
  === An example that shows how to use 'set_opt', set the banner string, and add a summary.
142
120
 
@@ -146,7 +124,7 @@ It prints out an automatic usage statement:
146
124
  "max" => 10
147
125
  }
148
126
 
149
- options,arguments = OptSimple.new(defaults).parse_opts! do
127
+ options = OptSimple.new(defaults).parse_opts! do
150
128
  banner "USAGE: #{$0}"
151
129
  summary "Show how to set a banner and summary."
152
130
 
@@ -157,13 +135,7 @@ It prints out an automatic usage statement:
157
135
  end
158
136
 
159
137
  puts "Options"
160
- puts options.inspect
161
-
162
- puts "Arguments"
163
- puts arguments.inspect
164
-
165
- puts "ARGV"
166
- puts ARGV
138
+ puts options
167
139
 
168
140
  === An example that shows how to use 'accumulate_opt' on an option to create a list, and on a flag to increment a counter
169
141
 
@@ -171,7 +143,7 @@ It prints out an automatic usage statement:
171
143
 
172
144
  verbosity = 0
173
145
 
174
- options,arguments = OptSimple.new.parse_opts! do
146
+ options = OptSimple.new.parse_opts! do
175
147
  option %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
176
148
  accumulate_opt arg
177
149
  end
@@ -186,17 +158,7 @@ It prints out an automatic usage statement:
186
158
  end
187
159
 
188
160
  puts "Options"
189
- puts options.inspect
190
-
191
- puts "Arguments"
192
- puts arguments.inspect
193
-
194
- puts "Verbosity"
195
- puts verbosity
196
-
197
- puts "ARGV"
198
- puts ARGV
199
-
161
+ puts options
200
162
 
201
163
  === An example that shows that you can easily set your defaults in normal Ruby variables and provide your own help.
202
164
 
@@ -284,17 +246,10 @@ It prints out an automatic usage statement:
284
246
  end
285
247
  end
286
248
 
287
- options,arguments = os.parse_opts!
249
+ options = os.parse_opts!
288
250
 
289
251
  puts "Options"
290
- puts options.inspect
291
-
292
- puts "Arguments"
293
- puts arguments.inspect
294
-
295
- puts "ARGV"
296
- puts ARGV
297
-
252
+ puts options
298
253
 
299
254
  == Questions and/or Comments
300
255
 
data/lib/opt_simple.rb CHANGED
@@ -33,9 +33,10 @@ class OptSimple
33
33
  @optional_opts = []
34
34
  @parameters = []
35
35
  @param_names = {}
36
+ @results = OptSimple::Result.new
36
37
  @longest_switch_len = 0
37
- @options = defaults.dup # not sure if I have to dup this
38
- @positional_arguments = []
38
+ @defaults = defaults
39
+ @positional_args = []
39
40
  @args = args
40
41
  @banner = "Usage: #{File.basename($0)} [options]"
41
42
  @summary = ""
@@ -60,20 +61,10 @@ class OptSimple
60
61
  # Simply register options without actually parsing them.
61
62
  # This allows registering parms in multiple places in your code.
62
63
  def register_opts(&block)
63
- begin
64
- # call the block to register all the parameters and
65
- # their corresponding code blocks
66
- # We use instance_exec so that the API is cleaner.
67
- instance_exec(@options,@positional_arguments,&block)
68
- ensure
69
- # we are ensuring that the options that occur before any break statement
70
- # actually get parsed.
71
-
72
- # add the help option at the end the first time register_opts is called
73
- unless(@parameters.find {|p| p.switches.include?('-h')})
74
- flag %w[-h --help] ,"(for this help message)"
75
- end
76
- end
64
+ # call the block to register all the parameters and
65
+ # their corresponding code blocks
66
+ # We use instance_exec so that the API is cleaner.
67
+ instance_exec(@results,&block)
77
68
  end
78
69
 
79
70
  # Parse the options, destructively pulling them out of the args array as it goes.
@@ -83,6 +74,14 @@ class OptSimple
83
74
  if block_given?
84
75
  register_opts(&block)
85
76
  end
77
+
78
+ # add the help option at the end, but only use -h if it hasn't been used
79
+ # already (cuz we're that nice).
80
+ help_strings = %w[-h --help]
81
+ if(@parameters.find {|p| p.switches.include?('-h')})
82
+ help_strings = %w[--help]
83
+ end
84
+ flag help_strings ,"(for this help message)"
86
85
 
87
86
  if @parameters.empty?
88
87
  #parse the @args array by looking for switches/args by regex
@@ -92,7 +91,7 @@ class OptSimple
92
91
  # the specified parms from @arg
93
92
 
94
93
  # first look for a call for help
95
- unless (%w[-h --help] & @args).empty?
94
+ unless (help_strings & @args).empty?
96
95
  $stdout.puts self.to_s
97
96
  exit(0)
98
97
  end
@@ -101,7 +100,7 @@ class OptSimple
101
100
 
102
101
  if(loc = @args.index('--'))
103
102
  #remove the '--', but don't include it w/ positional arguments
104
- @positional_arguments += @args.slice!(loc..-1)[1..-1]
103
+ @positional_args += @args.slice!(loc..-1)[1..-1]
105
104
  end
106
105
 
107
106
  # Handle the case where a user specifies --foo=bar, or --foo=bar,baz
@@ -118,7 +117,16 @@ class OptSimple
118
117
  intersection = @args & parm.switches
119
118
  unless intersection.empty?
120
119
  mandatory_check.delete(parm.switches)
120
+ parm.param_options.add_alias(parm.names)
121
121
 
122
+ default_switches = @defaults.keys & parm.names
123
+ if default_switches.length > 1
124
+ raise OptSimple::Error "Clashes in the defaults for #{parm.switches}"
125
+ elsif default_switches.length == 1
126
+ # set the default value before we see what is on the CL
127
+ parm.param_options[default_switches.first] = @defaults[default_switches.first]
128
+ end
129
+
122
130
  arg_locations = []
123
131
  @args.each_with_index {|arg,i| arg_locations << i if intersection.include?(arg) }
124
132
 
@@ -145,7 +153,7 @@ class OptSimple
145
153
  end
146
154
  end
147
155
 
148
- @options.merge!(parm.param_options)
156
+ @results.merge! parm.param_options
149
157
  end
150
158
  end
151
159
 
@@ -156,10 +164,11 @@ class OptSimple
156
164
  extra_switches = @args.find_all {|a| a.start_with?('-') }
157
165
  raise OptSimple::InvalidOption.new "Unknown options: #{extra_switches.join(' ')}",self unless extra_switches.empty?
158
166
 
159
- @positional_arguments += @args.slice!(0..-1)
167
+ @positional_args += @args.slice!(0..-1)
160
168
  end
161
-
162
- return [@options,@positional_arguments]
169
+
170
+ @results.positional_args = @positional_args
171
+ return @results
163
172
  end
164
173
 
165
174
  # Parse the options in a non-destructive way to the args array passed in.
@@ -178,18 +187,18 @@ class OptSimple
178
187
  @args.each_with_index do |arg,loc|
179
188
  if arg == '--'
180
189
  # end of flag marker
181
- @positional_args += @args[i+1 .. -1]
190
+ @results.positional_args += @args[i+1 .. -1]
182
191
  break
183
192
  elsif arg =~ /^-+(.*)/
184
193
  # assume flags are boolean
185
- @options[$1] = true
194
+ @results[$1] = true
186
195
  flag = $1
187
196
  elsif flag
188
197
  # unless followed by an arg
189
- @options[flag] = arg
198
+ @results[flag] = arg
190
199
  flag = nil
191
200
  else
192
- @positional_args << arg
201
+ @results.positional_args << arg
193
202
  end
194
203
  end
195
204
  @args.slice!(0..-1)
@@ -244,20 +253,19 @@ class OptSimple
244
253
 
245
254
  help_str << " MANDATORY ARGS:\n" unless mandatory_opts.empty?
246
255
  mandatory_opts.each do | parm |
247
- help_str << parm.help_str(@longest_switch_len) << "\n"
256
+ help_str << parm.help_str(@longest_switch_len) << "\n\n"
248
257
  end
249
- help_str << "\n" unless mandatory_opts.empty?
250
258
 
251
259
  help_str << " OPTIONS:\n" unless optional_opts.empty?
252
260
  optional_opts.each do | parm |
253
261
  help_str << parm.help_str(@longest_switch_len)
254
262
 
255
263
  # check to see if we have any defaults set to help in the help doc
256
- intersection = @options.keys & parm.names
264
+ intersection = @defaults.keys & parm.names
257
265
  if intersection.empty?
258
266
  help_str << "\n\n"
259
267
  else
260
- help_str << " (default is #{@options[intersection.first]})\n\n"
268
+ help_str << " (default is #{@defaults[intersection.first]})\n\n"
261
269
  end
262
270
  end
263
271
  help_str << " SUMMARY:\n\n #{@summary}\n\n" unless @summary.empty?
@@ -299,8 +307,9 @@ class OptSimple
299
307
  self.switches = switches
300
308
  @help = help
301
309
  @block = block
302
- @param_options = {}
310
+ @param_options = OptSimple::Result.new
303
311
  @names = nil
312
+ @param_options.add_alias(self.names)
304
313
  end
305
314
 
306
315
  # ensures that the switches is an array. Should be an array of Strings
@@ -340,9 +349,10 @@ class OptSimple
340
349
  end
341
350
 
342
351
  # A utility function that sets all the names to the specified value
343
- # in the param_options hash.
352
+ # in the param_options data structure.
344
353
  def set_opt val
345
- names.each {|n| @param_options[n] = val}
354
+ # all the other values are aliased, so we only need to set the first
355
+ @param_options[names.first] = val
346
356
  end
347
357
 
348
358
  # is it mandatory to see this parameter on the command line?
@@ -363,15 +373,15 @@ class OptSimple
363
373
  def initialize(switches,help="",&block)
364
374
  super(switches,help,&block)
365
375
  if block_given?
366
- names.each {|n| @param_options[n] = 0 }
376
+ @param_options[names.first] = 0
367
377
  else
368
- @block = Proc.new { names.each {|n| @param_options[n] = true}}
378
+ @block = Proc.new { @param_options[names.first] = true}
369
379
  end
370
380
  end
371
-
381
+
372
382
  # increment the parameter by one every time it is seen on the CL
373
383
  def accumulate_opt
374
- names.each {|n| @param_options[n] += 1}
384
+ @param_options[names.first] += 1
375
385
  end
376
386
 
377
387
  end
@@ -390,9 +400,9 @@ class OptSimple
390
400
  super(switches,help,&block)
391
401
  @metavar = metavar
392
402
  if block_given?
393
- names.each {|n| @param_options[n] = []}
403
+ @param_options[names.first] = []
394
404
  else
395
- @block = Proc.new {|arg| names.each {|n| @param_options[n] = arg}}
405
+ @block = Proc.new {|arg| @param_options[names.first] = arg}
396
406
  end
397
407
  end
398
408
 
@@ -407,7 +417,7 @@ class OptSimple
407
417
 
408
418
  # append val to the parameter list
409
419
  def accumulate_opt(val)
410
- names.each {|n| @param_options[n] << val}
420
+ @param_options[names.first] << val
411
421
  end
412
422
 
413
423
  end
@@ -444,5 +454,89 @@ class OptSimple
444
454
  # on the command line
445
455
  class ParameterUsageError < Error;end
446
456
 
457
+ # The results after parsing the CL in a hash-like object with method
458
+ # syntax for getters/setters as well. Each result that belong to the same
459
+ # Parameter are aliased to keep consistent
460
+ class Result
461
+ attr_accessor :positional_args
462
+
463
+ def initialize
464
+ @name_to_aliases = {}
465
+ @inside_hash = {}
466
+ @positional_args = []
467
+ end
468
+
469
+ # hash notation setter
470
+ def []=(key,value)
471
+ if @name_to_aliases.has_key?(key)
472
+ @inside_hash[@name_to_aliases[key]] = value
473
+ else
474
+ add_alias(key)
475
+ @inside_hash[[key].flatten] = value
476
+ end
477
+ end
478
+
479
+ # hash notation getter
480
+ def [](key)
481
+ @inside_hash[@name_to_aliases[key]]
482
+ end
483
+
484
+ # add a list of items that should be treated as the same key
485
+ def add_alias(list)
486
+ alias_list = [list].flatten
487
+ alias_list.each do | item |
488
+ @name_to_aliases[item] = alias_list
489
+ @name_to_aliases[item.to_s] = alias_list
490
+ @name_to_aliases[item.to_sym] = alias_list
491
+ end
492
+ end
493
+
494
+ # copy the values from hash into this Result object
495
+ def add_vals_from_hash(hash)
496
+ hash.keys.each { |k| self[k] = hash[k] }
497
+ end
498
+
499
+ # merge non-destructively, and return the result
500
+ def merge(other)
501
+ r = Result.new
502
+ r.merge! self
503
+ r.merge! other
504
+ end
505
+
506
+ # merge into this Result and return the result
507
+ def merge!(other)
508
+ other.aliases.each do | a |
509
+ add_alias(a)
510
+ self[a.first] = other[a.first]
511
+ end
512
+ end
513
+
514
+ # a list of all the aliases
515
+ def aliases
516
+ @name_to_aliases.values.uniq
517
+ end
518
+
519
+ # this allows for method calls for getters/setters
520
+ def method_missing(sym,*args,&block)
521
+ sym_str = sym.to_s
522
+ if @name_to_aliases.has_key?(sym)
523
+ return @inside_hash[@name_to_aliases[sym]]
524
+ elsif sym_str.end_with?('=') and
525
+ @name_to_aliases.has_key?(sym_str[0..-2])
526
+ @inside_hash[@name_to_aliases[sym_str[0..-2]]] = args.first
527
+ else
528
+ super(sym,*args,&block)
529
+ end
530
+ end
531
+
532
+ # a hash looking return string.
533
+ def to_s
534
+ ret = ""
535
+ aliases.each do | a |
536
+ ret << "#{a}=>#{@inside_hash[a]},"
537
+ end
538
+ return "{#{ret[0..-2]}}\n#{@positional_args.inspect}\n"
539
+ end
540
+ end
447
541
  end
448
542
 
data/test/test_arglist.rb CHANGED
@@ -13,13 +13,13 @@ class ArglistTest < Test::Unit::TestCase
13
13
  end
14
14
 
15
15
  must "put all args after the dash dash in the pos argument list" do
16
- options,arguments = @os.parse_opts &@block
17
- assert arguments.include? '-infile4' and arguments.include? 'infile5'
16
+ options = @os.parse_opts &@block
17
+ assert options.positional_args.include? '-infile4' and options.positional_args.include? 'infile5'
18
18
  end
19
19
 
20
20
  must "return all positional args in the arguments list" do
21
- options,arguments = @os.parse_opts &@block
22
- assert_equal arguments.sort,%w[infile1 infile2 infile3 -infile4 infile5].sort
21
+ options = @os.parse_opts &@block
22
+ assert_equal options.positional_args.sort,%w[infile1 infile2 infile3 -infile4 infile5].sort
23
23
  end
24
24
 
25
25
  must "empty out ARGV when using parse_opts!" do
@@ -0,0 +1,45 @@
1
+ require 'opt_simple'
2
+ require 'test/unit'
3
+ require 'test_unit_extensions'
4
+
5
+ #test the OptSimple::Result class
6
+ class TestReturn < Test::Unit::TestCase
7
+ def setup
8
+ @r = OptSimple::Result.new
9
+ @r.add_alias %w[a all]
10
+ end
11
+
12
+ must "change all variables that are aliased" do
13
+ @r['a'] = 3
14
+ assert_equal @r['all'],3
15
+ end
16
+
17
+ must "set string, symbol in hash notation and respond to method invocation" do
18
+ @r['a'] = 3
19
+ assert_equal @r.a, 3
20
+ assert_equal @r[:a], 3
21
+ assert_equal @r['a'], 3
22
+ assert_equal @r.all, 3
23
+ assert_equal @r['all'], 3
24
+ assert_equal @r[:all],3
25
+ end
26
+
27
+ must "merge with other result objects" do
28
+ r2 = OptSimple::Result.new
29
+ r2.add_alias %w[b ball]
30
+ r2.b = 4
31
+ @r.a = 7
32
+ r2.merge!(@r)
33
+ assert_equal r2.a,7
34
+ assert_equal r2.all,7
35
+ end
36
+
37
+ must "merge with hashes" do
38
+ h = {:a=>1,:z=>26}
39
+ @r.add_vals_from_hash(h)
40
+
41
+ assert_equal @r.a,1
42
+ assert_equal @r.z,26
43
+ end
44
+
45
+ end
data/test/test_usage.rb CHANGED
@@ -37,7 +37,7 @@ class TestHelpStatement < Test::Unit::TestCase
37
37
  os = OptSimple.new({},['-a=2','--foo=4,5'])
38
38
  x = nil
39
39
  y = nil
40
- opts, args = os.parse_opts! do
40
+ opts= os.parse_opts! do
41
41
  option '-a' do |arg|
42
42
  set_opt arg.to_i
43
43
  end
@@ -54,7 +54,7 @@ class TestHelpStatement < Test::Unit::TestCase
54
54
 
55
55
  must "accumulate lists of args when asked" do
56
56
  os = OptSimple.new({},%w[-i foo.bar --infile bar.in])
57
- o,a = os.parse_opts! do
57
+ o = os.parse_opts! do
58
58
  option %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
59
59
  accumulate_opt arg
60
60
  end
@@ -66,7 +66,7 @@ class TestHelpStatement < Test::Unit::TestCase
66
66
 
67
67
  must "accumulate numbers of flags set when asked" do
68
68
  os = OptSimple.new({},%w[-v -v --verbose -v])
69
- o,a = os.parse_opts! do
69
+ o = os.parse_opts! do
70
70
  flag %w[-v --verbose],"Verbosity. the more you set, the more we give" do
71
71
  accumulate_opt
72
72
  end
@@ -77,7 +77,7 @@ class TestHelpStatement < Test::Unit::TestCase
77
77
 
78
78
  must "set last arg when duplicated when accumulate opt isn't used" do
79
79
  os = OptSimple.new({},%w[-i foo.bar --infile bar.in -i baz])
80
- o,a = os.parse_opts! do
80
+ o = os.parse_opts! do
81
81
  option %w[-i --infile], "Infile, multiple allowed", "FILE" do | arg |
82
82
  set_opt arg
83
83
  end
@@ -100,7 +100,7 @@ class TestHelpStatement < Test::Unit::TestCase
100
100
  set_opt arg
101
101
  end
102
102
  end
103
- o,a = os.parse_opts!
103
+ o = os.parse_opts!
104
104
 
105
105
  assert_equal o['i'],'foo.bar'
106
106
  assert_equal o['o'],'bar.out'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opt-simple
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan Stryker
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2011-03-13 00:00:00 +00:00
12
+ date: 2011-03-15 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -27,6 +27,7 @@ files:
27
27
  - test/test_help.rb
28
28
  - test/test_usage.rb
29
29
  - test/test_arglist.rb
30
+ - test/test_return.rb
30
31
  - extensions/test_unit_extensions.rb
31
32
  - README
32
33
  - GPLv2-LICENSE