Решение на Трета задача - Четене на командни аргументи от Валентин Георгиев

Обратно към всички решения

Към профила на Валентин Георгиев

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 9 успешни тест(а)
  • 6 неуспешни тест(а)

Код

class CommandParser
attr_accessor :cmd_name
def initialize(cmd_name)
@cmd_name = cmd_name
@arg_blocks = []
@opt_blocks = []
@opt_param_blocks = []
@args = []
@options = []
@options_param = []
end
def argument(arg, &arg_block)
@arg_blocks.push(arg_block)
arg = arg.insert(0, '[').insert(-1, ']')
@args.push(arg)
end
def option(short_option, option, text, &opt_block)
@opt_blocks.push(opt_block)
@options.push([short_option.insert(0, '-'), option.insert(0, '--'), text])
end
def option_with_parameter(short_param, opt_p, text, pl, &opt_param_block)
@opt_param_blocks.push(opt_param_block)
param = [short_param.insert(0, '-'), opt_p.insert(0, '--'), text, pl]
@options_param.push(param)
end
def parse(command_runner, argv)
argv.each do |arg|
if option? arg
call_block(@opt_blocks, command_runner, true)
elsif arg.start_with?("-")
call_block(@opt_param_blocks, command_runner, convert_param(arg))
else
call_block(@arg_blocks, command_runner, arg)
end
end
end
def call_block(blocks, command_runner, arg)
unless blocks.empty?
blocks.first.call(command_runner, arg)
blocks.shift
end
end
def help
args_doc = "Usage: #{cmd_name} #{@args.join(" ")}\n" unless @args.empty?
opts_doc = ""
opts_params_doc = ""
@options.map { |opt| opts_doc << " #{opt[0]}, #{opt[1]} #{opt[2]}\n" }
@options_param.map do |opt|
opts_params_doc << " #{opt[0]}, #{opt[1]}=#{opt[3]} #{opt[2]}\n"
end
args_doc << opts_doc << opts_params_doc
end
def convert_param(arg)
arg.start_with?("--") ? arg.split("=")[1] : arg[2..-1]
end
def option?(arg)
short_option = arg.start_with?("-") && arg.size == 2
long_option = arg.start_with?("--") && !arg.include?("=")
short_option || long_option
end
end

Лог от изпълнението

.......FFFFFF..

Failures:

  1) CommandParser#help shows basic usage message
     Failure/Error: expect(parser.help).to eq 'Usage: ls'
     NoMethodError:
       undefined method `<<' for nil:NilClass
     # /tmp/d20161113-27983-15gp2rz/solution.rb:60:in `help'
     # /tmp/d20161113-27983-15gp2rz/spec.rb:104:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

  2) CommandParser#help shows single argument
     Failure/Error: expect(parser.help).to eq 'Usage: ls [FILE]'
       
       expected: "Usage: ls [FILE]"
            got: "Usage: ls [FILE]\n"
       
       (compared using ==)
       
       Diff:
     # /tmp/d20161113-27983-15gp2rz/spec.rb:110:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

  3) CommandParser#help shows multiple arguments
     Failure/Error: expect(parser.help).to eq 'Usage: ls [FIRST FILE] [SECOND FILE] [THIRD FILE]'
       
       expected: "Usage: ls [FIRST FILE] [SECOND FILE] [THIRD FILE]"
            got: "Usage: ls [FIRST FILE] [SECOND FILE] [THIRD FILE]\n"
       
       (compared using ==)
       
       Diff:
     # /tmp/d20161113-27983-15gp2rz/spec.rb:118:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

  4) CommandParser#help shows single option help
     Failure/Error: parser.help.lines.map(&:chomp).drop(1)
     NoMethodError:
       undefined method `<<' for nil:NilClass
     # /tmp/d20161113-27983-15gp2rz/solution.rb:60:in `help'
     # /tmp/d20161113-27983-15gp2rz/spec.rb:19:in `options_help_messages'
     # /tmp/d20161113-27983-15gp2rz/spec.rb:125:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

  5) CommandParser#help shows multiple options help
     Failure/Error: parser.help.lines.map(&:chomp).drop(1)
     NoMethodError:
       undefined method `<<' for nil:NilClass
     # /tmp/d20161113-27983-15gp2rz/solution.rb:60:in `help'
     # /tmp/d20161113-27983-15gp2rz/spec.rb:19:in `options_help_messages'
     # /tmp/d20161113-27983-15gp2rz/spec.rb:137:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

  6) CommandParser#help shows options with parameter
     Failure/Error: parser.help.lines.map(&:chomp).drop(1)
     NoMethodError:
       undefined method `<<' for nil:NilClass
     # /tmp/d20161113-27983-15gp2rz/solution.rb:60:in `help'
     # /tmp/d20161113-27983-15gp2rz/spec.rb:19:in `options_help_messages'
     # /tmp/d20161113-27983-15gp2rz/spec.rb:148:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

Finished in 0.00986 seconds
15 examples, 6 failures

Failed examples:

rspec /tmp/d20161113-27983-15gp2rz/spec.rb:103 # CommandParser#help shows basic usage message
rspec /tmp/d20161113-27983-15gp2rz/spec.rb:107 # CommandParser#help shows single argument
rspec /tmp/d20161113-27983-15gp2rz/spec.rb:113 # CommandParser#help shows multiple arguments
rspec /tmp/d20161113-27983-15gp2rz/spec.rb:121 # CommandParser#help shows single option help
rspec /tmp/d20161113-27983-15gp2rz/spec.rb:130 # CommandParser#help shows multiple options help
rspec /tmp/d20161113-27983-15gp2rz/spec.rb:143 # CommandParser#help shows options with parameter

История (1 версия и 0 коментара)

Валентин обнови решението на 08.11.2016 22:52 (преди над 7 години)

+class CommandParser
+ attr_accessor :cmd_name
+
+ def initialize(cmd_name)
+ @cmd_name = cmd_name
+ @arg_blocks = []
+ @opt_blocks = []
+ @opt_param_blocks = []
+ @args = []
+ @options = []
+ @options_param = []
+ end
+
+ def argument(arg, &arg_block)
+ @arg_blocks.push(arg_block)
+ arg = arg.insert(0, '[').insert(-1, ']')
+ @args.push(arg)
+ end
+
+ def option(short_option, option, text, &opt_block)
+ @opt_blocks.push(opt_block)
+
+ @options.push([short_option.insert(0, '-'), option.insert(0, '--'), text])
+
+ end
+
+ def option_with_parameter(short_param, opt_p, text, pl, &opt_param_block)
+ @opt_param_blocks.push(opt_param_block)
+ param = [short_param.insert(0, '-'), opt_p.insert(0, '--'), text, pl]
+ @options_param.push(param)
+ end
+
+ def parse(command_runner, argv)
+ argv.each do |arg|
+ if option? arg
+ call_block(@opt_blocks, command_runner, true)
+ elsif arg.start_with?("-")
+ call_block(@opt_param_blocks, command_runner, convert_param(arg))
+ else
+ call_block(@arg_blocks, command_runner, arg)
+ end
+ end
+ end
+
+ def call_block(blocks, command_runner, arg)
+ unless blocks.empty?
+ blocks.first.call(command_runner, arg)
+ blocks.shift
+ end
+ end
+
+ def help
+ args_doc = "Usage: #{cmd_name} #{@args.join(" ")}\n" unless @args.empty?
+ opts_doc = ""
+ opts_params_doc = ""
+ @options.map { |opt| opts_doc << " #{opt[0]}, #{opt[1]} #{opt[2]}\n" }
+ @options_param.map do |opt|
+ opts_params_doc << " #{opt[0]}, #{opt[1]}=#{opt[3]} #{opt[2]}\n"
+ end
+ args_doc << opts_doc << opts_params_doc
+ end
+
+ def convert_param(arg)
+ arg.start_with?("--") ? arg.split("=")[1] : arg[2..-1]
+ end
+
+ def option?(arg)
+ short_option = arg.start_with?("-") && arg.size == 2
+ long_option = arg.start_with?("--") && !arg.include?("=")
+ short_option || long_option
+ end
+end