source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/optparse.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 46.8 KB
Line 
1#
2# optparse.rb - command-line option analysis with the OptionParser class.
3#
4# Author:: Nobu Nakada
5# Documentation:: Nobu Nakada and Gavin Sinclair.
6#
7# See OptionParser for documentation.
8#
9
10
11# == Developer Documentation (not for RDoc output)
12#
13# === Class tree
14#
15# - OptionParser:: front end
16# - OptionParser::Switch:: each switches
17# - OptionParser::List:: options list
18# - OptionParser::ParseError:: errors on parsing
19# - OptionParser::AmbiguousOption
20# - OptionParser::NeedlessArgument
21# - OptionParser::MissingArgument
22# - OptionParser::InvalidOption
23# - OptionParser::InvalidArgument
24# - OptionParser::AmbiguousArgument
25#
26# === Object relationship diagram
27#
28# +--------------+
29# | OptionParser |<>-----+
30# +--------------+ | +--------+
31# | ,-| Switch |
32# on_head -------->+---------------+ / +--------+
33# accept/reject -->| List |<|>-
34# | |<|>- +----------+
35# on ------------->+---------------+ `-| argument |
36# : : | class |
37# +---------------+ |==========|
38# on_tail -------->| | |pattern |
39# +---------------+ |----------|
40# OptionParser.accept ->| DefaultList | |converter |
41# reject |(shared between| +----------+
42# | all instances)|
43# +---------------+
44#
45# == OptionParser
46#
47# === Introduction
48#
49# OptionParser is a class for command-line option analysis. It is much more
50# advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented
51# solution.
52#
53# === Features
54#
55# 1. The argument specification and the code to handle it are written in the
56# same place.
57# 2. It can output an option summary; you don't need to maintain this string
58# separately.
59# 3. Optional and mandatory arguments are specified very gracefully.
60# 4. Arguments can be automatically converted to a specified class.
61# 5. Arguments can be restricted to a certain set.
62#
63# All of these features are demonstrated in the examples below.
64#
65# === Minimal example
66#
67# require 'optparse'
68#
69# options = {}
70# OptionParser.new do |opts|
71# opts.banner = "Usage: example.rb [options]"
72#
73# opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
74# options[:verbose] = v
75# end
76# end.parse!
77#
78# p options
79# p ARGV
80#
81# === Complete example
82#
83# The following example is a complete Ruby program. You can run it and see the
84# effect of specifying various options. This is probably the best way to learn
85# the features of +optparse+.
86#
87# require 'optparse'
88# require 'optparse/time'
89# require 'ostruct'
90# require 'pp'
91#
92# class OptparseExample
93#
94# CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
95# CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
96#
97# #
98# # Return a structure describing the options.
99# #
100# def self.parse(args)
101# # The options specified on the command line will be collected in *options*.
102# # We set default values here.
103# options = OpenStruct.new
104# options.library = []
105# options.inplace = false
106# options.encoding = "utf8"
107# options.transfer_type = :auto
108# options.verbose = false
109#
110# opts = OptionParser.new do |opts|
111# opts.banner = "Usage: example.rb [options]"
112#
113# opts.separator ""
114# opts.separator "Specific options:"
115#
116# # Mandatory argument.
117# opts.on("-r", "--require LIBRARY",
118# "Require the LIBRARY before executing your script") do |lib|
119# options.library << lib
120# end
121#
122# # Optional argument; multi-line description.
123# opts.on("-i", "--inplace [EXTENSION]",
124# "Edit ARGV files in place",
125# " (make backup if EXTENSION supplied)") do |ext|
126# options.inplace = true
127# options.extension = ext || ''
128# options.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot.
129# end
130#
131# # Cast 'delay' argument to a Float.
132# opts.on("--delay N", Float, "Delay N seconds before executing") do |n|
133# options.delay = n
134# end
135#
136# # Cast 'time' argument to a Time object.
137# opts.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
138# options.time = time
139# end
140#
141# # Cast to octal integer.
142# opts.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
143# "Specify record separator (default \\0)") do |rs|
144# options.record_separator = rs
145# end
146#
147# # List of arguments.
148# opts.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
149# options.list = list
150# end
151#
152# # Keyword completion. We are specifying a specific set of arguments (CODES
153# # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
154# # the shortest unambiguous text.
155# code_list = (CODE_ALIASES.keys + CODES).join(',')
156# opts.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
157# " (#{code_list})") do |encoding|
158# options.encoding = encoding
159# end
160#
161# # Optional argument with keyword completion.
162# opts.on("--type [TYPE]", [:text, :binary, :auto],
163# "Select transfer type (text, binary, auto)") do |t|
164# options.transfer_type = t
165# end
166#
167# # Boolean switch.
168# opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
169# options.verbose = v
170# end
171#
172# opts.separator ""
173# opts.separator "Common options:"
174#
175# # No argument, shows at tail. This will print an options summary.
176# # Try it and see!
177# opts.on_tail("-h", "--help", "Show this message") do
178# puts opts
179# exit
180# end
181#
182# # Another typical switch to print the version.
183# opts.on_tail("--version", "Show version") do
184# puts OptionParser::Version.join('.')
185# exit
186# end
187# end
188#
189# opts.parse!(args)
190# options
191# end # parse()
192#
193# end # class OptparseExample
194#
195# options = OptparseExample.parse(ARGV)
196# pp options
197#
198# === Further documentation
199#
200# The above examples should be enough to learn how to use this class. If you
201# have any questions, email me ([email protected]) and I will update
202# this document.
203#
204class OptionParser
205 # :stopdoc:
206 RCSID = %w$Id: optparse.rb 11798 2007-02-20 06:53:16Z knu $[1..-1].each {|s| s.freeze}.freeze
207 Version = (RCSID[1].split('.').collect {|s| s.to_i}.extend(Comparable).freeze if RCSID[1])
208 LastModified = (Time.gm(*RCSID[2, 2].join('-').scan(/\d+/).collect {|s| s.to_i}) if RCSID[2])
209 Release = RCSID[2]
210
211 NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
212 RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze
213 OptionalArgument = [OPTIONAL_ARGUMENT = :OPTIONAL, false].freeze
214 # :startdoc:
215
216 #
217 # Keyword completion module. This allows partial arguments to be specified
218 # and resolved against a list of acceptable values.
219 #
220 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
225 candidates = []
226 each do |k, *v|
227 (if Regexp === k
228 kn = nil
229 k === key
230 else
231 kn = defined?(k.id2name) ? k.id2name : k
232 pat === kn
233 end) or next
234 v << k if v.empty?
235 candidates << [k, v, kn]
236 end
237 candidates = candidates.sort_by {|k, v, kn| kn.size}
238 if candidates.size == 1
239 canon, sw, * = candidates[0]
240 elsif candidates.size > 1
241 canon, sw, cn = candidates.shift
242 candidates.each do |k, v, kn|
243 next if sw == v
244 if String === cn and String === kn
245 if cn.rindex(kn, 0)
246 canon, sw, cn = k, v, kn
247 next
248 elsif kn.rindex(cn, 0)
249 next
250 end
251 end
252 throw :ambiguous, key
253 end
254 end
255 if canon
256 block_given? or return key, *sw
257 yield(key, *sw)
258 end
259 end
260
261 def convert(opt = nil, val = nil, *)
262 val
263 end
264 end
265
266
267 #
268 # Map from option/keyword string to object with completion.
269 #
270 class OptionMap < Hash
271 include Completion
272 end
273
274
275 #
276 # Individual switch class. Not important to the user.
277 #
278 # Defined within Switch are several Switch-derived classes: NoArgument,
279 # RequiredArgument, etc.
280 #
281 class Switch
282 attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
283
284 #
285 # Guesses argument style from +arg+. Returns corresponding
286 # OptionParser::Switch class (OptionalArgument, etc.).
287 #
288 def self.guess(arg)
289 case arg
290 when ""
291 t = self
292 when /\A=?\[/
293 t = Switch::OptionalArgument
294 when /\A\s+\[/
295 t = Switch::PlacedArgument
296 else
297 t = Switch::RequiredArgument
298 end
299 self >= t or incompatible_argument_styles(arg, t)
300 t
301 end
302
303 def self.incompatible_argument_styles(arg, t)
304 raise ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}"
305 end
306
307 def self.pattern
308 NilClass
309 end
310
311 def initialize(pattern = nil, conv = nil,
312 short = nil, long = nil, arg = nil,
313 desc = ([] if short or long), block = Proc.new)
314 raise if Array === pattern
315 @pattern, @conv, @short, @long, @arg, @desc, @block =
316 pattern, conv, short, long, arg, desc, block
317 end
318
319 #
320 # Parses +arg+ and returns rest of +arg+ and matched portion to the
321 # argument pattern. Yields when the pattern doesn't match substring.
322 #
323 def parse_arg(arg)
324 pattern or return nil, arg
325 unless m = pattern.match(arg)
326 yield(InvalidArgument, arg)
327 return arg, nil
328 end
329 if String === m
330 m = [s = m]
331 else
332 m = m.to_a
333 s = m[0]
334 return nil, m unless String === s
335 end
336 raise InvalidArgument, arg unless arg.rindex(s, 0)
337 return nil, m if s.length == arg.length
338 yield(InvalidArgument, arg) # didn't match whole arg
339 return arg[s.length..-1], m
340 end
341 private :parse_arg
342
343 #
344 # Parses argument, converts and returns +arg+, +block+ and result of
345 # conversion. Yields at semi-error condition instead of raising an
346 # exception.
347 #
348 def conv_arg(arg, val = nil)
349 if conv
350 val = conv.call(*val)
351 else
352 val = proc {|val| val}.call(*val)
353 end
354 return arg, block, val
355 end
356 private :conv_arg
357
358 #
359 # Produces the summary text. Each line of the summary is yielded to the
360 # block (without newline).
361 #
362 # +sdone+:: Already summarized short style options keyed hash.
363 # +ldone+:: Already summarized long style options keyed hash.
364 # +width+:: Width of left side (option part). In other words, the right
365 # side (description part) starts after +width+ columns.
366 # +max+:: Maximum width of left side -> the options are filled within
367 # +max+ columns.
368 # +indent+:: Prefix string indents all summarized lines.
369 #
370 def summarize(sdone = [], ldone = [], width = 1, max = width - 1, indent = "")
371 sopts, lopts, s = [], [], nil
372 @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short
373 @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long
374 return if sopts.empty? and lopts.empty? # completely hidden
375
376 left = [sopts.join(', ')]
377 right = desc.dup
378
379 while s = lopts.shift
380 l = left[-1].length + s.length
381 l += arg.length if left.size == 1 && arg
382 l < max or left << ''
383 left[-1] << if left[-1].empty? then ' ' * 4 else ', ' end << s
384 end
385
386 left[0] << arg if arg
387 mlen = left.collect {|s| s.length}.max.to_i
388 while mlen > width and l = left.shift
389 mlen = left.collect {|s| s.length}.max.to_i if l.length == mlen
390 yield(indent + l)
391 end
392
393 while begin l = left.shift; r = right.shift; l or r end
394 l = l.to_s.ljust(width) + ' ' + r if r and !r.empty?
395 yield(indent + l)
396 end
397
398 self
399 end
400
401 def add_banner(to) # :nodoc:
402 unless @short or @long
403 s = desc.join
404 to << " [" + s + "]..." unless s.empty?
405 end
406 to
407 end
408
409 def match_nonswitch?(str) # :nodoc:
410 @pattern =~ str unless @short or @long
411 end
412
413 #
414 # Main name of the switch.
415 #
416 def switch_name
417 (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '')
418 end
419
420 #
421 # Switch that takes no arguments.
422 #
423 class NoArgument < self
424
425 #
426 # Raises an exception if any arguments given.
427 #
428 def parse(arg, argv)
429 yield(NeedlessArgument, arg) if arg
430 conv_arg(arg)
431 end
432
433 def self.incompatible_argument_styles(*)
434 end
435
436 def self.pattern
437 Object
438 end
439 end
440
441 #
442 # Switch that takes an argument.
443 #
444 class RequiredArgument < self
445
446 #
447 # Raises an exception if argument is not present.
448 #
449 def parse(arg, argv)
450 unless arg
451 raise MissingArgument if argv.empty?
452 arg = argv.shift
453 end
454 conv_arg(*parse_arg(arg) {|*exc| raise(*exc)})
455 end
456 end
457
458 #
459 # Switch that can omit argument.
460 #
461 class OptionalArgument < self
462
463 #
464 # Parses argument if given, or uses default value.
465 #
466 def parse(arg, argv, &error)
467 if arg
468 conv_arg(*parse_arg(arg, &error))
469 else
470 conv_arg(arg)
471 end
472 end
473 end
474
475 #
476 # Switch that takes an argument, which does not begin with '-'.
477 #
478 class PlacedArgument < self
479
480 #
481 # Returns nil if argument is not present or begins with '-'.
482 #
483 def parse(arg, argv, &error)
484 if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
485 return nil, block, nil
486 end
487 opt = (val = parse_arg(val, &error))[1]
488 val = conv_arg(*val)
489 if opt and !arg
490 argv.shift
491 else
492 val[0] = nil
493 end
494 val
495 end
496 end
497 end
498
499 #
500 # Simple option list providing mapping from short and/or long option
501 # string to OptionParser::Switch and mapping from acceptable argument to
502 # matching pattern and converter pair. Also provides summary feature.
503 #
504 class List
505 # Map from acceptable argument types to pattern and converter pairs.
506 attr_reader :atype
507
508 # Map from short style option switches to actual switch objects.
509 attr_reader :short
510
511 # Map from long style option switches to actual switch objects.
512 attr_reader :long
513
514 # List of all switches and summary string.
515 attr_reader :list
516
517 #
518 # Just initializes all instance variables.
519 #
520 def initialize
521 @atype = {}
522 @short = OptionMap.new
523 @long = OptionMap.new
524 @list = []
525 end
526
527 #
528 # See OptionParser.accept.
529 #
530 def accept(t, pat = /.*/nm, &block)
531 if pat
532 pat.respond_to?(:match) or raise TypeError, "has no `match'"
533 else
534 pat = t if t.respond_to?(:match)
535 end
536 unless block
537 block = pat.method(:convert).to_proc if pat.respond_to?(:convert)
538 end
539 @atype[t] = [pat, block]
540 end
541
542 #
543 # See OptionParser.reject.
544 #
545 def reject(t)
546 @atype.delete(t)
547 end
548
549 #
550 # Adds +sw+ according to +sopts+, +lopts+ and +nlopts+.
551 #
552 # +sw+:: OptionParser::Switch instance to be added.
553 # +sopts+:: Short style option list.
554 # +lopts+:: Long style option list.
555 # +nlopts+:: Negated long style options list.
556 #
557 def update(sw, sopts, lopts, nsw = nil, nlopts = nil)
558 o = nil
559 sopts.each {|o| @short[o] = sw} if sopts
560 lopts.each {|o| @long[o] = sw} if lopts
561 nlopts.each {|o| @long[o] = nsw} if nsw and nlopts
562 used = @short.invert.update(@long.invert)
563 @list.delete_if {|o| Switch === o and !used[o]}
564 end
565 private :update
566
567 #
568 # Inserts +switch+ at the head of the list, and associates short, long
569 # and negated long options. Arguments are:
570 #
571 # +switch+:: OptionParser::Switch instance to be inserted.
572 # +short_opts+:: List of short style options.
573 # +long_opts+:: List of long style options.
574 # +nolong_opts+:: List of long style options with "no-" prefix.
575 #
576 # prepend(switch, short_opts, long_opts, nolong_opts)
577 #
578 def prepend(*args)
579 update(*args)
580 @list.unshift(args[0])
581 end
582
583 #
584 # Appends +switch+ at the tail of the list, and associates short, long
585 # and negated long options. Arguments are:
586 #
587 # +switch+:: OptionParser::Switch instance to be inserted.
588 # +short_opts+:: List of short style options.
589 # +long_opts+:: List of long style options.
590 # +nolong_opts+:: List of long style options with "no-" prefix.
591 #
592 # append(switch, short_opts, long_opts, nolong_opts)
593 #
594 def append(*args)
595 update(*args)
596 @list.push(args[0])
597 end
598
599 #
600 # Searches +key+ in +id+ list. The result is returned or yielded if a
601 # block is given. If it isn't found, nil is returned.
602 #
603 def search(id, key)
604 if list = __send__(id)
605 val = list.fetch(key) {return nil}
606 block_given? ? yield(val) : val
607 end
608 end
609
610 #
611 # Searches list +id+ for +opt+ and the optional patterns for completion
612 # +pat+. If +icase+ is true, the search is case insensitive. The result
613 # is returned or yielded if a block is given. If it isn't found, nil is
614 # returned.
615 #
616 def complete(id, opt, icase = false, *pat, &block)
617 __send__(id).complete(opt, icase, *pat, &block)
618 end
619
620 #
621 # Iterates over each option, passing the option to the +block+.
622 #
623 def each_option(&block)
624 list.each(&block)
625 end
626
627 #
628 # Creates the summary table, passing each line to the +block+ (without
629 # newline). The arguments +args+ are passed along to the summarize
630 # method which is called on every option.
631 #
632 def summarize(*args, &block)
633 list.each do |opt|
634 if opt.respond_to?(:summarize) # perhaps OptionParser::Switch
635 opt.summarize(*args, &block)
636 elsif !opt or opt.empty?
637 yield("")
638 else
639 opt.each(&block)
640 end
641 end
642 end
643
644 def add_banner(to) # :nodoc:
645 list.each do |opt|
646 if opt.respond_to?(:add_banner)
647 opt.add_banner(to)
648 end
649 end
650 to
651 end
652 end
653
654 #
655 # Hash with completion search feature. See OptionParser::Completion.
656 #
657 class CompletingHash < Hash
658 include Completion
659
660 #
661 # Completion for hash key.
662 #
663 def match(key)
664 return key, *fetch(key) {
665 raise AmbiguousArgument, catch(:ambiguous) {return complete(key)}
666 }
667 end
668 end
669
670 # :stopdoc:
671
672 #
673 # Enumeration of acceptable argument styles. Possible values are:
674 #
675 # NO_ARGUMENT:: The switch takes no arguments. (:NONE)
676 # REQUIRED_ARGUMENT:: The switch requires an argument. (:REQUIRED)
677 # OPTIONAL_ARGUMENT:: The switch requires an optional argument. (:OPTIONAL)
678 #
679 # Use like --switch=argument (long style) or -Xargument (short style). For
680 # short style, only portion matched to argument pattern is dealed as
681 # argument.
682 #
683 ArgumentStyle = {}
684 NoArgument.each {|el| ArgumentStyle[el] = Switch::NoArgument}
685 RequiredArgument.each {|el| ArgumentStyle[el] = Switch::RequiredArgument}
686 OptionalArgument.each {|el| ArgumentStyle[el] = Switch::OptionalArgument}
687 ArgumentStyle.freeze
688
689 #
690 # Switches common used such as '--', and also provides default
691 # argument classes
692 #
693 DefaultList = List.new
694 DefaultList.short['-'] = Switch::NoArgument.new {}
695 DefaultList.long[''] = Switch::NoArgument.new {throw :terminate}
696
697 #
698 # Default options for ARGV, which never appear in option summary.
699 #
700 Officious = {}
701
702 #
703 # --help
704 # Shows option summary.
705 #
706 Officious['help'] = proc do |parser|
707 Switch::NoArgument.new do
708 puts parser.help
709 exit
710 end
711 end
712
713 #
714 # --version
715 # Shows version string if Version is defined.
716 #
717 Officious['version'] = proc do |parser|
718 Switch::OptionalArgument.new do |pkg|
719 if pkg
720 begin
721 require 'optparse/version'
722 rescue LoadError
723 else
724 show_version(*pkg.split(/,/)) or
725 abort("#{parser.program_name}: no version found in package #{pkg}")
726 exit
727 end
728 end
729 v = parser.ver or abort("#{parser.program_name}: version unknown")
730 puts v
731 exit
732 end
733 end
734
735 # :startdoc:
736
737 #
738 # Class methods
739 #
740
741 #
742 # Initializes a new instance and evaluates the optional block in context
743 # of the instance. Arguments +args+ are passed to #new, see there for
744 # description of parameters.
745 #
746 # This method is *deprecated*, its behavior corresponds to the older #new
747 # method.
748 #
749 def self.with(*args, &block)
750 opts = new(*args)
751 opts.instance_eval(&block)
752 opts
753 end
754
755 #
756 # Returns an incremented value of +default+ according to +arg+.
757 #
758 def self.inc(arg, default = nil)
759 case arg
760 when Integer
761 arg.nonzero?
762 when nil
763 default.to_i + 1
764 end
765 end
766 def inc(*args)
767 self.class.inc(*args)
768 end
769
770 #
771 # Initializes the instance and yields itself if called with a block.
772 #
773 # +banner+:: Banner message.
774 # +width+:: Summary width.
775 # +indent+:: Summary indent.
776 #
777 def initialize(banner = nil, width = 32, indent = ' ' * 4)
778 @stack = [DefaultList, List.new, List.new]
779 @program_name = nil
780 @banner = banner
781 @summary_width = width
782 @summary_indent = indent
783 @default_argv = ARGV
784 add_officious
785 yield self if block_given?
786 end
787
788 def add_officious # :nodoc:
789 list = base()
790 Officious.each do |opt, block|
791 list.long[opt] ||= block.call(self)
792 end
793 end
794
795 #
796 # Terminates option parsing. Optional parameter +arg+ is a string pushed
797 # back to be the first non-option argument.
798 #
799 def terminate(arg = nil)
800 self.class.terminate(arg)
801 end
802 def self.terminate(arg = nil)
803 throw :terminate, arg
804 end
805
806 @stack = [DefaultList]
807 def self.top() DefaultList end
808
809 #
810 # Directs to accept specified class +t+. The argument string is passed to
811 # the block in which it should be converted to the desired class.
812 #
813 # +t+:: Argument class specifier, any object including Class.
814 # +pat+:: Pattern for argument, defaults to +t+ if it responds to match.
815 #
816 # accept(t, pat, &block)
817 #
818 def accept(*args, &blk) top.accept(*args, &blk) end
819 #
820 # See #accept.
821 #
822 def self.accept(*args, &blk) top.accept(*args, &blk) end
823
824 #
825 # Directs to reject specified class argument.
826 #
827 # +t+:: Argument class speficier, any object including Class.
828 #
829 # reject(t)
830 #
831 def reject(*args, &blk) top.reject(*args, &blk) end
832 #
833 # See #reject.
834 #
835 def self.reject(*args, &blk) top.reject(*args, &blk) end
836
837 #
838 # Instance methods
839 #
840
841 # Heading banner preceding summary.
842 attr_writer :banner
843
844 # Program name to be emitted in error message and default banner,
845 # defaults to $0.
846 attr_writer :program_name
847
848 # Width for option list portion of summary. Must be Numeric.
849 attr_accessor :summary_width
850
851 # Indentation for summary. Must be String (or have + String method).
852 attr_accessor :summary_indent
853
854 # Strings to be parsed in default.
855 attr_accessor :default_argv
856
857 #
858 # Heading banner preceding summary.
859 #
860 def banner
861 unless @banner
862 @banner = "Usage: #{program_name} [options]"
863 visit(:add_banner, @banner)
864 end
865 @banner
866 end
867
868 #
869 # Program name to be emitted in error message and default banner, defaults
870 # to $0.
871 #
872 def program_name
873 @program_name || File.basename($0, '.*')
874 end
875
876 # for experimental cascading :-)
877 alias set_banner banner=
878 alias set_program_name program_name=
879 alias set_summary_width summary_width=
880 alias set_summary_indent summary_indent=
881
882 # Version
883 attr_writer :version
884 # Release code
885 attr_writer :release
886
887 #
888 # Version
889 #
890 def version
891 @version || (defined?(::Version) && ::Version)
892 end
893
894 #
895 # Release code
896 #
897 def release
898 @release || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE)
899 end
900
901 #
902 # Returns version string from program_name, version and release.
903 #
904 def ver
905 if v = version
906 str = "#{program_name} #{[v].join('.')}"
907 str << " (#{v})" if v = release
908 str
909 end
910 end
911
912 def warn(mesg = $!)
913 super("#{program_name}: #{mesg}")
914 end
915
916 def abort(mesg = $!)
917 super("#{program_name}: #{mesg}")
918 end
919
920 #
921 # Subject of #on / #on_head, #accept / #reject
922 #
923 def top
924 @stack[-1]
925 end
926
927 #
928 # Subject of #on_tail.
929 #
930 def base
931 @stack[1]
932 end
933
934 #
935 # Pushes a new List.
936 #
937 def new
938 @stack.push(List.new)
939 if block_given?
940 yield self
941 else
942 self
943 end
944 end
945
946 #
947 # Removes the last List.
948 #
949 def remove
950 @stack.pop
951 end
952
953 #
954 # Puts option summary into +to+ and returns +to+. Yields each line if
955 # a block is given.
956 #
957 # +to+:: Output destination, which must have method <<. Defaults to [].
958 # +width+:: Width of left side, defaults to @summary_width.
959 # +max+:: Maximum length allowed for left side, defaults to +width+ - 1.
960 # +indent+:: Indentation, defaults to @summary_indent.
961 #
962 def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
963 visit(:summarize, {}, {}, width, max, indent, &(blk || proc {|l| to << l + $/}))
964 to
965 end
966
967 #
968 # Returns option summary string.
969 #
970 def help; summarize(banner.to_s.sub(/\n?\z/, "\n")) end
971 alias to_s help
972
973 #
974 # Returns option summary list.
975 #
976 def to_a; summarize(banner.to_a.dup) end
977
978 #
979 # Checks if an argument is given twice, in which case an ArgumentError is
980 # raised. Called from OptionParser#switch only.
981 #
982 # +obj+:: New argument.
983 # +prv+:: Previously specified argument.
984 # +msg+:: Exception message.
985 #
986 def notwice(obj, prv, msg)
987 unless !prv or prv == obj
988 begin
989 raise ArgumentError, "argument #{msg} given twice: #{obj}"
990 rescue
991 $@[0, 2] = nil
992 raise
993 end
994 end
995 obj
996 end
997 private :notwice
998
999 #
1000 # Creates an OptionParser::Switch from the parameters. The parsed argument
1001 # value is passed to the given block, where it can be processed.
1002 #
1003 # See at the beginning of OptionParser for some full examples.
1004 #
1005 # +opts+ can include the following elements:
1006 #
1007 # [Argument style:]
1008 # One of the following:
1009 # :NONE, :REQUIRED, :OPTIONAL
1010 #
1011 # [Argument pattern:]
1012 # Acceptable option argument format, must be pre-defined with
1013 # OptionParser.accept or OptionParser#accept, or Regexp. This can appear
1014 # once or assigned as String if not present, otherwise causes an
1015 # ArgumentError. Examples:
1016 # Float, Time, Array
1017 #
1018 # [Possible argument values:]
1019 # Hash or Array.
1020 # [:text, :binary, :auto]
1021 # %w[iso-2022-jp shift_jis euc-jp utf8 binary]
1022 # { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
1023 #
1024 # [Long style switch:]
1025 # Specifies a long style switch which takes a mandatory, optional or no
1026 # argument. It's a string of the following form:
1027 # "--switch=MANDATORY" or "--switch MANDATORY"
1028 # "--switch[=OPTIONAL]"
1029 # "--switch"
1030 #
1031 # [Short style switch:]
1032 # Specifies short style switch which takes a mandatory, optional or no
1033 # argument. It's a string of the following form:
1034 # "-xMANDATORY"
1035 # "-x[OPTIONAL]"
1036 # "-x"
1037 # There is also a special form which matches character range (not full
1038 # set of regural expression):
1039 # "-[a-z]MANDATORY"
1040 # "-[a-z][OPTIONAL]"
1041 # "-[a-z]"
1042 #
1043 # [Argument style and description:]
1044 # Instead of specifying mandatory or optional orguments directly in the
1045 # switch parameter, this separate parameter can be used.
1046 # "=MANDATORY"
1047 # "=[OPTIONAL]"
1048 #
1049 # [Description:]
1050 # Description string for the option.
1051 # "Run verbosely"
1052 #
1053 # [Handler:]
1054 # Handler for the parsed argument value. Either give a block or pass a
1055 # Proc or Method as an argument.
1056 #
1057 def make_switch(opts, block = nil)
1058 short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
1059 ldesc, sdesc, desc, arg = [], [], []
1060 default_style = Switch::NoArgument
1061 default_pattern = nil
1062 klass = nil
1063 o = nil
1064 n, q, a = nil
1065
1066 opts.each do |o|
1067 # argument class
1068 next if search(:atype, o) do |pat, c|
1069 klass = notwice(o, klass, 'type')
1070 if not_style and not_style != Switch::NoArgument
1071 not_pattern, not_conv = pat, c
1072 else
1073 default_pattern, conv = pat, c
1074 end
1075 end
1076
1077 # directly specified pattern(any object possible to match)
1078 if !(String === o) and o.respond_to?(:match)
1079 pattern = notwice(o, pattern, 'pattern')
1080 conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
1081 next
1082 end
1083
1084 # anything others
1085 case o
1086 when Proc, Method
1087 block = notwice(o, block, 'block')
1088 when Array, Hash
1089 case pattern
1090 when CompletingHash
1091 when nil
1092 pattern = CompletingHash.new
1093 conv = (pattern.method(:convert).to_proc if pattern.respond_to?(:convert))
1094 else
1095 raise ArgumentError, "argument pattern given twice"
1096 end
1097 o.each {|(o, *v)| pattern[o] = v.fetch(0) {o}}
1098 when Module
1099 raise ArgumentError, "unsupported argument type: #{o}"
1100 when *ArgumentStyle.keys
1101 style = notwice(ArgumentStyle[o], style, 'style')
1102 when /^--no-([^\[\]=\s]*)(.+)?/
1103 q, a = $1, $2
1104 o = notwice(a ? Object : TrueClass, klass, 'type')
1105 not_pattern, not_conv = search(:atype, o) unless not_style
1106 not_style = (not_style || default_style).guess(arg = a) if a
1107 default_style = Switch::NoArgument
1108 default_pattern, conv = search(:atype, FalseClass) unless default_pattern
1109 ldesc << "--no-#{q}"
1110 long << 'no-' + (q = q.downcase)
1111 nolong << q
1112 when /^--\[no-\]([^\[\]=\s]*)(.+)?/
1113 q, a = $1, $2
1114 o = notwice(a ? Object : TrueClass, klass, 'type')
1115 if a
1116 default_style = default_style.guess(arg = a)
1117 default_pattern, conv = search(:atype, o) unless default_pattern
1118 end
1119 ldesc << "--[no-]#{q}"
1120 long << (o = q.downcase)
1121 not_pattern, not_conv = search(:atype, FalseClass) unless not_style
1122 not_style = Switch::NoArgument
1123 nolong << 'no-' + o
1124 when /^--([^\[\]=\s]*)(.+)?/
1125 q, a = $1, $2
1126 if a
1127 o = notwice(NilClass, klass, 'type')
1128 default_style = default_style.guess(arg = a)
1129 default_pattern, conv = search(:atype, o) unless default_pattern
1130 end
1131 ldesc << "--#{q}"
1132 long << (o = q.downcase)
1133 when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
1134 q, a = $1, $2
1135 o = notwice(Object, klass, 'type')
1136 if a
1137 default_style = default_style.guess(arg = a)
1138 default_pattern, conv = search(:atype, o) unless default_pattern
1139 end
1140 sdesc << "-#{q}"
1141 short << Regexp.new(q)
1142 when /^-(.)(.+)?/
1143 q, a = $1, $2
1144 if a
1145 o = notwice(NilClass, klass, 'type')
1146 default_style = default_style.guess(arg = a)
1147 default_pattern, conv = search(:atype, o) unless default_pattern
1148 end
1149 sdesc << "-#{q}"
1150 short << q
1151 when /^=/
1152 style = notwice(default_style.guess(arg = o), style, 'style')
1153 default_pattern, conv = search(:atype, Object) unless default_pattern
1154 else
1155 desc.push(o)
1156 end
1157 end
1158
1159 default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
1160 if !(short.empty? and long.empty?)
1161 s = (style || default_style).new(pattern || default_pattern,
1162 conv, sdesc, ldesc, arg, desc, block)
1163 elsif !block
1164 raise ArgumentError, "no switch given" if style or pattern
1165 s = desc
1166 else
1167 short << pattern
1168 s = (style || default_style).new(pattern,
1169 conv, nil, nil, arg, desc, block)
1170 end
1171 return s, short, long,
1172 (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
1173 nolong
1174 end
1175
1176 def define(*opts, &block)
1177 top.append(*(sw = make_switch(opts, block)))
1178 sw[0]
1179 end
1180
1181 #
1182 # Add option switch and handler. See #make_switch for an explanation of
1183 # parameters.
1184 #
1185 def on(*opts, &block)
1186 define(*opts, &block)
1187 self
1188 end
1189 alias def_option define
1190
1191 def define_head(*opts, &block)
1192 top.prepend(*(sw = make_switch(opts, block)))
1193 sw[0]
1194 end
1195
1196 #
1197 # Add option switch like with #on, but at head of summary.
1198 #
1199 def on_head(*opts, &block)
1200 define_head(*opts, &block)
1201 self
1202 end
1203 alias def_head_option define_head
1204
1205 def define_tail(*opts, &block)
1206 base.append(*(sw = make_switch(opts, block)))
1207 sw[0]
1208 end
1209
1210 #
1211 # Add option switch like with #on, but at tail of summary.
1212 #
1213 def on_tail(*opts, &block)
1214 define_tail(*opts, &block)
1215 self
1216 end
1217 alias def_tail_option define_tail
1218
1219 #
1220 # Add separator in summary.
1221 #
1222 def separator(string)
1223 top.append(string, nil, nil)
1224 end
1225
1226 #
1227 # Parses command line arguments +argv+ in order. When a block is given,
1228 # each non-option argument is yielded.
1229 #
1230 # Returns the rest of +argv+ left unparsed.
1231 #
1232 def order(*argv, &block)
1233 argv = argv[0].dup if argv.size == 1 and Array === argv[0]
1234 order!(argv, &block)
1235 end
1236
1237 #
1238 # Same as #order, but removes switches destructively.
1239 #
1240 def order!(argv = default_argv, &nonopt)
1241 parse_in_order(argv, &nonopt)
1242 end
1243
1244 def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
1245 opt, arg, sw, val, rest = nil
1246 nonopt ||= proc {|arg| throw :terminate, arg}
1247 argv.unshift(arg) if arg = catch(:terminate) {
1248 while arg = argv.shift
1249 case arg
1250 # long option
1251 when /\A--([^=]*)(?:=(.*))?/nm
1252 opt, rest = $1, $2
1253 begin
1254 sw, = complete(:long, opt, true)
1255 rescue ParseError
1256 raise $!.set_option(arg, true)
1257 end
1258 begin
1259 opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
1260 val = cb.call(val) if cb
1261 setter.call(sw.switch_name, val) if setter
1262 rescue ParseError
1263 raise $!.set_option(arg, rest)
1264 end
1265
1266 # short option
1267 when /\A-(.)((=).*|.+)?/nm
1268 opt, has_arg, eq, val, rest = $1, $3, $3, $2, $2
1269 begin
1270 sw, = search(:short, opt)
1271 unless sw
1272 begin
1273 sw, = complete(:short, opt)
1274 # short option matched.
1275 val = arg.sub(/\A-/, '')
1276 has_arg = true
1277 rescue InvalidOption
1278 # if no short options match, try completion with long
1279 # options.
1280 sw, = complete(:long, opt)
1281 eq ||= !rest
1282 end
1283 end
1284 rescue ParseError
1285 raise $!.set_option(arg, true)
1286 end
1287 begin
1288 opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
1289 raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
1290 argv.unshift(opt) if opt and (opt = opt.sub(/\A-*/, '-')) != '-'
1291 val = cb.call(val) if cb
1292 setter.call(sw.switch_name, val) if setter
1293 rescue ParseError
1294 raise $!.set_option(arg, arg.length > 2)
1295 end
1296
1297 # non-option argument
1298 else
1299 catch(:prune) do
1300 visit(:each_option) do |sw|
1301 sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg)
1302 end
1303 nonopt.call(arg)
1304 end
1305 end
1306 end
1307
1308 nil
1309 }
1310
1311 visit(:search, :short, nil) {|sw| sw.block.call(*argv) if !sw.pattern}
1312
1313 argv
1314 end
1315 private :parse_in_order
1316
1317 #
1318 # Parses command line arguments +argv+ in permutation mode and returns
1319 # list of non-option arguments.
1320 #
1321 def permute(*argv)
1322 argv = argv[0].dup if argv.size == 1 and Array === argv[0]
1323 permute!(argv)
1324 end
1325
1326 #
1327 # Same as #permute, but removes switches destructively.
1328 #
1329 def permute!(argv = default_argv)
1330 nonopts = []
1331 arg = nil
1332 order!(argv) {|arg| nonopts << arg}
1333 argv[0, 0] = nonopts
1334 argv
1335 end
1336
1337 #
1338 # Parses command line arguments +argv+ in order when environment variable
1339 # POSIXLY_CORRECT is set, and in permutation mode otherwise.
1340 #
1341 def parse(*argv)
1342 argv = argv[0].dup if argv.size == 1 and Array === argv[0]
1343 parse!(argv)
1344 end
1345
1346 #
1347 # Same as #parse, but removes switches destructively.
1348 #
1349 def parse!(argv = default_argv)
1350 if ENV.include?('POSIXLY_CORRECT')
1351 order!(argv)
1352 else
1353 permute!(argv)
1354 end
1355 end
1356
1357 #
1358 # Wrapper method for getopts.rb.
1359 #
1360 # params = ARGV.getopts("ab:", "foo", "bar:")
1361 # # params[:a] = true # -a
1362 # # params[:b] = "1" # -b1
1363 # # params[:foo] = "1" # --foo
1364 # # params[:bar] = "x" # --bar x
1365 #
1366 def getopts(*args)
1367 argv = Array === args.first ? args.shift : default_argv
1368 single_options, *long_options = *args
1369
1370 result = {}
1371
1372 single_options.scan(/(.)(:)?/) do |opt, val|
1373 if val
1374 result[opt] = nil
1375 define("-#{opt} VAL")
1376 else
1377 result[opt] = false
1378 define("-#{opt}")
1379 end
1380 end if single_options
1381
1382 long_options.each do |arg|
1383 opt, val = arg.split(':', 2)
1384 if val
1385 result[opt] = val.empty? ? nil : val
1386 define("--#{opt} VAL")
1387 else
1388 result[opt] = false
1389 define("--#{opt}")
1390 end
1391 end
1392
1393 parse_in_order(argv, result.method(:[]=))
1394 result
1395 end
1396
1397 #
1398 # See #getopts.
1399 #
1400 def self.getopts(*args)
1401 new.getopts(*args)
1402 end
1403
1404 #
1405 # Traverses @stack, sending each element method +id+ with +args+ and
1406 # +block+.
1407 #
1408 def visit(id, *args, &block)
1409 el = nil
1410 @stack.reverse_each do |el|
1411 el.send(id, *args, &block)
1412 end
1413 nil
1414 end
1415 private :visit
1416
1417 #
1418 # Searches +key+ in @stack for +id+ hash and returns or yields the result.
1419 #
1420 def search(id, key)
1421 block_given = block_given?
1422 visit(:search, id, key) do |k|
1423 return block_given ? yield(k) : k
1424 end
1425 end
1426 private :search
1427
1428 #
1429 # Completes shortened long style option switch and returns pair of
1430 # canonical switch and switch descriptor OptionParser::Switch.
1431 #
1432 # +id+:: Searching table.
1433 # +opt+:: Searching key.
1434 # +icase+:: Search case insensitive if true.
1435 # +pat+:: Optional pattern for completion.
1436 #
1437 def complete(typ, opt, icase = false, *pat)
1438 if pat.empty?
1439 search(typ, opt) {|sw| return [sw, opt]} # exact match or...
1440 end
1441 raise AmbiguousOption, catch(:ambiguous) {
1442 visit(:complete, typ, opt, icase, *pat) {|opt, *sw| return sw}
1443 raise InvalidOption, opt
1444 }
1445 end
1446 private :complete
1447
1448 #
1449 # Loads options from file names as +filename+. Does nothing when the file
1450 # is not present. Returns whether successfully loaded.
1451 #
1452 # +filename+ defaults to basename of the program without suffix in a
1453 # directory ~/.options.
1454 #
1455 def load(filename = nil)
1456 begin
1457 filename ||= File.expand_path(File.basename($0, '.*'), '~/.options')
1458 rescue
1459 return false
1460 end
1461 begin
1462 parse(*IO.readlines(filename).each {|s| s.chomp!})
1463 true
1464 rescue Errno::ENOENT, Errno::ENOTDIR
1465 false
1466 end
1467 end
1468
1469 #
1470 # Parses environment variable +env+ or its uppercase with splitting like a
1471 # shell.
1472 #
1473 # +env+ defaults to the basename of the program.
1474 #
1475 def environment(env = File.basename($0, '.*'))
1476 env = ENV[env] || ENV[env.upcase] or return
1477 parse(*Shellwords.shellwords(env))
1478 end
1479
1480 #
1481 # Acceptable argument classes
1482 #
1483
1484 #
1485 # Any string and no conversion. This is fall-back.
1486 #
1487 accept(Object) {|s,|s or s.nil?}
1488
1489 accept(NilClass) {|s,|s}
1490
1491 #
1492 # Any non-empty string, and no conversion.
1493 #
1494 accept(String, /.+/nm) {|s,*|s}
1495
1496 #
1497 # Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal
1498 # for 0x, and decimal for others; with optional sign prefix. Converts to
1499 # Integer.
1500 #
1501 decimal = '\d+(?:_\d+)*'
1502 binary = 'b[01]+(?:_[01]+)*'
1503 hex = 'x[\da-f]+(?:_[\da-f]+)*'
1504 octal = "0(?:[0-7]*(?:_[0-7]+)*|#{binary}|#{hex})"
1505 integer = "#{octal}|#{decimal}"
1506 accept(Integer, %r"\A[-+]?(?:#{integer})"io) {|s,| Integer(s) if s}
1507
1508 #
1509 # Float number format, and converts to Float.
1510 #
1511 float = "(?:#{decimal}(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?"
1512 floatpat = %r"\A[-+]?#{float}"io
1513 accept(Float, floatpat) {|s,| s.to_f if s}
1514
1515 #
1516 # Generic numeric format, converts to Integer for integer format, Float
1517 # for float format.
1518 #
1519 accept(Numeric, %r"\A[-+]?(?:#{octal}|#{float})"io) {|s,| eval(s) if s}
1520
1521 #
1522 # Decimal integer format, to be converted to Integer.
1523 #
1524 DecimalInteger = /\A[-+]?#{decimal}/io
1525 accept(DecimalInteger) {|s,| s.to_i if s}
1526
1527 #
1528 # Ruby/C like octal/hexadecimal/binary integer format, to be converted to
1529 # Integer.
1530 #
1531 OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))/io
1532 accept(OctalInteger) {|s,| s.oct if s}
1533
1534 #
1535 # Decimal integer/float number format, to be converted to Integer for
1536 # integer format, Float for float format.
1537 #
1538 DecimalNumeric = floatpat # decimal integer is allowed as float also.
1539 accept(DecimalNumeric) {|s,| eval(s) if s}
1540
1541 #
1542 # Boolean switch, which means whether it is present or not, whether it is
1543 # absent or not with prefix no-, or it takes an argument
1544 # yes/no/true/false/+/-.
1545 #
1546 yesno = CompletingHash.new
1547 %w[- no false].each {|el| yesno[el] = false}
1548 %w[+ yes true].each {|el| yesno[el] = true}
1549 yesno['nil'] = false # shoud be nil?
1550 accept(TrueClass, yesno) {|arg, val| val == nil or val}
1551 #
1552 # Similar to TrueClass, but defaults to false.
1553 #
1554 accept(FalseClass, yesno) {|arg, val| val != nil and val}
1555
1556 #
1557 # List of strings separated by ",".
1558 #
1559 accept(Array) do |s,|
1560 if s
1561 s = s.split(',').collect {|s| s unless s.empty?}
1562 end
1563 s
1564 end
1565
1566 #
1567 # Regular expression with options.
1568 #
1569 accept(Regexp, %r"\A/((?:\\.|[^\\])*)/([[:alpha:]]+)?\z|.*") do |all, s, o|
1570 f = 0
1571 if o
1572 f |= Regexp::IGNORECASE if /i/ =~ o
1573 f |= Regexp::MULTILINE if /m/ =~ o
1574 f |= Regexp::EXTENDED if /x/ =~ o
1575 k = o.delete("^imx")
1576 end
1577 Regexp.new(s || all, f, k)
1578 end
1579
1580 #
1581 # Exceptions
1582 #
1583
1584 #
1585 # Base class of exceptions from OptionParser.
1586 #
1587 class ParseError < RuntimeError
1588 # Reason which caused the error.
1589 Reason = 'parse error'.freeze
1590
1591 def initialize(*args)
1592 @args = args
1593 @reason = nil
1594 end
1595
1596 attr_reader :args
1597 attr_writer :reason
1598
1599 #
1600 # Pushes back erred argument(s) to +argv+.
1601 #
1602 def recover(argv)
1603 argv[0, 0] = @args
1604 argv
1605 end
1606
1607 def set_option(opt, eq)
1608 if eq
1609 @args[0] = opt
1610 else
1611 @args.unshift(opt)
1612 end
1613 self
1614 end
1615
1616 #
1617 # Returns error reason. Override this for I18N.
1618 #
1619 def reason
1620 @reason || self.class::Reason
1621 end
1622
1623 def inspect
1624 "#<#{self.class.to_s}: #{args.join(' ')}>"
1625 end
1626
1627 #
1628 # Default stringizing method to emit standard error message.
1629 #
1630 def message
1631 reason + ': ' + args.join(' ')
1632 end
1633
1634 alias to_s message
1635 end
1636
1637 #
1638 # Raises when ambiguously completable string is encountered.
1639 #
1640 class AmbiguousOption < ParseError
1641 const_set(:Reason, 'ambiguous option'.freeze)
1642 end
1643
1644 #
1645 # Raises when there is an argument for a switch which takes no argument.
1646 #
1647 class NeedlessArgument < ParseError
1648 const_set(:Reason, 'needless argument'.freeze)
1649 end
1650
1651 #
1652 # Raises when a switch with mandatory argument has no argument.
1653 #
1654 class MissingArgument < ParseError
1655 const_set(:Reason, 'missing argument'.freeze)
1656 end
1657
1658 #
1659 # Raises when switch is undefined.
1660 #
1661 class InvalidOption < ParseError
1662 const_set(:Reason, 'invalid option'.freeze)
1663 end
1664
1665 #
1666 # Raises when the given argument does not match required format.
1667 #
1668 class InvalidArgument < ParseError
1669 const_set(:Reason, 'invalid argument'.freeze)
1670 end
1671
1672 #
1673 # Raises when the given argument word can't be completed uniquely.
1674 #
1675 class AmbiguousArgument < InvalidArgument
1676 const_set(:Reason, 'ambiguous argument'.freeze)
1677 end
1678
1679 #
1680 # Miscellaneous
1681 #
1682
1683 #
1684 # Extends command line arguments array (ARGV) to parse itself.
1685 #
1686 module Arguable
1687
1688 #
1689 # Sets OptionParser object, when +opt+ is +false+ or +nil+, methods
1690 # OptionParser::Arguable#options and OptionParser::Arguable#options= are
1691 # undefined. Thus, there is no ways to access the OptionParser object
1692 # via the receiver object.
1693 #
1694 def options=(opt)
1695 unless @optparse = opt
1696 class << self
1697 undef_method(:options)
1698 undef_method(:options=)
1699 end
1700 end
1701 end
1702
1703 #
1704 # Actual OptionParser object, automatically created if nonexistent.
1705 #
1706 # If called with a block, yields the OptionParser object and returns the
1707 # result of the block. If an OptionParser::ParseError exception occurs
1708 # in the block, it is rescued, a error message printed to STDERR and
1709 # +nil+ returned.
1710 #
1711 def options
1712 @optparse ||= OptionParser.new
1713 @optparse.default_argv = self
1714 block_given? or return @optparse
1715 begin
1716 yield @optparse
1717 rescue ParseError
1718 @optparse.warn $!
1719 nil
1720 end
1721 end
1722
1723 #
1724 # Parses +self+ destructively in order and returns +self+ containing the
1725 # rest arguments left unparsed.
1726 #
1727 def order!(&blk) options.order!(self, &blk) end
1728
1729 #
1730 # Parses +self+ destructively in permutation mode and returns +self+
1731 # containing the rest arguments left unparsed.
1732 #
1733 def permute!() options.permute!(self) end
1734
1735 #
1736 # Parses +self+ destructively and returns +self+ containing the
1737 # rest arguments left unparsed.
1738 #
1739 def parse!() options.parse!(self) end
1740
1741 #
1742 # Substitution of getopts is possible as follows. Also see
1743 # OptionParser#getopts.
1744 #
1745 # def getopts(*args)
1746 # ($OPT = ARGV.getopts(*args)).each do |opt, val|
1747 # eval "$OPT_#{opt.gsub(/[^A-Za-z0-9_]/, '_')} = val"
1748 # end
1749 # rescue OptionParser::ParseError
1750 # end
1751 #
1752 def getopts(*args)
1753 options.getopts(self, *args)
1754 end
1755
1756 #
1757 # Initializes instance variable.
1758 #
1759 def self.extend_object(obj)
1760 super
1761 obj.instance_eval {@optparse = nil}
1762 end
1763 def initialize(*args)
1764 super
1765 @optparse = nil
1766 end
1767 end
1768
1769 #
1770 # Acceptable argument classes. Now contains DecimalInteger, OctalInteger
1771 # and DecimalNumeric. See Acceptable argument classes (in source code).
1772 #
1773 module Acceptables
1774 const_set(:DecimalInteger, OptionParser::DecimalInteger)
1775 const_set(:OctalInteger, OptionParser::OctalInteger)
1776 const_set(:DecimalNumeric, OptionParser::DecimalNumeric)
1777 end
1778end
1779
1780# ARGV is arguable by OptionParser
1781ARGV.extend(OptionParser::Arguable)
1782
1783if $0 == __FILE__
1784 Version = OptionParser::Version
1785 ARGV.options {|q|
1786 q.parse!.empty? or puts "what's #{ARGV.join(' ')}?"
1787 } or abort(ARGV.options.to_s)
1788end
Note: See TracBrowser for help on using the repository browser.