* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / lib / getoptlong.rb
blob4cfb5fbd272f11c4d79fa904ad453cb5eabfc77c
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 #     require 'getoptlong'
28 #     require 'rdoc/usage'
29 #     
30 #     opts = GetoptLong.new(
31 #       [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
32 #       [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
33 #       [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
34 #     )
35 #     
36 #     dir = nil
37 #     name = nil
38 #     repetitions = 1
39 #     opts.each do |opt, arg|
40 #       case opt
41 #         when '--help'
42 #           puts <<-EOF
43 #     hello [OPTION] ... DIR
44 #     
45 #     -h, --help:
46 #        show help
47 #     
48 #     --repeat x, -n x:
49 #        repeat x times
50 #     
51 #     --name [name]:
52 #        greet user by name, if name not supplied default is John
53 #     
54 #     DIR: The directory in which to issue the greeting.
55 #           EOF
56 #         when '--repeat'
57 #           repetitions = arg.to_i
58 #         when '--name'
59 #           if arg == ''
60 #             name = 'John'
61 #           else
62 #             name = arg
63 #           end
64 #       end
65 #     end
66 #     
67 #     if ARGV.length != 1
68 #       puts "Missing dir argument (try --help)"
69 #       exit 0
70 #     end
71 #     
72 #     dir = ARGV.shift
74 #     Dir.chdir(dir)
75 #     for i in (1..repetitions)
76 #       print "Hello"
77 #       if name
78 #         print ", #{name}"
79 #       end
80 #       puts
81 #     end
83 # Example command line:
85 #     hello -n 6 --name -- /tmp
87 class GetoptLong
88   #
89   # Orderings.
90   #
91   ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
93   #
94   # Argument flags.
95   #
96   ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
97     OPTIONAL_ARGUMENT = 2]
99   #
100   # Status codes.
101   #
102   STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
104   #
105   # Error types.
106   #
107   class Error  < StandardError; end
108   class AmbiguousOption   < Error; end
109   class NeedlessArgument < Error; end
110   class MissingArgument  < Error; end
111   class InvalidOption    < Error; end
113   #
114   # Set up option processing.
115   #
116   # The options to support are passed to new() as an array of arrays.
117   # Each sub-array contains any number of String option names which carry 
118   # the same meaning, and one of the following flags:
119   #
120   # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
121   #
122   # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument.
123   #
124   # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument.
125   #
126   # The first option name is considered to be the preferred (canonical) name.
127   # Other than that, the elements of each sub-array can be in any order.
128   #
129   def initialize(*arguments)
130     #
131     # Current ordering.
132     #
133     if ENV.include?('POSIXLY_CORRECT')
134       @ordering = REQUIRE_ORDER
135     else
136       @ordering = PERMUTE
137     end
139     #
140     # Hash table of option names.
141     # Keys of the table are option names, and their values are canonical
142     # names of the options.
143     #
144     @canonical_names = Hash.new
146     #
147     # Hash table of argument flags.
148     # Keys of the table are option names, and their values are argument
149     # flags of the options.
150     #
151     @argument_flags = Hash.new
153     #
154     # Whether error messages are output to $stderr.
155     #
156     @quiet = FALSE
158     #
159     # Status code.
160     #
161     @status = STATUS_YET
163     #
164     # Error code.
165     #
166     @error = nil
168     #
169     # Error message.
170     #
171     @error_message = nil
173     #
174     # Rest of catenated short options.
175     #
176     @rest_singles = ''
178     #
179     # List of non-option-arguments.
180     # Append them to ARGV when option processing is terminated.
181     #
182     @non_option_arguments = Array.new
184     if 0 < arguments.length
185       set_options(*arguments)
186     end
187   end
189   #
190   # Set the handling of the ordering of options and arguments.
191   # A RuntimeError is raised if option processing has already started.
192   #
193   # The supplied value must be a member of GetoptLong::ORDERINGS. It alters
194   # the processing of options as follows:
195   #
196   # <b>REQUIRE_ORDER</b> :
197   # 
198   # Options are required to occur before non-options.
199   #
200   # Processing of options ends as soon as a word is encountered that has not
201   # been preceded by an appropriate option flag.
202   #
203   # For example, if -a and -b are options which do not take arguments,
204   # parsing command line arguments of '-a one -b two' would result in 
205   # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being 
206   # processed as an option/arg pair.
207   #
208   # This is the default ordering, if the environment variable
209   # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
210   #
211   # <b>PERMUTE</b> :
212   #  
213   # Options can occur anywhere in the command line parsed. This is the 
214   # default behavior.
215   #
216   # Every sequence of words which can be interpreted as an option (with or
217   # without argument) is treated as an option; non-option words are skipped.
218   #
219   # For example, if -a does not require an argument and -b optionally takes
220   # an argument, parsing '-a one -b two three' would result in ('-a','') and
221   # ('-b', 'two') being processed as option/arg pairs, and 'one','three'
222   # being left in ARGV.
223   #
224   # If the ordering is set to PERMUTE but the environment variable
225   # POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for
226   # compatibility with GNU getopt_long.
227   #
228   # <b>RETURN_IN_ORDER</b> :
229   #
230   # All words on the command line are processed as options. Words not 
231   # preceded by a short or long option flag are passed as arguments
232   # with an option of '' (empty string).
233   #
234   # For example, if -a requires an argument but -b does not, a command line
235   # of '-a one -b two three' would result in option/arg pairs of ('-a', 'one')
236   # ('-b', ''), ('', 'two'), ('', 'three') being processed.
237   #
238   def ordering=(ordering)
239     #
240     # The method is failed if option processing has already started.
241     #
242     if @status != STATUS_YET
243       set_error(ArgumentError, "argument error")
244       raise RuntimeError,
245         "invoke ordering=, but option processing has already started"
246     end
248     #
249     # Check ordering.
250     #
251     if !ORDERINGS.include?(ordering)
252       raise ArgumentError, "invalid ordering `#{ordering}'"
253     end
254     if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
255       @ordering = REQUIRE_ORDER
256     else
257       @ordering = ordering
258     end
259   end
261   #
262   # Return ordering.
263   #
264   attr_reader :ordering
266   #
267   # Set options. Takes the same argument as GetoptLong.new.
268   #
269   # Raises a RuntimeError if option processing has already started.
270   #
271   def set_options(*arguments)
272     #
273     # The method is failed if option processing has already started.
274     #
275     if @status != STATUS_YET
276       raise RuntimeError, 
277         "invoke set_options, but option processing has already started"
278     end
280     #
281     # Clear tables of option names and argument flags.
282     #
283     @canonical_names.clear
284     @argument_flags.clear
286     arguments.each do |*arg|
287       arg = arg.first # TODO: YARV Hack
288       #
289       # Find an argument flag and it set to `argument_flag'.
290       #
291       argument_flag = nil
292       arg.each do |i|
293         if ARGUMENT_FLAGS.include?(i)
294           if argument_flag != nil
295             raise ArgumentError, "too many argument-flags"
296           end
297           argument_flag = i
298         end
299       end
301       raise ArgumentError, "no argument-flag" if argument_flag == nil
303       canonical_name = nil
304       arg.each do |i|
305         #
306         # Check an option name.
307         #
308         next if i == argument_flag
309         begin
310           if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
311             raise ArgumentError, "an invalid option `#{i}'"
312           end
313           if (@canonical_names.include?(i))
314             raise ArgumentError, "option redefined `#{i}'"
315           end
316         rescue
317           @canonical_names.clear
318           @argument_flags.clear
319           raise
320         end
322         #
323         # Register the option (`i') to the `@canonical_names' and 
324         # `@canonical_names' Hashes.
325         #
326         if canonical_name == nil
327           canonical_name = i
328         end
329         @canonical_names[i] = canonical_name
330         @argument_flags[i] = argument_flag
331       end
332       raise ArgumentError, "no option name" if canonical_name == nil
333     end
334     return self
335   end
337   #
338   # Set/Unset `quiet' mode.
339   #
340   attr_writer :quiet
342   #
343   # Return the flag of `quiet' mode.
344   #
345   attr_reader :quiet
347   #
348   # `quiet?' is an alias of `quiet'.
349   #
350   alias quiet? quiet
352   #
353   # Explicitly terminate option processing.
354   #
355   def terminate
356     return nil if @status == STATUS_TERMINATED
357     raise RuntimeError, "an error has occured" if @error != nil
359     @status = STATUS_TERMINATED
360     @non_option_arguments.reverse_each do |argument|
361       ARGV.unshift(argument)
362     end
364     @canonical_names = nil
365     @argument_flags = nil
366     @rest_singles = nil
367     @non_option_arguments = nil
369     return self
370   end
372   #
373   # Returns true if option processing has terminated, false otherwise.
374   #
375   def terminated?
376     return @status == STATUS_TERMINATED
377   end
379   #
380   # Set an error (a protected method).
381   #
382   def set_error(type, message)
383     $stderr.print("#{$0}: #{message}\n") if !@quiet
385     @error = type
386     @error_message = message
387     @canonical_names = nil
388     @argument_flags = nil
389     @rest_singles = nil
390     @non_option_arguments = nil
392     raise type, message
393   end
394   protected :set_error
396   #
397   # Examine whether an option processing is failed.
398   #
399   attr_reader :error
401   #
402   # `error?' is an alias of `error'.
403   #
404   alias error? error
406   # Return the appropriate error message in POSIX-defined format.
407   # If no error has occurred, returns nil.
408   #
409   def error_message
410     return @error_message
411   end
413   #
414   # Get next option name and its argument, as an Array of two elements.
415   #
416   # The option name is always converted to the first (preferred)
417   # name given in the original options to GetoptLong.new.
418   #
419   # Example: ['--option', 'value']
420   #
421   # Returns nil if the processing is complete (as determined by
422   # STATUS_TERMINATED).
423   #
424   def get
425     option_name, option_argument = nil, ''
427     #
428     # Check status.
429     #
430     return nil if @error != nil
431     case @status
432     when STATUS_YET
433       @status = STATUS_STARTED
434     when STATUS_TERMINATED
435       return nil
436     end
438     #
439     # Get next option argument.
440     #
441     if 0 < @rest_singles.length
442       argument = '-' + @rest_singles
443     elsif (ARGV.length == 0)
444       terminate
445       return nil
446     elsif @ordering == PERMUTE
447       while 0 < ARGV.length && ARGV[0] !~ /^-./
448         @non_option_arguments.push(ARGV.shift)
449       end
450       if ARGV.length == 0
451         terminate
452         return nil
453       end
454       argument = ARGV.shift
455     elsif @ordering == REQUIRE_ORDER 
456       if (ARGV[0] !~ /^-./)
457         terminate
458         return nil
459       end
460       argument = ARGV.shift
461     else
462       argument = ARGV.shift
463     end
465     #
466     # Check the special argument `--'.
467     # `--' indicates the end of the option list.
468     #
469     if argument == '--' && @rest_singles.length == 0
470       terminate
471       return nil
472     end
474     #
475     # Check for long and short options.
476     #
477     if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0
478       #
479       # This is a long style option, which start with `--'.
480       #
481       pattern = $1
482       if @canonical_names.include?(pattern)
483         option_name = pattern
484       else
485         #
486         # The option `option_name' is not registered in `@canonical_names'.
487         # It may be an abbreviated.
488         #
489         matches = []
490         @canonical_names.each_key do |key|
491           if key.index(pattern) == 0
492             option_name = key
493             matches << key
494           end
495         end
496         if 2 <= matches.length
497           set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}")
498         elsif matches.length == 0
499           set_error(InvalidOption, "unrecognized option `#{argument}'")
500         end
501       end
503       #
504       # Check an argument to the option.
505       #
506       if @argument_flags[option_name] == REQUIRED_ARGUMENT
507         if argument =~ /=(.*)$/
508           option_argument = $1
509         elsif 0 < ARGV.length
510           option_argument = ARGV.shift
511         else
512           set_error(MissingArgument,
513                     "option `#{argument}' requires an argument")
514         end
515       elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
516         if argument =~ /=(.*)$/
517           option_argument = $1
518         elsif 0 < ARGV.length && ARGV[0] !~ /^-./
519           option_argument = ARGV.shift
520         else
521           option_argument = ''
522         end
523       elsif argument =~ /=(.*)$/
524         set_error(NeedlessArgument,
525                   "option `#{option_name}' doesn't allow an argument")
526       end
528     elsif argument =~ /^(-(.))(.*)/
529       #
530       # This is a short style option, which start with `-' (not `--').
531       # Short options may be catenated (e.g. `-l -g' is equivalent to
532       # `-lg').
533       #
534       option_name, ch, @rest_singles = $1, $2, $3
536       if @canonical_names.include?(option_name)
537         #
538         # The option `option_name' is found in `@canonical_names'.
539         # Check its argument.
540         #
541         if @argument_flags[option_name] == REQUIRED_ARGUMENT
542           if 0 < @rest_singles.length
543             option_argument = @rest_singles
544             @rest_singles = ''
545           elsif 0 < ARGV.length
546             option_argument = ARGV.shift
547           else
548             # 1003.2 specifies the format of this message.
549             set_error(MissingArgument, "option requires an argument -- #{ch}")
550           end
551         elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
552           if 0 < @rest_singles.length
553             option_argument = @rest_singles
554             @rest_singles = ''
555           elsif 0 < ARGV.length && ARGV[0] !~ /^-./
556             option_argument = ARGV.shift
557           else
558             option_argument = ''
559           end
560         end
561       else
562         #
563         # This is an invalid option.
564         # 1003.2 specifies the format of this message.
565         #
566         if ENV.include?('POSIXLY_CORRECT')
567           set_error(InvalidOption, "invalid option -- #{ch}")
568         else
569           set_error(InvalidOption, "invalid option -- #{ch}")
570         end
571       end
572     else
573       #
574       # This is a non-option argument.
575       # Only RETURN_IN_ORDER falled into here.
576       #
577       return '', argument
578     end
580     return @canonical_names[option_name], option_argument
581   end
583   #
584   # `get_option' is an alias of `get'.
585   #
586   alias get_option get
588   # Iterator version of `get'.
589   #
590   # The block is called repeatedly with two arguments:
591   # The first is the option name.
592   # The second is the argument which followed it (if any). 
593   # Example: ('--opt', 'value')
594   #
595   # The option name is always converted to the first (preferred)
596   # name given in the original options to GetoptLong.new.
597   #
598   def each
599     loop do
600       option_name, option_argument = get_option
601       break if option_name == nil
602       yield option_name, option_argument
603     end
604   end
606   #
607   # `each_option' is an alias of `each'.
608   #
609   alias each_option each