Class: Getopt::Long

### Home Classes Methods

### In Files

- lib/getopt/long.rb

### Parent

Object

### Namespace

- CLASS Getopt::Long::Error

### Methods

- ::getopts

### Files

- CHANGES
- MANIFEST
- README

### Class/Module Index

Quicksearch

- Getopt
- Getopt::Long
- Getopt::Long::Error
- Getopt::Std
- Getopt::Std::Error

No matching classes.

# Getopt::Long

The Getopt::Long class encapsulates longhanded parameter parsing options

### Constants

VERSION

  The version of the getopt library

### Public Class Methods

getopts(*switches) click to toggle source

Takes an array of switches. Each array consists of up to three elements that indicate the name and type of switch. Returns a hash containing each switch name, minus the '-', as a key. The value for each key depends on the type of switch and/or the value provided by the user.

The long switch must be provided. The short switch defaults to the first letter of the short switch. The default type is BOOLEAN.

Example:

    opts = Getopt::Long.getopts(
       ['--debug'                   ],
       ['--verbose', '-v'           ],
       ['--level',   '-l', INCREMENT]
    )

See the README file for more information.

    # File lib/getopt/long.rb, line 41
    def self.getopts(*switches)
       if switches.empty?
          raise ArgumentError, 'no switches provided'
       end

       hash  = {} # Hash returned to user
       valid = [] # Tracks valid switches
       types = {} # Tracks argument types
       syns  = {} # Tracks long and short arguments, or multiple shorts

       # If a string is passed, split it and convert it to an array of arrays
       if switches.first.kind_of?(String)
          switches = switches.join.split
          switches.map!{ |switch| switch = [switch] }
       end

       # Set our list of valid switches, and proper types for each switch
       switches.each{ |switch|
          valid.push(switch[0])       # Set valid long switches

          # Set type for long switch, default to BOOLEAN.
          if switch[1].kind_of?(Fixnum)
             switch[2] = switch[1]
             types[switch[0]] = switch[2]
             switch[1] = switch[0][1..2]
          else
             switch[2] ||= BOOLEAN
             types[switch[0]] = switch[2]
             switch[1] ||= switch[0][1..2]
          end

          # Create synonym hash.  Default to first char of long switch for
          # short switch, e.g. "--verbose" creates a "-v" synonym.  The same
          # synonym can only be used once - first one wins.
          syns[switch[0]] = switch[1] unless syns[switch[1]]
          syns[switch[1]] = switch[0] unless syns[switch[1]]

          switch[1] = [switch[1]] if RUBY_VERSION.to_f >= 1.9

          switch[1].each{ |char|
             types[char] = switch[2]  # Set type for short switch
             valid.push(char)         # Set valid short switches
          }
       }

       re_long     = /^(--\w+[-\w+]*)?$/
       re_short    = /^(-\w)$/
       re_long_eq  = /^(--\w+[-\w+]*)?=(.*?)$|(-\w?)=(.*?)$/
       re_short_sq = /^(-\w)(\S+?)$/

       ARGV.each_with_index{ |opt, index|

          # Allow either -x -v or -xv style for single char args
          if re_short_sq.match(opt)
             chars = opt.split("")[1..-1].map{ |s| s = "-#{s}" }

             chars.each_with_index{ |char, i|
                unless valid.include?(char)
                   raise Error, "invalid switch '#{char}'"
                end

                # Grab the next arg if the switch takes a required arg
                if types[char] == REQUIRED
                   # Deal with a argument squished up against switch
                   if chars[i+1]
                      arg = chars[i+1..-1].join.tr('-', '')
                      ARGV.push(char, arg)
                      break
                   else
                      arg = ARGV.delete_at(index+1)
                      if arg.nil? || valid.include?(arg) # Minor cheat here
                         err = "no value provided for required argument '#{char}'"
                         raise Error, err
                      end
                      ARGV.push(char, arg)
                   end
                elsif types[char] == OPTIONAL
                   if chars[i+1] && !valid.include?(chars[i+1])
                      arg = chars[i+1..-1].join.tr("-","")
                      ARGV.push(char, arg)
                      break
                   elsif
                      if ARGV[index+1] && !valid.include?(ARGV[index+1])
                         arg = ARGV.delete_at(index+1)
                         ARGV.push(char, arg)
                      end
                   else
                      ARGV.push(char)
                   end
                else
                   ARGV.push(char)
                end
             }
             next
          end

          if match = re_long.match(opt) || match = re_short.match(opt)
             switch = match.captures.first
          end

          if match = re_long_eq.match(opt)
             switch, value = match.captures.compact
             ARGV.push(switch, value)
             next
          end

          # Make sure that all the switches are valid.  If 'switch' isn't
          # defined at this point, it means an option was passed without
          # a preceding switch, e.g. --option foo bar.
          unless valid.include?(switch)
             switch ||= opt
             raise Error, "invalid switch '#{switch}'"
          end

          # Required arguments
          if types[switch] == REQUIRED
             nextval = ARGV[index+1]

             # Make sure there's a value for mandatory arguments
             if nextval.nil?
                err = "no value provided for required argument '#{switch}'"
                raise Error, err
             end

             # If there is a value, make sure it's not another switch
             if valid.include?(nextval)
                err = "cannot pass switch '#{nextval}' as an argument"
                raise Error, err
             end

             # If the same option appears more than once, put the values
             # in array.
             if hash[switch]
                hash[switch] = [hash[switch], nextval].flatten
             else
                hash[switch] = nextval
             end
             ARGV.delete_at(index+1)
          end

          # For boolean arguments set the switch's value to true.
          if types[switch] == BOOLEAN
             if hash.has_key?(switch)
                raise Error, 'boolean switch already set'
             end
             hash[switch] = true
          end

          # For increment arguments, set the switch's value to 0, or
          # increment it by one if it already exists.
          if types[switch] == INCREMENT
             if hash.has_key?(switch)
                hash[switch] += 1
             else
                hash[switch] = 1
             end
          end

          # For optional argument, there may be an argument.  If so, it
          # cannot be another switch.  If not, it is set to true.
          if types[switch] == OPTIONAL
             nextval = ARGV[index+1]
             if valid.include?(nextval)
                hash[switch] = true
             else
                hash[switch] = nextval
                ARGV.delete_at(index+1)
             end
          end
       }

       # Set synonymous switches to the same value, e.g. if -t is a synonym
       # for --test, and the user passes "--test", then set "-t" to the same
       # value that "--test" was set to.
       #
       # This allows users to refer to the long or short switch and get
       # the same value
       hash.dup.each{ |switch, val|
          if syns.keys.include?(switch)
             syns[switch] = [syns[switch]] if RUBY_VERSION.to_f >= 1.9
             syns[switch].each{ |key|
                hash[key] = val
             }
          end
       }

       # Get rid of leading "--" and "-" to make it easier to reference
       hash.dup.each{ |key, value|
          if key =~ /^-/
             if key[0,2] == '--'
                nkey = key.sub('--', '')
             else
                nkey = key.sub('-', '')
             end
             hash.delete(key)
             hash[nkey] = value
          end
       }

       hash
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.