def self.getopts(*switches)
if switches.empty?
raise ArgumentError, 'no switches provided'
end
hash = {}
valid = []
types = {}
syns = {}
if switches.first.kind_of?(String)
switches = switches.join.split
switches.map!{ |switch| switch = [switch] }
end
switches.each{ |switch|
valid.push(switch[0])
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
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]
valid.push(char)
}
}
re_long = /^(--\w+[-\w+]*)?$/
re_short = /^(-\w)$/
re_long_eq = /^(--\w+[-\w+]*)?=(.*?)$|(-\w?)=(.*?)$/
re_short_sq = /^(-\w)(\S+?)$/
ARGV.each_with_index{ |opt, index|
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
if types[char] == REQUIRED
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)
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
unless valid.include?(switch)
switch ||= opt
raise Error, "invalid switch '#{switch}'"
end
if types[switch] == REQUIRED
nextval = ARGV[index+1]
if nextval.nil?
err = "no value provided for required argument '#{switch}'"
raise Error, err
end
if valid.include?(nextval)
err = "cannot pass switch '#{nextval}' as an argument"
raise Error, err
end
if hash[switch]
hash[switch] = [hash[switch], nextval].flatten
else
hash[switch] = nextval
end
ARGV.delete_at(index+1)
end
if types[switch] == BOOLEAN
if hash.has_key?(switch)
raise Error, 'boolean switch already set'
end
hash[switch] = true
end
if types[switch] == INCREMENT
if hash.has_key?(switch)
hash[switch] += 1
else
hash[switch] = 1
end
end
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
}
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
}
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