Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / getoptlong.rb
blob7732369543f746b85f3af9f16b01371cc6e9b8fb
2 # GetoptLong for Ruby
4 # Copyright (C) 1998, 1999, 2000  Motoyuki Kasahara.
6 # You may redistribute and/or modify this library under the same license
7 # terms as Ruby.
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
23 # arguments.
25 # Here is a simple example of usage:
27 #     # == Synopsis
28 #     #
29 #     # hello: greets user, demonstrates command line parsing
30 #     #
31 #     # == Usage
32 #     #
33 #     # hello [OPTION] ... DIR
34 #     #
35 #     # -h, --help:
36 #     #    show help
37 #     #
38 #     # --repeat x, -n x:
39 #     #    repeat x times
40 #     #
41 #     # --name [name]:
42 #     #    greet user by name, if name not supplied default is John
43 #     #
44 #     # DIR: The directory in which to issue the greeting.
45 #     
46 #     require 'getoptlong'
47 #     require 'rdoc/usage'
48 #     
49 #     opts = GetoptLong.new(
50 #       [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
51 #       [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
52 #       [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
53 #     )
54 #     
55 #     dir = nil
56 #     name = nil
57 #     repetitions = 1
58 #     opts.each do |opt, arg|
59 #       case opt
60 #         when '--help'
61 #           RDoc::usage
62 #         when '--repeat'
63 #           repetitions = arg.to_i
64 #         when '--name'
65 #           if arg == ''
66 #             name = 'John'
67 #           else
68 #             name = arg
69 #           end
70 #       end
71 #     end
72 #     
73 #     if ARGV.length != 1
74 #       puts "Missing dir argument (try --help)"
75 #       exit 0
76 #     end
77 #     
78 #     dir = ARGV.shift
79 #     
80 #     Dir.chdir(dir)
81 #     for i in (1..repetitions)
82 #       print "Hello"
83 #       if name
84 #         print ", #{name}"
85 #       end
86 #       puts
87 #     end
89 # Example command line:
91 #     hello -n 6 --name -- /tmp
93 class GetoptLong
94   #
95   # Orderings.
96   #
97   ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
99   #
100   # Argument flags.
101   #
102   ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
103     OPTIONAL_ARGUMENT = 2]
105   #
106   # Status codes.
107   #
108   STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
110   #
111   # Error types.
112   #
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
119   #
120   # Set up option processing.
121   #
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:
125   #
126   # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
127   #
128   # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument.
129   #
130   # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument.
131   #
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.
134   #
135   def initialize(*arguments)
136     #
137     # Current ordering.
138     #
139     if ENV.include?('POSIXLY_CORRECT')
140       @ordering = REQUIRE_ORDER
141     else
142       @ordering = PERMUTE
143     end
145     #
146     # Hash table of option names.
147     # Keys of the table are option names, and their values are canonical
148     # names of the options.
149     #
150     @canonical_names = Hash.new
152     #
153     # Hash table of argument flags.
154     # Keys of the table are option names, and their values are argument
155     # flags of the options.
156     #
157     @argument_flags = Hash.new
159     #
160     # Whether error messages are output to $stderr.
161     #
162     @quiet = FALSE
164     #
165     # Status code.
166     #
167     @status = STATUS_YET
169     #
170     # Error code.
171     #
172     @error = nil
174     #
175     # Error message.
176     #
177     @error_message = nil
179     #
180     # Rest of catenated short options.
181     #
182     @rest_singles = ''
184     #
185     # List of non-option-arguments.
186     # Append them to ARGV when option processing is terminated.
187     #
188     @non_option_arguments = Array.new
190     if 0 < arguments.length
191       set_options(*arguments)
192     end
193   end
195   #
196   # Set the handling of the ordering of options and arguments.
197   # A RuntimeError is raised if option processing has already started.
198   #
199   # The supplied value must be a member of GetoptLong::ORDERINGS. It alters
200   # the processing of options as follows:
201   #
202   # <b>REQUIRE_ORDER</b> :
203   # 
204   # Options are required to occur before non-options.
205   #
206   # Processing of options ends as soon as a word is encountered that has not
207   # been preceded by an appropriate option flag.
208   #
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.
213   #
214   # This is the default ordering, if the environment variable
215   # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
216   #
217   # <b>PERMUTE</b> :
218   #  
219   # Options can occur anywhere in the command line parsed. This is the 
220   # default behavior.
221   #
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.
224   #
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.
229   #
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.
233   #
234   # <b>RETURN_IN_ORDER</b> :
235   #
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).
239   #
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.
243   #
244   def ordering=(ordering)
245     #
246     # The method is failed if option processing has already started.
247     #
248     if @status != STATUS_YET
249       set_error(ArgumentError, "argument error")
250       raise RuntimeError,
251         "invoke ordering=, but option processing has already started"
252     end
254     #
255     # Check ordering.
256     #
257     if !ORDERINGS.include?(ordering)
258       raise ArgumentError, "invalid ordering `#{ordering}'"
259     end
260     if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
261       @ordering = REQUIRE_ORDER
262     else
263       @ordering = ordering
264     end
265   end
267   #
268   # Return ordering.
269   #
270   attr_reader :ordering
272   #
273   # Set options. Takes the same argument as GetoptLong.new.
274   #
275   # Raises a RuntimeError if option processing has already started.
276   #
277   def set_options(*arguments)
278     #
279     # The method is failed if option processing has already started.
280     #
281     if @status != STATUS_YET
282       raise RuntimeError, 
283         "invoke set_options, but option processing has already started"
284     end
286     #
287     # Clear tables of option names and argument flags.
288     #
289     @canonical_names.clear
290     @argument_flags.clear
292     arguments.each do |arg|
293       #
294       # Each argument must be an Array.
295       #
296       if !arg.is_a?(Array)
297         raise ArgumentError, "the option list contains non-Array argument"
298       end
300       #
301       # Find an argument flag and it set to `argument_flag'.
302       #
303       argument_flag = nil
304       arg.each do |i|
305         if ARGUMENT_FLAGS.include?(i)
306           if argument_flag != nil
307             raise ArgumentError, "too many argument-flags"
308           end
309           argument_flag = i
310         end
311       end
312       raise ArgumentError, "no argument-flag" if argument_flag == nil
314       canonical_name = nil
315       arg.each do |i|
316         #
317         # Check an option name.
318         #
319         next if i == argument_flag
320         begin
321           if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
322             raise ArgumentError, "an invalid option `#{i}'"
323           end
324           if (@canonical_names.include?(i))
325             raise ArgumentError, "option redefined `#{i}'"
326           end
327         rescue
328           @canonical_names.clear
329           @argument_flags.clear
330           raise
331         end
333         #
334         # Register the option (`i') to the `@canonical_names' and 
335         # `@canonical_names' Hashes.
336         #
337         if canonical_name == nil
338           canonical_name = i
339         end
340         @canonical_names[i] = canonical_name
341         @argument_flags[i] = argument_flag
342       end
343       raise ArgumentError, "no option name" if canonical_name == nil
344     end
345     return self
346   end
348   #
349   # Set/Unset `quiet' mode.
350   #
351   attr_writer :quiet
353   #
354   # Return the flag of `quiet' mode.
355   #
356   attr_reader :quiet
358   #
359   # `quiet?' is an alias of `quiet'.
360   #
361   alias quiet? quiet
363   #
364   # Explicitly terminate option processing.
365   #
366   def terminate
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)
373     end
375     @canonical_names = nil
376     @argument_flags = nil
377     @rest_singles = nil
378     @non_option_arguments = nil
380     return self
381   end
383   #
384   # Returns true if option processing has terminated, false otherwise.
385   #
386   def terminated?
387     return @status == STATUS_TERMINATED
388   end
390   #
391   # Set an error (protected).
392   #
393   def set_error(type, message)
394     $stderr.print("#{$0}: #{message}\n") if !@quiet
396     @error = type
397     @error_message = message
398     @canonical_names = nil
399     @argument_flags = nil
400     @rest_singles = nil
401     @non_option_arguments = nil
403     raise type, message
404   end
405   protected :set_error
407   #
408   # Examine whether an option processing is failed.
409   #
410   attr_reader :error
412   #
413   # `error?' is an alias of `error'.
414   #
415   alias error? error
417   # Return the appropriate error message in POSIX-defined format.
418   # If no error has occurred, returns nil.
419   #
420   def error_message
421     return @error_message
422   end
424   #
425   # Get next option name and its argument, as an Array of two elements.
426   #
427   # The option name is always converted to the first (preferred)
428   # name given in the original options to GetoptLong.new.
429   #
430   # Example: ['--option', 'value']
431   #
432   # Returns nil if the processing is complete (as determined by
433   # STATUS_TERMINATED).
434   #
435   def get
436     option_name, option_argument = nil, ''
438     #
439     # Check status.
440     #
441     return nil if @error != nil
442     case @status
443     when STATUS_YET
444       @status = STATUS_STARTED
445     when STATUS_TERMINATED
446       return nil
447     end
449     #
450     # Get next option argument.
451     #
452     if 0 < @rest_singles.length
453       argument = '-' + @rest_singles
454     elsif (ARGV.length == 0)
455       terminate
456       return nil
457     elsif @ordering == PERMUTE
458       while 0 < ARGV.length && ARGV[0] !~ /^-./
459         @non_option_arguments.push(ARGV.shift)
460       end
461       if ARGV.length == 0
462         terminate
463         return nil
464       end
465       argument = ARGV.shift
466     elsif @ordering == REQUIRE_ORDER 
467       if (ARGV[0] !~ /^-./)
468         terminate
469         return nil
470       end
471       argument = ARGV.shift
472     else
473       argument = ARGV.shift
474     end
476     #
477     # Check the special argument `--'.
478     # `--' indicates the end of the option list.
479     #
480     if argument == '--' && @rest_singles.length == 0
481       terminate
482       return nil
483     end
485     #
486     # Check for long and short options.
487     #
488     if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0
489       #
490       # This is a long style option, which start with `--'.
491       #
492       pattern = $1
493       if @canonical_names.include?(pattern)
494         option_name = pattern
495       else
496         #
497         # The option `option_name' is not registered in `@canonical_names'.
498         # It may be an abbreviated.
499         #
500         match_count = 0
501         @canonical_names.each_key do |key|
502           if key.index(pattern) == 0
503             option_name = key
504             match_count += 1
505           end
506         end
507         if 2 <= match_count
508           set_error(AmbigousOption, "option `#{argument}' is ambiguous")
509         elsif match_count == 0
510           set_error(InvalidOption, "unrecognized option `#{argument}'")
511         end
512       end
514       #
515       # Check an argument to the option.
516       #
517       if @argument_flags[option_name] == REQUIRED_ARGUMENT
518         if argument =~ /=(.*)$/
519           option_argument = $1
520         elsif 0 < ARGV.length
521           option_argument = ARGV.shift
522         else
523           set_error(MissingArgument,
524                     "option `#{argument}' requires an argument")
525         end
526       elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
527         if argument =~ /=(.*)$/
528           option_argument = $1
529         elsif 0 < ARGV.length && ARGV[0] !~ /^-./
530           option_argument = ARGV.shift
531         else
532           option_argument = ''
533         end
534       elsif argument =~ /=(.*)$/
535         set_error(NeedlessArgument,
536                   "option `#{option_name}' doesn't allow an argument")
537       end
539     elsif argument =~ /^(-(.))(.*)/
540       #
541       # This is a short style option, which start with `-' (not `--').
542       # Short options may be catenated (e.g. `-l -g' is equivalent to
543       # `-lg').
544       #
545       option_name, ch, @rest_singles = $1, $2, $3
547       if @canonical_names.include?(option_name)
548         #
549         # The option `option_name' is found in `@canonical_names'.
550         # Check its argument.
551         #
552         if @argument_flags[option_name] == REQUIRED_ARGUMENT
553           if 0 < @rest_singles.length
554             option_argument = @rest_singles
555             @rest_singles = ''
556           elsif 0 < ARGV.length
557             option_argument = ARGV.shift
558           else
559             # 1003.2 specifies the format of this message.
560             set_error(MissingArgument, "option requires an argument -- #{ch}")
561           end
562         elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
563           if 0 < @rest_singles.length
564             option_argument = @rest_singles
565             @rest_singles = ''
566           elsif 0 < ARGV.length && ARGV[0] !~ /^-./
567             option_argument = ARGV.shift
568           else
569             option_argument = ''
570           end
571         end
572       else
573         #
574         # This is an invalid option.
575         # 1003.2 specifies the format of this message.
576         #
577         if ENV.include?('POSIXLY_CORRECT')
578           set_error(InvalidOption, "illegal option -- #{ch}")
579         else
580           set_error(InvalidOption, "invalid option -- #{ch}")
581         end
582       end
583     else
584       #
585       # This is a non-option argument.
586       # Only RETURN_IN_ORDER falled into here.
587       #
588       return '', argument
589     end
591     return @canonical_names[option_name], option_argument
592   end
594   #
595   # `get_option' is an alias of `get'.
596   #
597   alias get_option get
599   # Iterator version of `get'.
600   #
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')
605   #
606   # The option name is always converted to the first (preferred)
607   # name given in the original options to GetoptLong.new.
608   #
609   def each
610     loop do
611       option_name, option_argument = get_option
612       break if option_name == nil
613       yield option_name, option_argument
614     end
615   end
617   #
618   # `each_option' is an alias of `each'.
619   #
620   alias each_option each