class TTY::Option::Parser::Options
Constants
- LONG_OPTION_RE
- SHORT_OPTION_RE
Public Class Methods
new(options, check_invalid_params: true, raise_on_parse_error: false)
click to toggle source
Create a command line env variables parser
@param [Array<Option>] options
the list of options
@param [Hash] config
the configuration settings
@api public
# File lib/tty/option/parser/options.rb, line 27 def initialize(options, check_invalid_params: true, raise_on_parse_error: false) @options = options @check_invalid_params = check_invalid_params @error_aggregator = ErrorAggregator.new(raise_on_parse_error: raise_on_parse_error) @required_check = RequiredCheck.new(@error_aggregator) @arity_check = ArityCheck.new(@error_aggregator) @pipeline = Pipeline.new(@error_aggregator) @parsed = {} @remaining = [] @shorts = {} @longs = {} @arities = Hash.new(0) setup_opts end
Public Instance Methods
parse(argv) { |opt, value| ... }
click to toggle source
Read option(s) from command line
@param [Array<String>] argv
@api public
# File lib/tty/option/parser/options.rb, line 74 def parse(argv) @argv = argv.dup loop do opt, value = next_option if !opt.nil? @required_check.delete(opt) @arities[opt.key] += 1 if block_given? yield(opt, value) else assign_option(opt, value) end end break if @argv.empty? end @arity_check.(@arities) @required_check.() [@parsed, @remaining, @error_aggregator.errors] end
setup_opts()
click to toggle source
Configure list of returned options
@api private
# File lib/tty/option/parser/options.rb, line 48 def setup_opts @options.each do |opt| @shorts[opt.short_name] = opt @longs[opt.long_name] = opt @arity_check << opt if opt.multiple? if opt.default? case opt.default when Proc assign_option(opt, opt.default.()) else assign_option(opt, opt.default) end elsif !(opt.argument_optional? || opt.argument_required?) assign_option(opt, false) elsif opt.required? @required_check << opt end end end
Private Instance Methods
assign_option(opt, val)
click to toggle source
@api private
# File lib/tty/option/parser/options.rb, line 248 def assign_option(opt, val) value = @pipeline.(opt, val) if opt.multiple? allowed = opt.arity < 0 || @arities[opt.key] <= opt.arity if allowed case value when Hash (@parsed[opt.key] ||= {}).merge!(value) else Array(value).each do |v| (@parsed[opt.key] ||= []) << v end end else @remaining << opt.short_name @remaining << value end else @parsed[opt.key] = value end end
consume_arguments(values: [])
click to toggle source
Consume multi argument
@api private
# File lib/tty/option/parser/options.rb, line 237 def consume_arguments(values: []) while (value = @argv.first) && !option?(value) val = @argv.shift parts = val.include?("&") ? val.split(/&/) : [val] parts.each { |part| values << part } end values.size == 1 ? values.first : values end
next_option()
click to toggle source
Get next option
@api private
# File lib/tty/option/parser/options.rb, line 103 def next_option opt, value = nil, nil while !@argv.empty? && !option?(@argv.first) @remaining << @argv.shift end return if @argv.empty? argument = @argv.shift if (matched = argument.match(LONG_OPTION_RE)) long, sep, rest = matched[1..-1] opt, value = *process_double_option(long, sep, rest) elsif (matched = argument.match(SHORT_OPTION_RE)) short, other_singles = *matched[1..-1] opt, value = *process_single_option(short, other_singles) end [opt, value] end
process_double_option(long, sep, rest)
click to toggle source
Process a double option
@return [Array<Option, Object>]
a list of option and its value
@api private
# File lib/tty/option/parser/options.rb, line 131 def process_double_option(long, sep, rest) opt, value = nil, nil if (opt = @longs[long]) if opt.argument_required? if !rest.empty? || sep.to_s.include?("=") value = rest if opt.multi_argument? && !(consumed = consume_arguments).empty? value = [rest] + consumed end elsif !@argv.empty? value = opt.multi_argument? ? consume_arguments : @argv.shift else @error_aggregator.(MissingArgument.new(opt)) end elsif opt.argument_optional? if !rest.empty? value = rest if opt.multi_argument? && !(consumed = consume_arguments).empty? value = [rest] + consumed end elsif !@argv.empty? value = opt.multi_argument? ? consume_arguments : @argv.shift end else # boolean flag value = true end else # option stuck together with an argument or abbreviated matching_options = 0 @longs.each_key do |key| if !key.to_s.empty? && (key.to_s.start_with?(long) || long.to_s.start_with?(key)) opt = @longs[key] matching_options += 1 end end if matching_options.zero? if @check_invalid_params @error_aggregator.(InvalidParameter.new("invalid option '#{long}'")) else @remaining << long end elsif matching_options == 1 value = long[opt.long_name.size..-1] else @error_aggregator.(AmbiguousOption.new("option '#{long}' is ambiguous")) end end [opt, value] end
process_single_option(short, other_singles)
click to toggle source
Process a single option
@return [Array<Option, Object>]
a list of option and its value
@api private
# File lib/tty/option/parser/options.rb, line 193 def process_single_option(short, other_singles) opt, value = nil, nil if (opt = @shorts[short]) if opt.argument_required? if !other_singles.empty? value = other_singles if opt.multi_argument? && !(consumed = consume_arguments).empty? value = [other_singles] + consumed end elsif !@argv.empty? value = opt.multi_argument? ? consume_arguments : @argv.shift else @error_aggregator.(MissingArgument.new(opt)) end elsif opt.argument_optional? if !other_singles.empty? value = other_singles if opt.multi_argument? && !(consumed = consume_arguments).empty? value = [other_singles] + consumed end elsif !@argv.empty? value = opt.multi_argument? ? consume_arguments : @argv.shift end else # boolean flag if !other_singles.empty? @argv.unshift("-#{other_singles}") end value = true end elsif @check_invalid_params @error_aggregator.(InvalidParameter.new("invalid option '#{short}'")) else @remaining << short end [opt, value] end