Георги обнови решението на 09.11.2016 12:52 (преди около 8 години)
+class CommandParser
+ def initialize(command_name)
+ @command_name = command_name
+ @list = []
+ end
+
+ def argument(argument_name, &block)
+ @list.push(Argument.new(argument_name, &block))
+ end
+
+ def option(short_name, long_name, help, &block)
+ @list.push(Option.new(short_name, long_name, help, &block))
+ end
+
+ def option_with_parameter(*option_name, &block)
+ @list.push(OptonWithParameter.new(*option_name, &block))
+ end
+
+ def parse(command_runner, argv)
+ until argv.empty?
+ arg = argv.shift
+ @list.detect { |e| e.parse(command_runner, arg) }
+ end
+ @list.each do |e|
+ e.used = false if e.respond_to? :used
+ end
+ end
+
+ def help
+ help_msg = "Usage: #{@command_name}"
+ @list.each { |e| help_msg += " [#{e.name}]" if e.is_a? Argument }
+ @list.each { |e| help_msg += e.help_msg unless e.is_a? Argument }
+ help_msg
+ end
+end
+class Argument
+ attr_reader :name
+ attr_accessor :used
+
+ def initialize(name, &block)
+ @name = name
+ @block = block
+ @used = false
+ end
+
+ def parse(command_runner, arg)
+ unless arg.start_with?('-') || @used
+ @used = true
+ @block.call command_runner, arg
+ end
+ end
+end
+
+class Option
+ def initialize(short, long, help, &block)
+ @short = short
+ @long = long
+ @help = help
+ @block = block
+ end
+
+ def parse(command_runner, arg)
+ @block.call command_runner, true if option_found arg
+ end
+
+ def option_found(arg)
+ %W(--#{@long} -#{@short}).include? arg
+ end
+
+ def help_msg
+ "\n -#{@short}, --#{@long} #{@help}"
+ end
+end
+
+class OptonWithParameter < Option
+ def initialize(short, long, help, parameter, &block)
+ super(short, long, help, &block)
+ @parameter = parameter
+ end
+
+ def parse(command_runner, arg)
+ option, parameter =
+ if arg.start_with? '--'
+ arg.split('=', 2)
+ elsif arg[0] == '-'
+ [arg[0..1], arg[2..-1]]
+ else
+ [nil, nil]
+ end
+ @block.call command_runner, parameter if option_found option
+ end
+
+ def help_msg
+ "\n -#{@short}, --#{@long}=#{@parameter} #{@help}"
+ end
+end