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

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

Към профила на Калоян Евтимов

Резултати

  • 4 точки от тестове
  • 1 отнета точка
  • 3 точки общо
  • 10 успешни тест(а)
  • 5 неуспешни тест(а)

Код

def determine_type(value)
return "with_pars" if value.include? "="
return "opt" if value[0] == '-' || value.include?("--")
"arg"
end
def optionize(elems, val, command_runner)
fst, sec = val.split("=")
sec = true unless sec
elems.each do |x|
x[-1].call(command_runner, sec) if x.include? fst.tr('-', '')
end
end
class CommandParser
def initialize(command_name)
@cmd = command_name
@opts = []
@with_pars = []
@args = []
@parsed = {}
end
def argument(argument, &block)
@args.push([argument])
@args[-1].push(block) if block_given?
end
def option(sh_name, l_name, hlp, &block)
@opts.push([sh_name, l_name, hlp])
@opts[-1].push(block) if block_given?
end
def option_with_parameter(sh_name, l_name, hlp, value, &block)
@with_pars.push([sh_name, l_name, hlp, value])
@with_pars[-1].push(block) if block_given?
end
def help
out = ""
out << "Usage: #{@cmd} " + @args.map { |x| "[#{x[0]}]" }.join(" ") + "\n"
@opts.each { |x, y, z| out << " -#{x}, --#{y} #{z}\n" }
@with_pars.each { |x, y, z, p| out << " -#{x}, --#{y}=#{p} #{z}\n" }
out
end
def parse(command_runner, argv)
with_pars_cp = @with_pars.dup
argv.each_with_index do |val, _|
case determine_type(val)
when "with_pars" then optionize(with_pars_cp, val, command_runner)
when "opt" then optionize(@opts, val, command_runner)
when "arg" then @args.shift[-1].call(command_runner, val)
end
end
@parsed.merge!(command_runner)
command_runner.merge!(@parsed)
end
end

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

.....F.FFF...F.

Failures:

  1) CommandParser#option_with_parameter parses a option with parameter in short format
     Failure/Error: expect(command_runner[:sort]).to eq 'time'
       
       expected: "time"
            got: :default
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -"time"
       +:default
     # /tmp/d20161113-27983-111cccx/spec.rb:89: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 basic usage message
     Failure/Error: expect(parser.help).to eq 'Usage: ls'
       
       expected: "Usage: ls"
            got: "Usage: ls \n"
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -Usage: ls
       +Usage: ls 
     # /tmp/d20161113-27983-111cccx/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)>'

  3) 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-111cccx/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)>'

  4) 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-111cccx/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)>'

  5) CommandParser when having options with and without values and parameters parses all the options and arguments correctly
     Failure/Error: expect(command_runner[:sort]).to eq 'size'
       
       expected: "size"
            got: :default
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -"size"
       +:default
     # /tmp/d20161113-27983-111cccx/spec.rb:177: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.00982 seconds
15 examples, 5 failures

Failed examples:

rspec /tmp/d20161113-27983-111cccx/spec.rb:83 # CommandParser#option_with_parameter parses a option with parameter in short format
rspec /tmp/d20161113-27983-111cccx/spec.rb:103 # CommandParser#help shows basic usage message
rspec /tmp/d20161113-27983-111cccx/spec.rb:107 # CommandParser#help shows single argument
rspec /tmp/d20161113-27983-111cccx/spec.rb:113 # CommandParser#help shows multiple arguments
rspec /tmp/d20161113-27983-111cccx/spec.rb:168 # CommandParser when having options with and without values and parameters parses all the options and arguments correctly

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

Калоян обнови решението на 09.11.2016 15:47 (преди над 7 години)

+def determine_type(value)
+ return "with_pars" if value.include? "="
+ return "opt" if value[0] == '-' || value.include?("--")
+ "arg"
+end
+
+def optionize(elems, val, command_runner)
+ fst, sec = val.split("=")
+ sec = true unless sec
+ elems.each do |x|
+ x[-1].call(command_runner, sec) if x.include? fst.tr('-', '')
+ end
+end
+
+class CommandParser
+ def initialize(command_name)
+ @cmd = command_name
+ @opts = []
+ @with_pars = []
+ @args = []
+ @parsed = {}
+ end
+
+ def argument(argument, &block)
+ @args.push([argument])
+ @args[-1].push(block) if block_given?
+ end
+
+ def option(sh_name, l_name, hlp, &block)
+ @opts.push([sh_name, l_name, hlp])
+ @opts[-1].push(block) if block_given?
+ end
+
+ def option_with_parameter(sh_name, l_name, hlp, value, &block)
+ @with_pars.push([sh_name, l_name, hlp, value])
+ @with_pars[-1].push(block) if block_given?
+ end
+
+ def help
+ out = ""
+ out << "Usage: #{@cmd} " + @args.map { |x| "[#{x[0]}]" }.join(" ") + "\n"
+ @opts.each { |x, y, z| out << " -#{x}, --#{y} #{z}\n" }
+ @with_pars.each { |x, y, z, p| out << " -#{x}, --#{y}=#{p} #{z}\n" }
+ out
+ end
+
+ def parse(command_runner, argv)
+ with_pars_cp = @with_pars.dup
+ argv.each_with_index do |val, _|
+ case determine_type(val)
+ when "with_pars" then optionize(with_pars_cp, val, command_runner)
+ when "opt" then optionize(@opts, val, command_runner)
+ when "arg" then @args.shift[-1].call(command_runner, val)
+ end
+ end
+ @parsed.merge!(command_runner)
+ command_runner.merge!(@parsed)
+ end
+end

Взех ти 1 точка заради именуването - cmd, with_pars, x, y, z, p. Използвай пълни имена - правят кода по-лесен за четене и по-разбираем. Използвайки съкращения пестиш само писане, но затрудняваш четенето на кода значително.