Христо обнови решението на 09.11.2016 14:16 (преди около 8 години)
+class Argument
+ attr_accessor :name, :block
+
+ def initialize(name, &block)
+ @name = name
+ @block = block
+ end
+
+ def parse(command_runner, arg)
+ block.call command_runner, arg
+ end
+
+ def to_s
+ '[' + name + ']'
+ end
+end
+
+class Option
+ attr_accessor :short_name, :long_name, :info, :block
+
+ def initialize(short_name, long_name, info, &block)
+ @short_name = short_name
+ @long_name = long_name
+ @info = info
+ @block = block
+ end
+
+ def parse(command_runner, _)
+ block.call command_runner, true
+ end
+
+ def to_s
+ " -" + short_name + ', --' + long_name + ' ' + info
+ end
+end
+
+class OptionWithParameter
+ attr_accessor :short_name, :long_name, :info, :block, :placeholder
+
+ def initialize(short_name, long_name, info, placeholder, &block)
+ @short_name = short_name
+ @long_name = long_name
+ @info = info
+ @placeholder = placeholder
+ @block = block
+ end
+
+ def parse(command_runner, arg)
+ block.call command_runner, arg
+ end
+
+ def to_s
+ " -" + short_name + ', --' + long_name + '=' + placeholder + ' ' + info
+ end
+end
+
+class CommandParser
+ attr_accessor :command_name, :blocks, :options
+
+ def initialize(command_name)
+ @command_name = command_name
+
+ @blocks = []
+ @options = {}
+ end
+
+ def argument(name, &block)
+ @blocks.push(Argument.new(name, &block))
+ end
+
+ def option(short_name, long_name, info, &block)
+ o = Option.new(short_name, long_name, info, &block)
+
+ options[short_name] = o
+ options[long_name] = o
+ end
+
+ def option_with_parameter(short_name, long_name, info, placeholder, &block)
+ o = OptionWithParameter.new(
+ short_name, long_name,
+ info, placeholder, &block
+ )
+
+ options[short_name] = o
+ options[long_name] = o
+ end
+
+ def parse(command_runner, argv)
+ all_options, arguments = argv.partition { |i| i.start_with? '-' }
+ (blocks.zip arguments).to_h.each { |k, v| k.parse command_runner, v }
+ extracted = extract_options all_options
+ extracted.each { |k, v| options[k].parse command_runner, v }
+ end
+
+ def help
+ h = 'Usage: ' + command_name
+ blocks.each { |i| h += ' ' + i.to_s }
+ options.values.uniq.each { |i| h += "\n" + i.to_s }
+ h
+ end
+
+ private
+
+ def extract_options(all_options)
+ extracted = {}
+
+ long, short = all_options.partition { |i| i.start_with? '--' }
+
+ short.each { |i| extracted[i[1]] = i[2..-1] }
+ with_arg, wo_arg = long.partition { |i| i.include? '=' }
+ wo_arg.each { |i| extracted[i[/-*(.*)/m, 1]] = "" }
+ with_arg.each { |i| extracted[i[/-*(.*)=/m, 1]] = i[/=(.*)/m, 1] }
+ extracted.select { |k, _| !options[k].nil? }
+ end
+end