opt-simple 0.7.5 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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