rubysl-optparse 1.0.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa8ff0156078cefb2380c403370d14f7bd196d3e
4
- data.tar.gz: b6cb3da1024139ee990669aaa7e6faa49aebdfe5
3
+ metadata.gz: 1cfe59bacd74fb653c8967f2dccf22144da8a746
4
+ data.tar.gz: 594662245f2a9727976e49dac263d3081f856301
5
5
  SHA512:
6
- metadata.gz: f640fd3b164fe023b368536d7d10d841273454efd8f90f48b890d7937a8b345d3b55e2e8760df5d6339815ab4e96023b05b680eee6ea9567ba568b3194f8a800
7
- data.tar.gz: 15fa125bab26ad3284a73bfec0a3a6e3cb25366aa0abd8e537c9290301fab0d1a609fd698f18cbb9bfe647f296a4af6e3e0ee8c966b0b4e5600d0a27634d242a
6
+ metadata.gz: 684c6f7b6442080de3577f81bb0630630cc8b49ee65a3791f8ad32688de539f29b9e01cb81c39115fe0839c427971ae07c5898962a370f731f27263acadf94bd
7
+ data.tar.gz: 9a113544d4f18ce4a2335342f00622b8ccf845f989e01a3c0e2ce0d16ea036da3bd482d4bf70da77920891153567ca00a39464369ce6d4ccd0ec79ef212f7774
@@ -1,8 +1,6 @@
1
1
  language: ruby
2
- before_install:
3
- - gem update --system
4
- - gem --version
5
- - gem install rubysl-bundler
2
+ env:
3
+ - RUBYLIB=lib
6
4
  script: bundle exec mspec spec
7
5
  rvm:
8
- - rbx-nightly-18mode
6
+ - rbx-nightly-19mode
@@ -0,0 +1,50 @@
1
+ require 'optparse'
2
+
3
+ class OptionParser::AC < OptionParser
4
+ private
5
+
6
+ def _check_ac_args(name, block)
7
+ unless /\A\w[-\w]*\z/ =~ name
8
+ raise ArgumentError, name
9
+ end
10
+ unless block
11
+ raise ArgumentError, "no block given", ParseError.filter_backtrace(caller)
12
+ end
13
+ end
14
+
15
+ def _ac_arg_enable(prefix, name, help_string, block)
16
+ _check_ac_args(name, block)
17
+
18
+ sdesc = []
19
+ ldesc = ["--#{prefix}-#{name}"]
20
+ desc = [help_string]
21
+ q = name.downcase
22
+ enable = Switch::NoArgument.new(nil, proc {true}, sdesc, ldesc, nil, desc, block)
23
+ disable = Switch::NoArgument.new(nil, proc {false}, sdesc, ldesc, nil, desc, block)
24
+ top.append(enable, [], ["enable-" + q], disable, ['disable-' + q])
25
+ enable
26
+ end
27
+
28
+ public
29
+
30
+ def ac_arg_enable(name, help_string, &block)
31
+ _ac_arg_enable("enable", name, help_string, block)
32
+ end
33
+
34
+ def ac_arg_disable(name, help_string, &block)
35
+ _ac_arg_enable("disable", name, help_string, block)
36
+ end
37
+
38
+ def ac_arg_with(name, help_string, &block)
39
+ _check_ac_args(name, block)
40
+
41
+ sdesc = []
42
+ ldesc = ["--with-#{name}"]
43
+ desc = [help_string]
44
+ q = name.downcase
45
+ with = Switch::PlacedArgument.new(*search(:atype, String), sdesc, ldesc, nil, desc, block)
46
+ without = Switch::NoArgument.new(nil, proc {}, sdesc, ldesc, nil, desc, block)
47
+ top.append(with, [], ["with-" + q], without, ['without-' + q])
48
+ with
49
+ end
50
+ end
@@ -1,7 +1,7 @@
1
1
  # OptionParser internal utility
2
2
 
3
3
  class << OptionParser
4
- def show_version(*pkg)
4
+ def show_version(*pkgs)
5
5
  progname = ARGV.options.program_name
6
6
  result = false
7
7
  show = proc do |klass, cname, version|
@@ -19,14 +19,14 @@ class << OptionParser
19
19
  puts str
20
20
  result = true
21
21
  end
22
- if pkg.size == 1 and pkg[0] == "all"
22
+ if pkgs.size == 1 and pkgs[0] == "all"
23
23
  self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version|
24
24
  unless cname[1] == ?e and klass.const_defined?(:Version)
25
25
  show.call(klass, cname.intern, version)
26
26
  end
27
27
  end
28
28
  else
29
- pkg.each do |pkg|
29
+ pkgs.each do |pkg|
30
30
  begin
31
31
  pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)}
32
32
  v = case
@@ -46,8 +46,8 @@ class << OptionParser
46
46
  result
47
47
  end
48
48
 
49
- def each_const(path, klass = ::Object)
50
- path.split(/::|\//).inject(klass) do |klass, name|
49
+ def each_const(path, base = ::Object)
50
+ path.split(/::|\//).inject(base) do |klass, name|
51
51
  raise NameError, path unless Module === klass
52
52
  klass.constants.grep(/#{name}/i) do |c|
53
53
  klass.const_defined?(c) or next
@@ -1,15 +1,16 @@
1
1
  #
2
2
  # optparse.rb - command-line option analysis with the OptionParser class.
3
- #
3
+ #
4
4
  # Author:: Nobu Nakada
5
5
  # Documentation:: Nobu Nakada and Gavin Sinclair.
6
6
  #
7
- # See OptionParser for documentation.
7
+ # See OptionParser for documentation.
8
8
  #
9
9
 
10
10
 
11
- # == Developer Documentation (not for RDoc output)
12
- #
11
+ #--
12
+ # == Developer Documentation (not for RDoc output)
13
+ #
13
14
  # === Class tree
14
15
  #
15
16
  # - OptionParser:: front end
@@ -42,6 +43,8 @@
42
43
  # | all instances)|
43
44
  # +---------------+
44
45
  #
46
+ #++
47
+ #
45
48
  # == OptionParser
46
49
  #
47
50
  # === Introduction
@@ -51,7 +54,7 @@
51
54
  # solution.
52
55
  #
53
56
  # === Features
54
- #
57
+ #
55
58
  # 1. The argument specification and the code to handle it are written in the
56
59
  # same place.
57
60
  # 2. It can output an option summary; you don't need to maintain this string
@@ -60,7 +63,8 @@
60
63
  # 4. Arguments can be automatically converted to a specified class.
61
64
  # 5. Arguments can be restricted to a certain set.
62
65
  #
63
- # All of these features are demonstrated in the examples below.
66
+ # All of these features are demonstrated in the examples below. See
67
+ # #make_switch for full documentation.
64
68
  #
65
69
  # === Minimal example
66
70
  #
@@ -88,12 +92,12 @@
88
92
  # require 'optparse/time'
89
93
  # require 'ostruct'
90
94
  # require 'pp'
91
- #
95
+ #
92
96
  # class OptparseExample
93
- #
97
+ #
94
98
  # CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
95
99
  # CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
96
- #
100
+ #
97
101
  # #
98
102
  # # Return a structure describing the options.
99
103
  # #
@@ -106,19 +110,19 @@
106
110
  # options.encoding = "utf8"
107
111
  # options.transfer_type = :auto
108
112
  # options.verbose = false
109
- #
110
- # opts = OptionParser.new do |opts|
113
+ #
114
+ # opt_parser = OptionParser.new do |opts|
111
115
  # opts.banner = "Usage: example.rb [options]"
112
- #
116
+ #
113
117
  # opts.separator ""
114
118
  # opts.separator "Specific options:"
115
- #
119
+ #
116
120
  # # Mandatory argument.
117
121
  # opts.on("-r", "--require LIBRARY",
118
122
  # "Require the LIBRARY before executing your script") do |lib|
119
123
  # options.library << lib
120
124
  # end
121
- #
125
+ #
122
126
  # # Optional argument; multi-line description.
123
127
  # opts.on("-i", "--inplace [EXTENSION]",
124
128
  # "Edit ARGV files in place",
@@ -127,28 +131,28 @@
127
131
  # options.extension = ext || ''
128
132
  # options.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot.
129
133
  # end
130
- #
134
+ #
131
135
  # # Cast 'delay' argument to a Float.
132
136
  # opts.on("--delay N", Float, "Delay N seconds before executing") do |n|
133
137
  # options.delay = n
134
138
  # end
135
- #
139
+ #
136
140
  # # Cast 'time' argument to a Time object.
137
141
  # opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
138
142
  # options.time = time
139
143
  # end
140
- #
144
+ #
141
145
  # # Cast to octal integer.
142
146
  # opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
143
147
  # "Specify record separator (default \\0)") do |rs|
144
148
  # options.record_separator = rs
145
149
  # end
146
- #
150
+ #
147
151
  # # List of arguments.
148
152
  # opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
149
153
  # options.list = list
150
154
  # end
151
- #
155
+ #
152
156
  # # Keyword completion. We are specifying a specific set of arguments (CODES
153
157
  # # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
154
158
  # # the shortest unambiguous text.
@@ -157,53 +161,58 @@
157
161
  # " (#{code_list})") do |encoding|
158
162
  # options.encoding = encoding
159
163
  # end
160
- #
164
+ #
161
165
  # # Optional argument with keyword completion.
162
166
  # opts.on("--type [TYPE]", [:text, :binary, :auto],
163
167
  # "Select transfer type (text, binary, auto)") do |t|
164
168
  # options.transfer_type = t
165
169
  # end
166
- #
170
+ #
167
171
  # # Boolean switch.
168
172
  # opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
169
173
  # options.verbose = v
170
174
  # end
171
- #
175
+ #
172
176
  # opts.separator ""
173
177
  # opts.separator "Common options:"
174
- #
178
+ #
175
179
  # # No argument, shows at tail. This will print an options summary.
176
180
  # # Try it and see!
177
181
  # opts.on_tail("-h", "--help", "Show this message") do
178
182
  # puts opts
179
183
  # exit
180
184
  # end
181
- #
185
+ #
182
186
  # # Another typical switch to print the version.
183
187
  # opts.on_tail("--version", "Show version") do
184
188
  # puts OptionParser::Version.join('.')
185
189
  # exit
186
190
  # end
187
191
  # end
188
- #
189
- # opts.parse!(args)
192
+ #
193
+ # opt_parser.parse!(args)
190
194
  # options
191
195
  # end # parse()
192
- #
196
+ #
193
197
  # end # class OptparseExample
194
- #
198
+ #
195
199
  # options = OptparseExample.parse(ARGV)
196
200
  # pp options
201
+ # pp ARGV
202
+ #
203
+ # === Shell Completion
204
+ #
205
+ # For modern shells (e.g. bash, zsh, etc.), you can use shell
206
+ # completion for command line options.
197
207
  #
198
208
  # === Further documentation
199
209
  #
200
210
  # The above examples should be enough to learn how to use this class. If you
201
- # have any questions, email me (gsinclair@soyabean.com.au) and I will update
202
- # this document.
211
+ # have any questions, file a ticket at http://bugs.ruby-lang.org.
203
212
  #
204
213
  class OptionParser
205
214
  # :stopdoc:
206
- RCSID = %w$Id: optparse.rb 22469 2009-02-20 11:43:35Z shyouhei $[1..-1].each {|s| s.freeze}.freeze
215
+ RCSID = %w$Id$[1..-1].each {|s| s.freeze}.freeze
207
216
  Version = (RCSID[1].split('.').collect {|s| s.to_i}.extend(Comparable).freeze if RCSID[1])
208
217
  LastModified = (Time.gm(*RCSID[2, 2].join('-').scan(/\d+/).collect {|s| s.to_i}) if RCSID[2])
209
218
  Release = RCSID[2]
@@ -218,12 +227,14 @@ class OptionParser
218
227
  # and resolved against a list of acceptable values.
219
228
  #
220
229
  module Completion
221
- def complete(key, icase = false, pat = nil)
222
- pat ||= Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'),
223
- icase)
224
- canon, sw, k, v, cn = nil
230
+ def self.regexp(key, icase)
231
+ Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase)
232
+ end
233
+
234
+ def self.candidate(key, icase = false, pat = nil, &block)
235
+ pat ||= Completion.regexp(key, icase)
225
236
  candidates = []
226
- each do |k, *v|
237
+ block.call do |k, *v|
227
238
  (if Regexp === k
228
239
  kn = nil
229
240
  k === key
@@ -234,7 +245,16 @@ class OptionParser
234
245
  v << k if v.empty?
235
246
  candidates << [k, v, kn]
236
247
  end
237
- candidates = candidates.sort_by {|k, v, kn| kn.size}
248
+ candidates
249
+ end
250
+
251
+ def candidate(key, icase = false, pat = nil)
252
+ Completion.candidate(key, icase, pat, &method(:each))
253
+ end
254
+
255
+ public
256
+ def complete(key, icase = false, pat = nil)
257
+ candidates = candidate(key, icase, pat, &method(:each)).sort_by {|k, v, kn| kn.size}
238
258
  if candidates.size == 1
239
259
  canon, sw, * = candidates[0]
240
260
  elsif candidates.size > 1
@@ -276,7 +296,7 @@ class OptionParser
276
296
  # Individual switch class. Not important to the user.
277
297
  #
278
298
  # Defined within Switch are several Switch-derived classes: NoArgument,
279
- # RequiredArgument, etc.
299
+ # RequiredArgument, etc.
280
300
  #
281
301
  class Switch
282
302
  attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
@@ -301,7 +321,8 @@ class OptionParser
301
321
  end
302
322
 
303
323
  def self.incompatible_argument_styles(arg, t)
304
- raise ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}"
324
+ raise(ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}",
325
+ ParseError.filter_backtrace(caller(2)))
305
326
  end
306
327
 
307
328
  def self.pattern
@@ -321,10 +342,10 @@ class OptionParser
321
342
  # argument pattern. Yields when the pattern doesn't match substring.
322
343
  #
323
344
  def parse_arg(arg)
324
- pattern or return nil, arg
345
+ pattern or return nil, [arg]
325
346
  unless m = pattern.match(arg)
326
347
  yield(InvalidArgument, arg)
327
- return arg, nil
348
+ return arg, []
328
349
  end
329
350
  if String === m
330
351
  m = [s = m]
@@ -345,11 +366,11 @@ class OptionParser
345
366
  # conversion. Yields at semi-error condition instead of raising an
346
367
  # exception.
347
368
  #
348
- def conv_arg(arg, val = nil)
369
+ def conv_arg(arg, val = [])
349
370
  if conv
350
371
  val = conv.call(*val)
351
372
  else
352
- val = proc {|val| val}.call(*val)
373
+ val = proc {|v| v}.call(*val)
353
374
  end
354
375
  return arg, block, val
355
376
  end
@@ -368,7 +389,7 @@ class OptionParser
368
389
  # +indent+:: Prefix string indents all summarized lines.
369
390
  #
370
391
  def summarize(sdone = [], ldone = [], width = 1, max = width - 1, indent = "")
371
- sopts, lopts, s = [], [], nil
392
+ sopts, lopts = [], [], nil
372
393
  @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short
373
394
  @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long
374
395
  return if sopts.empty? and lopts.empty? # completely hidden
@@ -383,10 +404,16 @@ class OptionParser
383
404
  left[-1] << if left[-1].empty? then ' ' * 4 else ', ' end << s
384
405
  end
385
406
 
386
- left[0] << arg if arg
387
- mlen = left.collect {|s| s.length}.max.to_i
407
+ if arg
408
+ left[0] << (left[1] ? arg.sub(/\A(\[?)=/, '\1') + ',' : arg)
409
+ end
410
+ mlen = left.collect {|ss| ss.length}.max.to_i
388
411
  while mlen > width and l = left.shift
389
- mlen = left.collect {|s| s.length}.max.to_i if l.length == mlen
412
+ mlen = left.collect {|ss| ss.length}.max.to_i if l.length == mlen
413
+ if l.length < width and (r = right[0]) and !r.empty?
414
+ l = l.to_s.ljust(width) + ' ' + r
415
+ right.shift
416
+ end
390
417
  yield(indent + l)
391
418
  end
392
419
 
@@ -406,7 +433,7 @@ class OptionParser
406
433
  to
407
434
  end
408
435
 
409
- def match_nonswitch?(str) # :nodoc:
436
+ def match_nonswitch?(str) # :nodoc:
410
437
  @pattern =~ str unless @short or @long
411
438
  end
412
439
 
@@ -417,6 +444,24 @@ class OptionParser
417
444
  (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '')
418
445
  end
419
446
 
447
+ def compsys(sdone, ldone) # :nodoc:
448
+ sopts, lopts = [], []
449
+ @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short
450
+ @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long
451
+ return if sopts.empty? and lopts.empty? # completely hidden
452
+
453
+ (sopts+lopts).each do |opt|
454
+ # "(-x -c -r)-l[left justify]" \
455
+ if opt =~ /^--\[no-\](.+)$/
456
+ o = $1
457
+ yield("--#{o}", desc.join(""))
458
+ yield("--no-#{o}", desc.join(""))
459
+ else
460
+ yield("#{opt}", desc.join(""))
461
+ end
462
+ end
463
+ end
464
+
420
465
  #
421
466
  # Switch that takes no arguments.
422
467
  #
@@ -451,7 +496,7 @@ class OptionParser
451
496
  raise MissingArgument if argv.empty?
452
497
  arg = argv.shift
453
498
  end
454
- conv_arg(*parse_arg(arg) {|*exc| raise(*exc)})
499
+ conv_arg(*parse_arg(arg, &method(:raise)))
455
500
  end
456
501
  end
457
502
 
@@ -504,13 +549,13 @@ class OptionParser
504
549
  class List
505
550
  # Map from acceptable argument types to pattern and converter pairs.
506
551
  attr_reader :atype
507
-
552
+
508
553
  # Map from short style option switches to actual switch objects.
509
554
  attr_reader :short
510
-
555
+
511
556
  # Map from long style option switches to actual switch objects.
512
557
  attr_reader :long
513
-
558
+
514
559
  # List of all switches and summary string.
515
560
  attr_reader :list
516
561
 
@@ -527,9 +572,10 @@ class OptionParser
527
572
  #
528
573
  # See OptionParser.accept.
529
574
  #
530
- def accept(t, pat = /.*/nm, &block)
575
+ def accept(t, pat = /.*/m, &block)
531
576
  if pat
532
- pat.respond_to?(:match) or raise TypeError, "has no `match'"
577
+ pat.respond_to?(:match) or
578
+ raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2))
533
579
  else
534
580
  pat = t if t.respond_to?(:match)
535
581
  end
@@ -555,7 +601,6 @@ class OptionParser
555
601
  # +nlopts+:: Negated long style options list.
556
602
  #
557
603
  def update(sw, sopts, lopts, nsw = nil, nlopts = nil)
558
- o = nil
559
604
  sopts.each {|o| @short[o] = sw} if sopts
560
605
  lopts.each {|o| @long[o] = sw} if lopts
561
606
  nlopts.each {|o| @long[o] = nsw} if nsw and nlopts
@@ -567,7 +612,7 @@ class OptionParser
567
612
  #
568
613
  # Inserts +switch+ at the head of the list, and associates short, long
569
614
  # and negated long options. Arguments are:
570
- #
615
+ #
571
616
  # +switch+:: OptionParser::Switch instance to be inserted.
572
617
  # +short_opts+:: List of short style options.
573
618
  # +long_opts+:: List of long style options.
@@ -583,7 +628,7 @@ class OptionParser
583
628
  #
584
629
  # Appends +switch+ at the tail of the list, and associates short, long
585
630
  # and negated long options. Arguments are:
586
- #
631
+ #
587
632
  # +switch+:: OptionParser::Switch instance to be inserted.
588
633
  # +short_opts+:: List of short style options.
589
634
  # +long_opts+:: List of long style options.
@@ -655,6 +700,14 @@ class OptionParser
655
700
  end
656
701
  to
657
702
  end
703
+
704
+ def compsys(*args, &block) # :nodoc:
705
+ list.each do |opt|
706
+ if opt.respond_to?(:compsys)
707
+ opt.compsys(*args, &block)
708
+ end
709
+ end
710
+ end
658
711
  end
659
712
 
660
713
  #
@@ -667,9 +720,10 @@ class OptionParser
667
720
  # Completion for hash key.
668
721
  #
669
722
  def match(key)
670
- return key, *fetch(key) {
723
+ *values = fetch(key) {
671
724
  raise AmbiguousArgument, catch(:ambiguous) {return complete(key)}
672
725
  }
726
+ return key, *values
673
727
  end
674
728
  end
675
729
 
@@ -700,6 +754,24 @@ class OptionParser
700
754
  DefaultList.short['-'] = Switch::NoArgument.new {}
701
755
  DefaultList.long[''] = Switch::NoArgument.new {throw :terminate}
702
756
 
757
+
758
+ COMPSYS_HEADER = <<'XXX' # :nodoc:
759
+
760
+ typeset -A opt_args
761
+ local context state line
762
+
763
+ _arguments -s -S \
764
+ XXX
765
+
766
+ def compsys(to, name = File.basename($0)) # :nodoc:
767
+ to << "#compdef #{name}\n"
768
+ to << COMPSYS_HEADER
769
+ visit(:compsys, {}, {}) {|o, d|
770
+ to << %Q[ "#{o}[#{d.gsub(/[\"\[\]]/, '\\\\\&')}]" \\\n]
771
+ }
772
+ to << " '*:file:_files' && return 0\n"
773
+ end
774
+
703
775
  #
704
776
  # Default options for ARGV, which never appear in option summary.
705
777
  #
@@ -710,12 +782,34 @@ class OptionParser
710
782
  # Shows option summary.
711
783
  #
712
784
  Officious['help'] = proc do |parser|
713
- Switch::NoArgument.new do
785
+ Switch::NoArgument.new do |arg|
714
786
  puts parser.help
715
787
  exit
716
788
  end
717
789
  end
718
790
 
791
+ #
792
+ # --*-completion-bash=WORD
793
+ # Shows candidates for command line completion.
794
+ #
795
+ Officious['*-completion-bash'] = proc do |parser|
796
+ Switch::RequiredArgument.new do |arg|
797
+ puts parser.candidate(arg)
798
+ exit
799
+ end
800
+ end
801
+
802
+ #
803
+ # --*-completion-zsh[=NAME:FILE]
804
+ # Creates zsh completion file.
805
+ #
806
+ Officious['*-completion-zsh'] = proc do |parser|
807
+ Switch::OptionalArgument.new do |arg|
808
+ parser.compsys(STDOUT, arg)
809
+ exit
810
+ end
811
+ end
812
+
719
813
  #
720
814
  # --version
721
815
  # Shows version string if Version is defined.
@@ -748,7 +842,7 @@ class OptionParser
748
842
  # Initializes a new instance and evaluates the optional block in context
749
843
  # of the instance. Arguments +args+ are passed to #new, see there for
750
844
  # description of parameters.
751
- #
845
+ #
752
846
  # This method is *deprecated*, its behavior corresponds to the older #new
753
847
  # method.
754
848
  #
@@ -974,13 +1068,13 @@ class OptionParser
974
1068
  #
975
1069
  # Returns option summary string.
976
1070
  #
977
- def help; summarize(banner.to_s.sub(/\n?\z/, "\n")) end
1071
+ def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end
978
1072
  alias to_s help
979
1073
 
980
1074
  #
981
1075
  # Returns option summary list.
982
1076
  #
983
- def to_a; summarize(banner.to_a.dup) end
1077
+ def to_a; summarize("#{banner}".split(/^/)) end
984
1078
 
985
1079
  #
986
1080
  # Checks if an argument is given twice, in which case an ArgumentError is
@@ -992,17 +1086,14 @@ class OptionParser
992
1086
  #
993
1087
  def notwice(obj, prv, msg)
994
1088
  unless !prv or prv == obj
995
- begin
996
- raise ArgumentError, "argument #{msg} given twice: #{obj}"
997
- rescue
998
- $@[0, 2] = nil
999
- raise
1000
- end
1089
+ raise(ArgumentError, "argument #{msg} given twice: #{obj}",
1090
+ ParseError.filter_backtrace(caller(2)))
1001
1091
  end
1002
1092
  obj
1003
1093
  end
1004
1094
  private :notwice
1005
1095
 
1096
+ SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a}
1006
1097
  #
1007
1098
  # Creates an OptionParser::Switch from the parameters. The parsed argument
1008
1099
  # value is passed to the given block, where it can be processed.
@@ -1044,7 +1135,7 @@ class OptionParser
1044
1135
  # There is also a special form which matches character range (not full
1045
1136
  # set of regular expression):
1046
1137
  # "-[a-z]MANDATORY"
1047
- # "-[a-z][OPTIONAL]"
1138
+ # "-[a-z][OPTIONAL]"
1048
1139
  # "-[a-z]"
1049
1140
  #
1050
1141
  # [Argument style and description:]
@@ -1056,7 +1147,7 @@ class OptionParser
1056
1147
  # [Description:]
1057
1148
  # Description string for the option.
1058
1149
  # "Run verbosely"
1059
- #
1150
+ #
1060
1151
  # [Handler:]
1061
1152
  # Handler for the parsed argument value. Either give a block or pass a
1062
1153
  # Proc or Method as an argument.
@@ -1067,8 +1158,7 @@ class OptionParser
1067
1158
  default_style = Switch::NoArgument
1068
1159
  default_pattern = nil
1069
1160
  klass = nil
1070
- o = nil
1071
- n, q, a = nil
1161
+ q, a = nil
1072
1162
 
1073
1163
  opts.each do |o|
1074
1164
  # argument class
@@ -1082,9 +1172,13 @@ class OptionParser
1082
1172
  end
1083
1173
 
1084
1174
  # directly specified pattern(any object possible to match)
1085
- if !(String === o) and o.respond_to?(:match)
1175
+ if (!(String === o || Symbol === o)) and o.respond_to?(:match)
1086
1176
  pattern = notwice(o, pattern, 'pattern')
1087
- conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert)
1177
+ if pattern.respond_to?(:convert)
1178
+ conv = pattern.method(:convert).to_proc
1179
+ else
1180
+ conv = SPLAT_PROC
1181
+ end
1088
1182
  next
1089
1183
  end
1090
1184
 
@@ -1101,9 +1195,9 @@ class OptionParser
1101
1195
  else
1102
1196
  raise ArgumentError, "argument pattern given twice"
1103
1197
  end
1104
- o.each {|(o, *v)| pattern[o] = v.fetch(0) {o}}
1198
+ o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
1105
1199
  when Module
1106
- raise ArgumentError, "unsupported argument type: #{o}"
1200
+ raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
1107
1201
  when *ArgumentStyle.keys
1108
1202
  style = notwice(ArgumentStyle[o], style, 'style')
1109
1203
  when /^--no-([^\[\]=\s]*)(.+)?/
@@ -1168,7 +1262,9 @@ class OptionParser
1168
1262
  s = (style || default_style).new(pattern || default_pattern,
1169
1263
  conv, sdesc, ldesc, arg, desc, block)
1170
1264
  elsif !block
1171
- raise ArgumentError, "no switch given" if style or pattern
1265
+ if style or pattern
1266
+ raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
1267
+ end
1172
1268
  s = desc
1173
1269
  else
1174
1270
  short << pattern
@@ -1243,19 +1339,20 @@ class OptionParser
1243
1339
 
1244
1340
  #
1245
1341
  # Same as #order, but removes switches destructively.
1342
+ # Non-option arguments remain in +argv+.
1246
1343
  #
1247
1344
  def order!(argv = default_argv, &nonopt)
1248
1345
  parse_in_order(argv, &nonopt)
1249
1346
  end
1250
1347
 
1251
1348
  def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
1252
- opt, arg, sw, val, rest = nil
1253
- nonopt ||= proc {|arg| throw :terminate, arg}
1349
+ opt, arg, val, rest = nil
1350
+ nonopt ||= proc {|a| throw :terminate, a}
1254
1351
  argv.unshift(arg) if arg = catch(:terminate) {
1255
1352
  while arg = argv.shift
1256
1353
  case arg
1257
1354
  # long option
1258
- when /\A--([^=]*)(?:=(.*))?/nm
1355
+ when /\A--([^=]*)(?:=(.*))?/m
1259
1356
  opt, rest = $1, $2
1260
1357
  begin
1261
1358
  sw, = complete(:long, opt, true)
@@ -1271,7 +1368,7 @@ class OptionParser
1271
1368
  end
1272
1369
 
1273
1370
  # short option
1274
- when /\A-(.)((=).*|.+)?/nm
1371
+ when /\A-(.)((=).*|.+)?/m
1275
1372
  opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
1276
1373
  begin
1277
1374
  sw, = search(:short, opt)
@@ -1294,7 +1391,7 @@ class OptionParser
1294
1391
  begin
1295
1392
  opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
1296
1393
  raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
1297
- argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
1394
+ argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
1298
1395
  val = cb.call(val) if cb
1299
1396
  setter.call(sw.switch_name, val) if setter
1300
1397
  rescue ParseError
@@ -1304,7 +1401,8 @@ class OptionParser
1304
1401
  # non-option argument
1305
1402
  else
1306
1403
  catch(:prune) do
1307
- visit(:each_option) do |sw|
1404
+ visit(:each_option) do |sw0|
1405
+ sw = sw0
1308
1406
  sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg)
1309
1407
  end
1310
1408
  nonopt.call(arg)
@@ -1332,11 +1430,11 @@ class OptionParser
1332
1430
 
1333
1431
  #
1334
1432
  # Same as #permute, but removes switches destructively.
1433
+ # Non-option arguments remain in +argv+.
1335
1434
  #
1336
1435
  def permute!(argv = default_argv)
1337
1436
  nonopts = []
1338
- arg = nil
1339
- order!(argv) {|arg| nonopts << arg}
1437
+ order!(argv, &nonopts.method(:<<))
1340
1438
  argv[0, 0] = nonopts
1341
1439
  argv
1342
1440
  end
@@ -1352,6 +1450,7 @@ class OptionParser
1352
1450
 
1353
1451
  #
1354
1452
  # Same as #parse, but removes switches destructively.
1453
+ # Non-option arguments remain in +argv+.
1355
1454
  #
1356
1455
  def parse!(argv = default_argv)
1357
1456
  if ENV.include?('POSIXLY_CORRECT')
@@ -1413,7 +1512,6 @@ class OptionParser
1413
1512
  # +block+.
1414
1513
  #
1415
1514
  def visit(id, *args, &block)
1416
- el = nil
1417
1515
  @stack.reverse_each do |el|
1418
1516
  el.send(id, *args, &block)
1419
1517
  end
@@ -1446,12 +1544,42 @@ class OptionParser
1446
1544
  search(typ, opt) {|sw| return [sw, opt]} # exact match or...
1447
1545
  end
1448
1546
  raise AmbiguousOption, catch(:ambiguous) {
1449
- visit(:complete, typ, opt, icase, *pat) {|opt, *sw| return sw}
1547
+ visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw}
1450
1548
  raise InvalidOption, opt
1451
1549
  }
1452
1550
  end
1453
1551
  private :complete
1454
1552
 
1553
+ def candidate(word)
1554
+ list = []
1555
+ case word
1556
+ when /\A--/
1557
+ word, arg = word.split(/=/, 2)
1558
+ argpat = Completion.regexp(arg, false) if arg and !arg.empty?
1559
+ long = true
1560
+ when /\A-(!-)/
1561
+ short = true
1562
+ when /\A-/
1563
+ long = short = true
1564
+ end
1565
+ pat = Completion.regexp(word, true)
1566
+ visit(:each_option) do |opt|
1567
+ next unless Switch === opt
1568
+ opts = (long ? opt.long : []) + (short ? opt.short : [])
1569
+ opts = Completion.candidate(word, true, pat, &opts.method(:each)).map(&:first) if pat
1570
+ if /\A=/ =~ opt.arg
1571
+ opts.map! {|sw| sw + "="}
1572
+ if arg and CompletingHash === opt.pattern
1573
+ if opts = opt.pattern.candidate(arg, false, argpat)
1574
+ opts.map!(&:last)
1575
+ end
1576
+ end
1577
+ end
1578
+ list.concat(opts)
1579
+ end
1580
+ list
1581
+ end
1582
+
1455
1583
  #
1456
1584
  # Loads options from file names as +filename+. Does nothing when the file
1457
1585
  # is not present. Returns whether successfully loaded.
@@ -1499,7 +1627,7 @@ class OptionParser
1499
1627
  #
1500
1628
  # Any non-empty string, and no conversion.
1501
1629
  #
1502
- accept(String, /.+/nm) {|s,*|s}
1630
+ accept(String, /.+/m) {|s,*|s}
1503
1631
 
1504
1632
  #
1505
1633
  # Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal
@@ -1522,9 +1650,16 @@ class OptionParser
1522
1650
 
1523
1651
  #
1524
1652
  # Generic numeric format, converts to Integer for integer format, Float
1525
- # for float format.
1526
- #
1527
- accept(Numeric, %r"\A[-+]?(?:#{octal}|#{float})"io) {|s,| eval(s) if s}
1653
+ # for float format, and Rational for rational format.
1654
+ #
1655
+ real = "[-+]?(?:#{octal}|#{float})"
1656
+ accept(Numeric, /\A(#{real})(?:\/(#{real}))?/io) {|s, d, n|
1657
+ if n
1658
+ Rational(d, n)
1659
+ elsif s
1660
+ eval(s)
1661
+ end
1662
+ }
1528
1663
 
1529
1664
  #
1530
1665
  # Decimal integer format, to be converted to Integer.
@@ -1554,7 +1689,7 @@ class OptionParser
1554
1689
  yesno = CompletingHash.new
1555
1690
  %w[- no false].each {|el| yesno[el] = false}
1556
1691
  %w[+ yes true].each {|el| yesno[el] = true}
1557
- yesno['nil'] = false # shoud be nil?
1692
+ yesno['nil'] = false # should be nil?
1558
1693
  accept(TrueClass, yesno) {|arg, val| val == nil or val}
1559
1694
  #
1560
1695
  # Similar to TrueClass, but defaults to false.
@@ -1566,7 +1701,7 @@ class OptionParser
1566
1701
  #
1567
1702
  accept(Array) do |s,|
1568
1703
  if s
1569
- s = s.split(',').collect {|s| s unless s.empty?}
1704
+ s = s.split(',').collect {|ss| ss unless ss.empty?}
1570
1705
  end
1571
1706
  s
1572
1707
  end
@@ -1580,7 +1715,8 @@ class OptionParser
1580
1715
  f |= Regexp::IGNORECASE if /i/ =~ o
1581
1716
  f |= Regexp::MULTILINE if /m/ =~ o
1582
1717
  f |= Regexp::EXTENDED if /x/ =~ o
1583
- k = o.delete("^imx")
1718
+ k = o.delete("imx")
1719
+ k = nil if k.empty?
1584
1720
  end
1585
1721
  Regexp.new(s || all, f, k)
1586
1722
  end
@@ -1612,6 +1748,17 @@ class OptionParser
1612
1748
  argv
1613
1749
  end
1614
1750
 
1751
+ def self.filter_backtrace(array)
1752
+ unless $DEBUG
1753
+ array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
1754
+ end
1755
+ array
1756
+ end
1757
+
1758
+ def set_backtrace(array)
1759
+ super(self.class.filter_backtrace(array))
1760
+ end
1761
+
1615
1762
  def set_option(opt, eq)
1616
1763
  if eq
1617
1764
  @args[0] = opt
@@ -1791,6 +1938,6 @@ ARGV.extend(OptionParser::Arguable)
1791
1938
  if $0 == __FILE__
1792
1939
  Version = OptionParser::Version
1793
1940
  ARGV.options {|q|
1794
- q.parse!.empty? or puts "what's #{ARGV.join(' ')}?"
1941
+ q.parse!.empty? or print "what's #{ARGV.join(' ')}?\n"
1795
1942
  } or abort(ARGV.options.to_s)
1796
1943
  end
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module OptionParser
3
- VERSION = "1.0.1"
3
+ VERSION = "2.0.1"
4
4
  end
5
5
  end
@@ -16,12 +16,11 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.required_ruby_version = "~> 1.8.7"
19
+ spec.required_ruby_version = "~> 2.0"
20
20
 
21
- spec.add_runtime_dependency "rubysl-shellwords", "~> 1.0"
21
+ spec.add_runtime_dependency "rubysl-shellwords", "~> 2.0"
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "mspec", "~> 1.5"
26
- spec.add_development_dependency "rubysl-prettyprint", "~> 1.0"
27
26
  end
metadata CHANGED
@@ -1,85 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-optparse
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-16 00:00:00.000000000 Z
11
+ date: 2013-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubysl-shellwords
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '10.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: mspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.5'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.5'
69
- - !ruby/object:Gem::Dependency
70
- name: rubysl-prettyprint
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.0'
83
69
  description: Ruby standard library OptionParser.
84
70
  email:
85
71
  - brixen@gmail.com
@@ -87,13 +73,14 @@ executables: []
87
73
  extensions: []
88
74
  extra_rdoc_files: []
89
75
  files:
90
- - ".gitignore"
91
- - ".travis.yml"
76
+ - .gitignore
77
+ - .travis.yml
92
78
  - Gemfile
93
79
  - LICENSE
94
80
  - README.md
95
81
  - Rakefile
96
82
  - lib/optparse.rb
83
+ - lib/optparse/ac.rb
97
84
  - lib/optparse/date.rb
98
85
  - lib/optparse/shellwords.rb
99
86
  - lib/optparse/time.rb
@@ -113,18 +100,19 @@ require_paths:
113
100
  - lib
114
101
  required_ruby_version: !ruby/object:Gem::Requirement
115
102
  requirements:
116
- - - "~>"
103
+ - - ~>
117
104
  - !ruby/object:Gem::Version
118
- version: 1.8.7
105
+ version: '2.0'
119
106
  required_rubygems_version: !ruby/object:Gem::Requirement
120
107
  requirements:
121
- - - ">="
108
+ - - '>='
122
109
  - !ruby/object:Gem::Version
123
110
  version: '0'
124
111
  requirements: []
125
112
  rubyforge_project:
126
- rubygems_version: 2.2.2
113
+ rubygems_version: 2.0.7
127
114
  signing_key:
128
115
  specification_version: 4
129
116
  summary: Ruby standard library OptionParser.
130
117
  test_files: []
118
+ has_rdoc: