def self.parse(arguments_and_options, definitions)
unprocessed_arguments_and_options = arguments_and_options.dup
arguments = []
options = {}
no_more_options = false
loop do
e = unprocessed_arguments_and_options.shift
break if e.nil?
if e == '--'
no_more_options = true
elsif e =~ /^--./ and !no_more_options
if e =~ /^--([^=]+)=(.+)$/
option_key = $1
option_value = $2
else
option_key = e[2..-1]
option_value = nil
end
definition = definitions.find { |d| d[:long] == option_key }
raise IllegalOptionError.new(option_key) if definition.nil?
if [ :required, :optional ].include?(definition[:argument])
if option_value.nil?
option_value = unprocessed_arguments_and_options.shift
if option_value.nil? || option_value =~ /^-/
if definition[:argument] == :required
raise OptionRequiresAnArgumentError.new(option_key)
else
unprocessed_arguments_and_options.unshift(option_value)
option_value = true
end
end
end
options[definition[:long].to_sym] = option_value
else
options[definition[:long].to_sym] = true
end
elsif e =~ /^-./ and !no_more_options
option_keys = e[1..-1].scan(/./)
option_keys.each do |option_key|
definition = definitions.find { |d| d[:short] == option_key }
raise IllegalOptionError.new(option_key) if definition.nil?
if option_keys.length > 1 and definition[:argument] == :required
raise OptionRequiresAnArgumentError.new(option_key)
elsif [ :required, :optional ].include?(definition[:argument])
option_value = unprocessed_arguments_and_options.shift
if option_value.nil? || option_value =~ /^-/
if definition[:argument] == :required
raise OptionRequiresAnArgumentError.new(option_key)
else
unprocessed_arguments_and_options.unshift(option_value)
option_value = true
end
end
options[definition[:long].to_sym] = option_value
else
options[definition[:long].to_sym] = true
end
end
else
arguments << e
end
end
{ :options => options, :arguments => arguments }
end