Кристъфър обнови решението на 09.11.2016 00:24 (преди около 8 години)
+class Option
+ attr_accessor :short, :long, :description
+
+ def initialize(short, long, description, placeholder)
+ @short = '-' + short
+ @long = '--' + long
+ @description = description
+ @placeholder = placeholder
+ end
+
+ def to_str
+ return " #{@short}, #{@long} #{@description}" if @placeholder.nil?
+ " #{@short}, #{@long}=#{@placeholder} #{@description}"
+ end
+
+ def self.get_option_value(option)
+ return option.split('=')[1] if option.split('=').length == 2
+ is_short_with_value = option.length > 2 && !Option.long?(option)
+ return option.slice(2, option.length) if is_short_with_value
+ true
+ end
+
+ def self.get_option_name(option)
+ return option.slice(0, 2) if Option.short?(option)
+ return option.split('=')[0] if Option.long?(option)
+ end
+
+ def self.long?(option)
+ option.start_with?('--') && option.length > 2
+ end
+
+ def self.short?(option)
+ option.slice(0, 2).start_with?('-') && option.slice(0, 2) != '--'
+ end
+end
+
+class CommandParser
+ def initialize(name)
+ @name = name
+ @argument_blocks = {}
+ @option_blocks = {}
+ @arguments = []
+ @options = []
+ @option_objects = []
+ end
+
+ def argument(name, &block)
+ @argument_blocks[name] = block
+ end
+
+ def option(short, long, description, &block)
+ add_option(short, long, description, nil, &block)
+ end
+
+ def option_with_parameter(short, long, description, placeholder, &block)
+ add_option(short, long, description, placeholder, &block)
+ end
+
+ def parse(command_runner, argv)
+ init_options_and_arguments(argv)
+ @argument_blocks.values.each do |argument_block|
+ argument_block.call(command_runner, @arguments.shift)
+ end
+
+ @options.each do |option|
+ value = Option.get_option_value(option)
+ block = @option_blocks[Option.get_option_name(option)]
+ block.call(command_runner, value) unless block.nil?
+ end
+ end
+
+ def help
+ usage_message = 'Usage: ' + @name
+ @argument_blocks.keys.each do |key|
+ usage_message += " [#{key}]"
+ end
+ usage_message += "\n"
+ option_message = ""
+ @option_objects.each do |option|
+ option_message += option.to_str + "\n"
+ end
+ usage_message + option_message
+ end
+
+ private
+
+ def add_option(short, long, description, placeholder, &block)
+ option = Option.new(short, long, description, placeholder)
+ @option_blocks[option.short] = block
+ @option_blocks[option.long] = block
+ @option_objects.push(option)
+ end
+
+ def init_options_and_arguments(argv)
+ @options.clear
+ @arguments.clear
+ argv.each do |arg|
+ if arg.start_with?('-')
+ @options.push(arg)
+ else
+ @arguments.push(arg)
+ end
+ end
+ end
+end