Теодора обнови решението на 09.11.2016 03:34 (преди около 8 години)
+class OptionData
+ attr_accessor :short_name
+ attr_accessor :full_name
+ attr_accessor :description
+ attr_accessor :block
+ attr_accessor :placeholder
+
+ def initialize(short_name, full_name, description, placeholder = nil, &block)
+ @short_name = short_name
+ @full_name = full_name
+ @description = description
+ @block = block
+ @placeholder = placeholder unless placeholder.nil?
+ end
+
+ def to_s
+ if placeholder == nil
+ " -%s, --%s %s" % [self.short_name, self.full_name, self.description]
+ else
+ " -%s, --%s=%s %s" %
+ [self.short_name, self.full_name, self.placeholder, self.description]
+ end
+ end
+end
+
+class OptionParser
+ def initialize(_)
+ @options = {}
+ @options_links = {}
+ @parameter_options = {}
+ @parameter_options_links = {}
+ end
+
+ def option(short_name, full_name, description, &_)
+
+ new_block = proc do |sth, _|
+ yield(sth, true)
+ end
+
+ data = OptionData.new(short_name, full_name, description, &new_block)
+
+ @options[short_name] = data
+ @options_links[full_name] = short_name
+ end
+
+ def option_with_parameter(short_name, full_name, description, holder, &block)
+ data = OptionData.new(short_name, full_name, description, holder, &block)
+
+ @parameter_options[short_name] = data
+ @parameter_options_links[full_name] = short_name
+ end
+
+ def parse_option(runner, arg)
+ if arg =~ /^--.+$/
+ key = @options_links[arg[2, arg.size]]
+ elsif arg =~ /^-.$/
+ key = arg[1, arg.size]
+ end
+
+ @options[key].block.call(runner, arg) if key != nil && @options[key] != nil
+ end
+
+ def parse_option_with_parameter(runner, arg)
+ if arg =~ /^--.+\=.+$/
+ equal_sign = arg =~ /\=/
+ key = @parameter_options_links[arg[2, equal_sign - 2]]
+ value = arg[equal_sign + 1, arg.size]
+ elsif arg =~ /^-..+$/
+ key = arg[1, 1]
+ value = arg[2, arg.size]
+ end
+
+ @parameter_options[key].block.call(runner, value) if key != nil &&
+ @parameter_options[key] != nil
+
+ end
+end
+
+class CommandParser < OptionParser
+ def initialize(command_name)
+ super
+ @command = command_name
+ @arguments = {}
+ end
+
+ def argument(argument_name, &block)
+ @arguments[argument_name] = block
+ end
+
+ def help
+
+ args = @arguments.keys.map { |k| "[" + k + "]" }.concat_with_spaces
+ ops = @options.map { |o| o[1].to_s }.concat_with_newlines
+ param_ops = @parameter_options.map { |o| o[1].to_s }.concat_with_newlines
+
+ message = "Usage: #{@command}"
+ message += " #{args}" if args != nil
+ message += "\n#{ops}" if ops != nil
+ message += "\n#{param_ops}" if param_ops != nil
+ message
+ end
+
+ def parse(runner, argv)
+ i = 0
+ argv.each do |arg|
+ parse_option_with_parameter(runner, arg)
+
+ parse_option(runner, arg)
+
+ key = arg["-"] == nil ? @arguments.keys[i] : nil
+ if key != nil
+ @arguments[key].call(runner, arg) if @arguments[key] != nil
+ i += 1
+ end
+ end
+ end
+end
+
+class Array
+ def concat_with_spaces
+ self.reduce { |a, b| a + " " + b }
+ end
+
+ def concat_with_newlines
+ self.reduce { |a, b| a + "\n" + b }
+ end
+end