Петър обнови решението на 09.11.2016 00:19 (преди около 8 години)
+class OptionHash
+ attr_accessor :hash
+
+ def initialize(hash)
+ @hash = hash
+ end
+
+ def [](key)
+ @hash[key]
+ end
+
+ def to_s
+ "-#{@hash[:short_name]}, --#{@hash[:full_name]} #{@hash[:description]}"
+ end
+end
+
+class OptionWithParameterHash
+ attr_accessor :hash
+
+ def initialize(hash)
+ @hash = hash
+ end
+
+ def [](key)
+ @hash[key]
+ end
+
+ def to_s
+ "-#{@hash[:short_name]}, --#{@hash[:full_name]}=#{@hash[:parameter]}" \
+ " #{@hash[:description]}"
+ end
+end
+
+module CommandParserHelper
+ def handle_option_with_parameter(runner, argv_text)
+ option_key = argv_text.count('-') == 2 ? :full_name : :short_name
+
+ if argv_text.include? '='
+ option_name, value = argv_text[2..argv_text.size].split '='
+ else
+ option_name = argv_text[1]
+ value = argv_text[2..argv_text.size]
+ end
+
+ @options_with_parameter.each do |option|
+ option[:block].call runner, value if option[option_key] == option_name
+ end
+ end
+
+ def option_with_parameter?(argv_text)
+ argv_text.include?('=') || (argv_text.count('-') == 1 && argv_text.size > 2)
+ end
+
+ def handle_option(runner, argv_text)
+ if option_with_parameter? argv_text
+ handle_option_with_parameter runner, argv_text
+ else
+ option_key = argv_text.count('-') == 2 ? :full_name : :short_name
+ option_name = argv_text.delete '-'
+
+ @options.each do |option|
+ option[:block].call runner, true if option[option_key] == option_name
+ end
+ end
+ end
+end
+
+class CommandParser
+ attr_accessor :command_name, :arguments, :options, :options_with_parameter
+
+ include CommandParserHelper
+
+ def initialize(command_name)
+ @command_name = command_name
+ @arguments = []
+ @options = []
+ @options_with_parameter = []
+ end
+
+ def argument(argument_name, &block)
+ @arguments << {
+ argument_name: argument_name,
+ block: block
+ }
+ end
+
+ def option(short_name, full_name, description, &block)
+ hash = {
+ short_name: short_name,
+ full_name: full_name,
+ description: description,
+ block: block
+ }
+
+ @options << OptionHash.new(hash)
+ end
+
+ def option_with_parameter(short_name, full_name, help_text, parameter, &block)
+ hash = {
+ short_name: short_name,
+ full_name: full_name,
+ description: help_text,
+ parameter: parameter,
+ block: block
+ }
+
+ @options_with_parameter << OptionWithParameterHash.new(hash)
+ end
+
+ def parse(command_runner, argv)
+ argument_index = 0
+
+ argv.each do |value|
+ if value.include? '-'
+ handle_option(command_runner, value)
+ else
+ @arguments[argument_index][:block].call command_runner, value
+ argument_index += 1
+ end
+ end
+ end
+
+ def help
+ help_text = "Usage: #{@command_name}"
+ space = " " * 4
+ @arguments.each { |argument| help_text += " [#{argument[:argument_name]}]" }
+ @options.each { |option| help_text += "\n#{space}#{option}" }
+ @options_with_parameter.each { |option| help_text += "\n#{space}#{option}" }
+
+ help_text
+ end
+end