Владимир обнови решението на 09.11.2016 01:33 (преди около 8 години)
+class CommandParser
+ def initialize(command_name)
+ @command_name = command_name
+ @arguments = []
+ @opts_help = []
+ @arg_blks = []
+ @opt_with_p_blks = {}
+ @opt_blks = {}
+ end
+
+ def argument(argument, &block)
+ @arguments << argument
+ @arg_blks << block if block_given?
+ end
+
+ def option(name, full_name, help_text, &block)
+ @opts_help << "-#{name}, --#{full_name} #{help_text}"
+ @opt_blks["-#{name}"] = @opt_blks["--#{full_name}"] = block if block_given?
+ end
+
+ def option_with_parameter(name, full_name, help_text, placeholder, &block)
+ @opts_help << "-#{name}, --#{full_name}=#{placeholder} #{help_text}"
+ if block_given?
+ @opt_with_p_blks["-#{name}"] = @opt_with_p_blks["--#{full_name}"] = block
+ end
+ end
+
+ def parse(command_runner, argv)
+ if !@opt_with_p_blks.empty?
+ opt_regex = Regexp.new("^#{@opt_with_p_blks.keys.join('|')}")
+ opt_with_p, rest = argv.partition { |arg| arg =~ opt_regex }
+ else
+ rest = argv
+ end
+ arguments, options = rest.partition { |element| element[0] != '-' }
+ handle_arguments(command_runner, arguments)
+ handle_options(command_runner, options)
+ handle_opts_with_params(command_runner, opt_with_p) if opt_with_p
+ end
+
+ def handle_arguments(command_runner, arguments)
+ @arg_blks.each_with_index do |block, index|
+ block.call(command_runner, arguments[index])
+ end
+ end
+
+ def handle_options(command_runner, options)
+ options.each do |option|
+ if @opt_blks.keys.include?(option)
+ @opt_blks[option].call(command_runner, true)
+ end
+ end
+ end
+
+ def handle_opts_with_params(command_runner, options)
+ options.each do |option|
+ splitted = option.split('=')
+ if splitted.size == 2
+ @opt_with_p_blks[splitted[0]].call(command_runner, splitted[1])
+ else
+ @opt_with_p_blks[option[0..1]].call(command_runner, option[2..-1])
+ end
+ end
+ end
+
+ def help
+ arguments_help = @arguments.map { |arg| "[#{arg}]" }.join(' ')
+ (["Usage: #{@command_name} #{arguments_help}"] + @opts_help).join("\n ")
+ end
+end