Радослав обнови решението на 09.11.2016 00:51 (преди около 8 години)
+class Argument
+ attr_reader(:name, :block)
+ def initialize(name, block)
+ @name = name
+ @block = block
+ end
+
+ def help
+ " [#{@name}]"
+ end
+end
+class Option
+ attr_reader(:short_name, :long_name, :description, :block)
+ def initialize(short_name, long_name, description, block)
+ @short_name = short_name
+ @long_name = long_name
+ @description = description
+ @block = block
+ end
+
+ def help
+ " -#{@short_name}, --#{@long_name} #{@description}\n"
+ end
+end
+class OptionWParameter < Option
+ attr_reader(:argument)
+ def initialize(short_name, long_name, description, block, argument)
+ super(short_name, long_name, description, block)
+ @argument = argument
+ end
+
+ def help
+ " -#{@short_name}, --#{@long_name}=#{@argument} #{@description}\n"
+ end
+end
+class CommandParser
+ def initialize(command_name)
+ @command_name = command_name
+ @arguments = []
+ @options = []
+ end
+
+ def argument(arg_name, &block)
+ @arguments.push(Argument.new(arg_name, block))
+ end
+
+ def option(short_name, long_name, description, &block)
+ @options.push(Option.new(short_name, long_name, description, block))
+ end
+
+ def option_with_parameter(short_name, long_name, description, arg, &block )
+ optn = OptionWParameter.new(short_name, long_name, description, block, arg)
+ @options.push(optn)
+ end
+
+ def parse(command_runner, argv)
+ cloner = @arguments.clone
+ argv.each do |member|
+ cloner.shift.block.call(command_runner, member) if member[0] != '-'
+ if member.include?('=') && member[0..1] == '--'
+ search(member.split('=')[0], command_runner, member.split('=')[1])
+ elsif member.length > 2 && member[0] == '-'
+ search(member[0..1], command_runner, member[2..-1])
+ end
+ search(member, command_runner, true)
+ end
+ end
+
+ def help
+ help_str = "Usage: #{@command_name}"
+ @arguments.each { |arg| help_str << arg.help }
+ help_str << "\n" unless @options.empty?
+ @options.each { |opt| help_str << opt.help }
+ help_str
+ end
+
+ private
+
+ def search(option, container, arg)
+ @options.each do |this|
+ if '--' << this.long_name == option || '-' << this.short_name == option
+ this.block.call(container, arg)
+ end
+ end
+ end
+end