rubysl-optparse 1.0.1 → 2.0.1

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.
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: