Решение на Трета задача - Четене на командни аргументи от Божидар Михайлов

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

Към профила на Божидар Михайлов

Резултати

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

Код

class CommandParser
def initialize(cmd_name)
@cmd_name = cmd_name
@prepped_args = []
@prepped_opts = {}
@prepped_popts = {}
end
def argument(name, &block)
@prepped_args << Arg.new(name, block)
end
def option(s_name, l_name, desc, &block)
opt = Opt.new(s_name, l_name, desc, block)
@prepped_opts.merge!(s_name => opt, l_name => opt)
end
def option_with_parameter(s_name, l_name, descr, pholder, &block)
opt = POpt.new(s_name, l_name, descr, pholder, block)
@prepped_popts.merge!(s_name => opt, l_name => opt)
end
def parse(command_runner, argv)
@arg_blocks = @prepped_args.lazy.map &:block
argv.each do |token|
block, value = get_block_and_val(token)
block.call(command_runner, value)
end
end
def get_block_and_val(token)
return [@arg_blocks.next, token] unless token.start_with?('-')
token = token.delete('-')
if token.include?('=')
opt, val = token.split('=')
[@prepped_popts[opt].block, val]
else
[@prepped_opts[token].block, true]
end
end
def help
formatted_arg_names = @prepped_args.map { |arg| "[#{arg.name}]" }.join(' ')
help = ["Usage: #{@cmd_name} #{formatted_arg_names}"]
all_opts = @prepped_opts.merge(@prepped_popts).values.uniq
all_opts.each do |opt|
pholder = "=#{opt.pholder}" if opt.respond_to?(:pholder)
help << " -#{opt.s_name}, --#{opt.l_name}#{pholder} #{opt.desc}"
end
help.join("\n") + "\n"
end
Arg = Struct.new(:name, :block)
Opt = Struct.new(:s_name, :l_name, :desc, :block)
POpt = Struct.new(:s_name, :l_name, :desc, :pholder, :block)
end

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

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

Failures:

  1) CommandParser#option_with_parameter parses a option with parameter in short format
     Failure/Error: parser.parse(command_runner, %w(-stime))
     NoMethodError:
       undefined method `block' for nil:NilClass
     # /tmp/d20161113-27983-1fccd9y/solution.rb:39:in `get_block_and_val'
     # /tmp/d20161113-27983-1fccd9y/solution.rb:26:in `block in parse'
     # /tmp/d20161113-27983-1fccd9y/solution.rb:25:in `each'
     # /tmp/d20161113-27983-1fccd9y/solution.rb:25:in `parse'
     # /tmp/d20161113-27983-1fccd9y/spec.rb:87: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-1fccd9y/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-1fccd9y/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-1fccd9y/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: parser.parse(command_runner, %w(--all -d -ssize first.rb second.rb))
     NoMethodError:
       undefined method `block' for nil:NilClass
     # /tmp/d20161113-27983-1fccd9y/solution.rb:39:in `get_block_and_val'
     # /tmp/d20161113-27983-1fccd9y/solution.rb:26:in `block in parse'
     # /tmp/d20161113-27983-1fccd9y/solution.rb:25:in `each'
     # /tmp/d20161113-27983-1fccd9y/solution.rb:25:in `parse'
     # /tmp/d20161113-27983-1fccd9y/spec.rb:169: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.0469 seconds
15 examples, 5 failures

Failed examples:

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

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

Божидар обнови решението на 08.11.2016 21:44 (преди над 7 години)

+class CommandParser
+ def initialize(cmd_name)
+ @cmd_name = cmd_name
+ @prepped_args = []
+ @prepped_opts = {}
+ @prepped_popts = {}
+ end
+
+ def argument(name, &block)
+ @prepped_args << Arg.new(name, block)
+ end
+
+ def option(s_name, l_name, desc, &block)
+ opt = Opt.new(s_name, l_name, desc, block)
+ @prepped_opts.merge!(s_name => opt, l_name => opt)
+ end
+
+ def option_with_parameter(s_name, l_name, descr, pholder, &block)
+ opt = POpt.new(s_name, l_name, descr, pholder, block)
+ @prepped_popts.merge!(s_name => opt, l_name => opt)
+ end
+
+ def parse(command_runner, argv)
+ @arg_blocks = @prepped_args.lazy.map &:block
+ argv.each do |token|
+ block, value = get_block_and_val(token)
+ block.call(command_runner, value)
+ end
+ end
+
+ def get_block_and_val(token)
+ return [@arg_blocks.next, token] unless token.start_with?('-')
+
+ token = token.delete('-')
+ if token.include?('=')
+ opt, val = token.split('=')
+ [@prepped_popts[opt].block, val]
+ else
+ [@prepped_opts[token].block, true]
+ end
+ end
+
+ def help
+ formatted_arg_names = @prepped_args.map { |arg| "[#{arg.name}]" }.join(' ')
+ help = ["Usage: #{@cmd_name} #{formatted_arg_names}"]
+ all_opts = @prepped_opts.merge(@prepped_popts).values.uniq
+ all_opts.each do |opt|
+ pholder = "=#{opt.pholder}" if opt.respond_to?(:pholder)
+ help << " -#{opt.s_name}, --#{opt.l_name}#{pholder} #{opt.desc}"
+ end
+ help.join("\n") + "\n"
+ end
+
+ Arg = Struct.new(:name, :block)
+ Opt = Struct.new(:s_name, :l_name, :desc, :block)
+ POpt = Struct.new(:s_name, :l_name, :desc, :pholder, :block)
+end