4 # Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara.
6 # You may redistribute and/or modify this library under the same license
9 # See GetoptLong for documentation.
11 # Additional documents and the latest version of `getoptlong.rb' can be
12 # found at http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
14 # The GetoptLong class allows you to parse command line options similarly to
15 # the GNU getopt_long() C library call. Note, however, that GetoptLong is a
16 # pure Ruby implementation.
18 # GetoptLong allows for POSIX-style options like <tt>--file</tt> as well
19 # as single letter options like <tt>-f</tt>
21 # The empty option <tt>--</tt> (two minus symbols) is used to end option
22 # processing. This can be particularly important if options have optional
25 # Here is a simple example of usage:
29 # # hello: greets user, demonstrates command line parsing
33 # # hello [OPTION] ... DIR
42 # # greet user by name, if name not supplied default is John
44 # # DIR: The directory in which to issue the greeting.
46 # require 'getoptlong'
47 # require 'rdoc/usage'
49 # opts = GetoptLong.new(
50 # [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
51 # [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
52 # [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
58 # opts.each do |opt, arg|
63 # repetitions = arg.to_i
74 # puts "Missing dir argument (try --help)"
81 # for i in (1..repetitions)
89 # Example command line:
91 # hello -n 6 --name -- /tmp
97 ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
102 ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
103 OPTIONAL_ARGUMENT = 2]
108 STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
113 class Error < StandardError; end
114 class AmbigousOption < Error; end
115 class NeedlessArgument < Error; end
116 class MissingArgument < Error; end
117 class InvalidOption < Error; end
120 # Set up option processing.
122 # The options to support are passed to new() as an array of arrays.
123 # Each sub-array contains any number of String option names which carry
124 # the same meaning, and one of the following flags:
126 # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
128 # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument.
130 # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument.
132 # The first option name is considered to be the preferred (canonical) name.
133 # Other than that, the elements of each sub-array can be in any order.
135 def initialize(*arguments)
139 if ENV.include?('POSIXLY_CORRECT')
140 @ordering = REQUIRE_ORDER
146 # Hash table of option names.
147 # Keys of the table are option names, and their values are canonical
148 # names of the options.
150 @canonical_names = Hash.new
153 # Hash table of argument flags.
154 # Keys of the table are option names, and their values are argument
155 # flags of the options.
157 @argument_flags = Hash.new
160 # Whether error messages are output to $stderr.
180 # Rest of catenated short options.
185 # List of non-option-arguments.
186 # Append them to ARGV when option processing is terminated.
188 @non_option_arguments = Array.new
190 if 0 < arguments.length
191 set_options(*arguments)
196 # Set the handling of the ordering of options and arguments.
197 # A RuntimeError is raised if option processing has already started.
199 # The supplied value must be a member of GetoptLong::ORDERINGS. It alters
200 # the processing of options as follows:
202 # <b>REQUIRE_ORDER</b> :
204 # Options are required to occur before non-options.
206 # Processing of options ends as soon as a word is encountered that has not
207 # been preceded by an appropriate option flag.
209 # For example, if -a and -b are options which do not take arguments,
210 # parsing command line arguments of '-a one -b two' would result in
211 # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being
212 # processed as an option/arg pair.
214 # This is the default ordering, if the environment variable
215 # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
219 # Options can occur anywhere in the command line parsed. This is the
222 # Every sequence of words which can be interpreted as an option (with or
223 # without argument) is treated as an option; non-option words are skipped.
225 # For example, if -a does not require an argument and -b optionally takes
226 # an argument, parsing '-a one -b two three' would result in ('-a','') and
227 # ('-b', 'two') being processed as option/arg pairs, and 'one','three'
228 # being left in ARGV.
230 # If the ordering is set to PERMUTE but the environment variable
231 # POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for
232 # compatibility with GNU getopt_long.
234 # <b>RETURN_IN_ORDER</b> :
236 # All words on the command line are processed as options. Words not
237 # preceded by a short or long option flag are passed as arguments
238 # with an option of '' (empty string).
240 # For example, if -a requires an argument but -b does not, a command line
241 # of '-a one -b two three' would result in option/arg pairs of ('-a', 'one')
242 # ('-b', ''), ('', 'two'), ('', 'three') being processed.
244 def ordering=(ordering)
246 # The method is failed if option processing has already started.
248 if @status != STATUS_YET
249 set_error(ArgumentError, "argument error")
251 "invoke ordering=, but option processing has already started"
257 if !ORDERINGS.include?(ordering)
258 raise ArgumentError, "invalid ordering `#{ordering}'"
260 if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
261 @ordering = REQUIRE_ORDER
270 attr_reader :ordering
273 # Set options. Takes the same argument as GetoptLong.new.
275 # Raises a RuntimeError if option processing has already started.
277 def set_options(*arguments)
279 # The method is failed if option processing has already started.
281 if @status != STATUS_YET
283 "invoke set_options, but option processing has already started"
287 # Clear tables of option names and argument flags.
289 @canonical_names.clear
290 @argument_flags.clear
292 arguments.each do |arg|
294 # Each argument must be an Array.
297 raise ArgumentError, "the option list contains non-Array argument"
301 # Find an argument flag and it set to `argument_flag'.
305 if ARGUMENT_FLAGS.include?(i)
306 if argument_flag != nil
307 raise ArgumentError, "too many argument-flags"
312 raise ArgumentError, "no argument-flag" if argument_flag == nil
317 # Check an option name.
319 next if i == argument_flag
321 if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
322 raise ArgumentError, "an invalid option `#{i}'"
324 if (@canonical_names.include?(i))
325 raise ArgumentError, "option redefined `#{i}'"
328 @canonical_names.clear
329 @argument_flags.clear
334 # Register the option (`i') to the `@canonical_names' and
335 # `@canonical_names' Hashes.
337 if canonical_name == nil
340 @canonical_names[i] = canonical_name
341 @argument_flags[i] = argument_flag
343 raise ArgumentError, "no option name" if canonical_name == nil
349 # Set/Unset `quiet' mode.
354 # Return the flag of `quiet' mode.
359 # `quiet?' is an alias of `quiet'.
364 # Explicitly terminate option processing.
367 return nil if @status == STATUS_TERMINATED
368 raise RuntimeError, "an error has occured" if @error != nil
370 @status = STATUS_TERMINATED
371 @non_option_arguments.reverse_each do |argument|
372 ARGV.unshift(argument)
375 @canonical_names = nil
376 @argument_flags = nil
378 @non_option_arguments = nil
384 # Returns true if option processing has terminated, false otherwise.
387 return @status == STATUS_TERMINATED
391 # Set an error (protected).
393 def set_error(type, message)
394 $stderr.print("#{$0}: #{message}\n") if !@quiet
397 @error_message = message
398 @canonical_names = nil
399 @argument_flags = nil
401 @non_option_arguments = nil
408 # Examine whether an option processing is failed.
413 # `error?' is an alias of `error'.
417 # Return the appropriate error message in POSIX-defined format.
418 # If no error has occurred, returns nil.
421 return @error_message
425 # Get next option name and its argument, as an Array of two elements.
427 # The option name is always converted to the first (preferred)
428 # name given in the original options to GetoptLong.new.
430 # Example: ['--option', 'value']
432 # Returns nil if the processing is complete (as determined by
433 # STATUS_TERMINATED).
436 option_name, option_argument = nil, ''
441 return nil if @error != nil
444 @status = STATUS_STARTED
445 when STATUS_TERMINATED
450 # Get next option argument.
452 if 0 < @rest_singles.length
453 argument = '-' + @rest_singles
454 elsif (ARGV.length == 0)
457 elsif @ordering == PERMUTE
458 while 0 < ARGV.length && ARGV[0] !~ /^-./
459 @non_option_arguments.push(ARGV.shift)
465 argument = ARGV.shift
466 elsif @ordering == REQUIRE_ORDER
467 if (ARGV[0] !~ /^-./)
471 argument = ARGV.shift
473 argument = ARGV.shift
477 # Check the special argument `--'.
478 # `--' indicates the end of the option list.
480 if argument == '--' && @rest_singles.length == 0
486 # Check for long and short options.
488 if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0
490 # This is a long style option, which start with `--'.
493 if @canonical_names.include?(pattern)
494 option_name = pattern
497 # The option `option_name' is not registered in `@canonical_names'.
498 # It may be an abbreviated.
501 @canonical_names.each_key do |key|
502 if key.index(pattern) == 0
508 set_error(AmbigousOption, "option `#{argument}' is ambiguous")
509 elsif match_count == 0
510 set_error(InvalidOption, "unrecognized option `#{argument}'")
515 # Check an argument to the option.
517 if @argument_flags[option_name] == REQUIRED_ARGUMENT
518 if argument =~ /=(.*)$/
520 elsif 0 < ARGV.length
521 option_argument = ARGV.shift
523 set_error(MissingArgument,
524 "option `#{argument}' requires an argument")
526 elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
527 if argument =~ /=(.*)$/
529 elsif 0 < ARGV.length && ARGV[0] !~ /^-./
530 option_argument = ARGV.shift
534 elsif argument =~ /=(.*)$/
535 set_error(NeedlessArgument,
536 "option `#{option_name}' doesn't allow an argument")
539 elsif argument =~ /^(-(.))(.*)/
541 # This is a short style option, which start with `-' (not `--').
542 # Short options may be catenated (e.g. `-l -g' is equivalent to
545 option_name, ch, @rest_singles = $1, $2, $3
547 if @canonical_names.include?(option_name)
549 # The option `option_name' is found in `@canonical_names'.
550 # Check its argument.
552 if @argument_flags[option_name] == REQUIRED_ARGUMENT
553 if 0 < @rest_singles.length
554 option_argument = @rest_singles
556 elsif 0 < ARGV.length
557 option_argument = ARGV.shift
559 # 1003.2 specifies the format of this message.
560 set_error(MissingArgument, "option requires an argument -- #{ch}")
562 elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
563 if 0 < @rest_singles.length
564 option_argument = @rest_singles
566 elsif 0 < ARGV.length && ARGV[0] !~ /^-./
567 option_argument = ARGV.shift
574 # This is an invalid option.
575 # 1003.2 specifies the format of this message.
577 if ENV.include?('POSIXLY_CORRECT')
578 set_error(InvalidOption, "illegal option -- #{ch}")
580 set_error(InvalidOption, "invalid option -- #{ch}")
585 # This is a non-option argument.
586 # Only RETURN_IN_ORDER falled into here.
591 return @canonical_names[option_name], option_argument
595 # `get_option' is an alias of `get'.
599 # Iterator version of `get'.
601 # The block is called repeatedly with two arguments:
602 # The first is the option name.
603 # The second is the argument which followed it (if any).
604 # Example: ('--opt', 'value')
606 # The option name is always converted to the first (preferred)
607 # name given in the original options to GetoptLong.new.
611 option_name, option_argument = get_option
612 break if option_name == nil
613 yield option_name, option_argument
618 # `each_option' is an alias of `each'.
620 alias each_option each