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

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

Към профила на Ивайло Дончев

Резултати

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

Код

class CommandParser
def initialize(command_name)
@command_name = command_name
@argument_block_dict = {}
@option_block_list = []
end
def argument(opt, &block)
@argument_block_dict[opt] = block
end
def option(short_name, full_name, description, file = nil, &block)
@option_block_list.push(
{
"block": block,
"short_name": short_name,
"full_name": full_name,
"description": description,
"parameter": file
}
)
end
def option_with_parameter(short_name, full_name, description, file, &block)
self.option(short_name, full_name, description, file, &block)
end
def parse_option(arg)
eq_index = arg.include?('=') ? arg.index('=') : -1
parameter = arg.include?('=') ? arg[(eq_index + 1)..-1] : nil
option_name = arg[(eq_index + 1)..-1]
key = arg.length == 3 ? :short_name : :full_name
found_options = @option_block_list
.select { |option| option[key] == option_name }
found_options[0][:block].call(
command_runner,
parameter ? parameter : found_options[0].fetch(:parameter, true)
)
end
def parse(command_runner, argv)
argv.each do |arg|
if arg[0] == '-'
parse_option(arg)
else
(@argument_block_dict[arg]).call(command_runner, arg)
end
end
end
def help
usage = "Usage: " + @command_name
@argument_block_dict.each do |key, _|
usage += " " + key
end
puts(usage)
@option_block_list.each do |option|
option = '-' + option[:short_name] +
", --" + option[:full_name] + ", " + option[:description]
puts(option)
end
end
end

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

FFFFFFFUsage: ls
FUsage: ls FILE
FUsage: ls FIRST FILE SECOND FILE THIRD FILE
FUsage: ls
-a, --all, do not ignore entries starting with .
FUsage: ls
-a, --all, do not ignore entries starting with .
-d, --directory, list directories themselves, not their contents
FUsage: ls
-s, --sort, sort by WORD instead of name
FFUsage: ls FIRST FILE SECOND FILE
-a, --all, do not ignore entries starting with .
-d, --directory, list directories themselves, not their contents
-s, --sort, sort by WORD instead of name
F

Failures:

  1) CommandParser#argument parses a single argument
     Failure/Error: parser.parse(command_runner, %w(Programming/ruby))
     NoMethodError:
       undefined method `call' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:47:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/spec.rb:32: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#argument parses multiple arguments
     Failure/Error: parser.parse(command_runner, %w(first.rb second.rb other/third.rb))
     NoMethodError:
       undefined method `call' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:47:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/spec.rb:42: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#option parses a single option in short form
     Failure/Error: parser.parse(command_runner, %w(-a))
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:35:in `parse_option'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:45:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/spec.rb:55: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#option parses a single option in long form
     Failure/Error: parser.parse(command_runner, %w(--all))
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:35:in `parse_option'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:45:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/spec.rb:64: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#option parses multiple options
     Failure/Error: parser.parse(command_runner, %w(--directory -a))
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:35:in `parse_option'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:45:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/spec.rb:75: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#option_with_parameter parses a option with parameter in short format
     Failure/Error: parser.parse(command_runner, %w(-stime))
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:35:in `parse_option'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:45:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/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)>'

  7) CommandParser#option_with_parameter parses a option with parameter in long format
     Failure/Error: parser.parse(command_runner, %w(--sort=time))
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:35:in `parse_option'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:45:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/spec.rb:96: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)>'

  8) CommandParser#help shows basic usage message
     Failure/Error: expect(parser.help).to eq 'Usage: ls'
       
       expected: "Usage: ls"
            got: []
       
       (compared using ==)
     # /tmp/d20161113-27983-1o1uibn/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)>'

  9) CommandParser#help shows single argument
     Failure/Error: expect(parser.help).to eq 'Usage: ls [FILE]'
       
       expected: "Usage: ls [FILE]"
            got: []
       
       (compared using ==)
     # /tmp/d20161113-27983-1o1uibn/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)>'

  10) 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: []
       
       (compared using ==)
     # /tmp/d20161113-27983-1o1uibn/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)>'

  11) CommandParser#help shows single option help
     Failure/Error: parser.help.lines.map(&:chomp).drop(1)
     NoMethodError:
       undefined method `lines' for #<Array:0x007f36529f3668>
     # /tmp/d20161113-27983-1o1uibn/spec.rb:19:in `options_help_messages'
     # /tmp/d20161113-27983-1o1uibn/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)>'

  12) CommandParser#help shows multiple options help
     Failure/Error: parser.help.lines.map(&:chomp).drop(1)
     NoMethodError:
       undefined method `lines' for #<Array:0x007f36529eed98>
     # /tmp/d20161113-27983-1o1uibn/spec.rb:19:in `options_help_messages'
     # /tmp/d20161113-27983-1o1uibn/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)>'

  13) CommandParser#help shows options with parameter
     Failure/Error: parser.help.lines.map(&:chomp).drop(1)
     NoMethodError:
       undefined method `lines' for #<Array:0x007f36529d14a0>
     # /tmp/d20161113-27983-1o1uibn/spec.rb:19:in `options_help_messages'
     # /tmp/d20161113-27983-1o1uibn/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)>'

  14) 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 `[]' for nil:NilClass
     # /tmp/d20161113-27983-1o1uibn/solution.rb:35:in `parse_option'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:45:in `block in parse'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `each'
     # /tmp/d20161113-27983-1o1uibn/solution.rb:43:in `parse'
     # /tmp/d20161113-27983-1o1uibn/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)>'

  15) CommandParser when having options with and without values and parameters generates a correct help usage
     Failure/Error: header = parser.help.lines.first.chomp
     NoMethodError:
       undefined method `lines' for #<Array:0x007f36529a0e40>
     # /tmp/d20161113-27983-1o1uibn/spec.rb:181: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.00927 seconds
15 examples, 15 failures

Failed examples:

rspec /tmp/d20161113-27983-1o1uibn/spec.rb:26 # CommandParser#argument parses a single argument
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:37 # CommandParser#argument parses multiple arguments
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:51 # CommandParser#option parses a single option in short form
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:60 # CommandParser#option parses a single option in long form
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:69 # CommandParser#option parses multiple options
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:83 # CommandParser#option_with_parameter parses a option with parameter in short format
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:92 # CommandParser#option_with_parameter parses a option with parameter in long format
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:103 # CommandParser#help shows basic usage message
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:107 # CommandParser#help shows single argument
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:113 # CommandParser#help shows multiple arguments
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:121 # CommandParser#help shows single option help
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:130 # CommandParser#help shows multiple options help
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:143 # CommandParser#help shows options with parameter
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:168 # CommandParser when having options with and without values and parameters parses all the options and arguments correctly
rspec /tmp/d20161113-27983-1o1uibn/spec.rb:180 # CommandParser when having options with and without values and parameters generates a correct help usage

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

Ивайло обнови решението на 09.11.2016 15:04 (преди над 7 години)

+class CommandParser
+ def initialize(command_name)
+ @command_name = command_name
+ @argument_block_dict = {}
+ @option_block_list = []
+ end
+
+ def argument(opt, &block)
+ @argument_block_dict[opt] = block
+ end
+
+ def option(short_name, full_name, description, file = nil, &block)
+ @option_block_list.push(
+ {
+ "block": block,
+ "short_name": short_name,
+ "full_name": full_name,
+ "description": description,
+ "parameter": file
+ }
+ )
+ end
+
+ def option_with_parameter(short_name, full_name, description, file, &block)
+ self.option(short_name, full_name, description, file, &block)
+ end
+
+ def parse_option(arg)
+ eq_index = arg.include?('=') ? arg.index('=') : -1
+ parameter = arg.include?('=') ? arg[(eq_index + 1)..-1] : nil
+ option_name = arg[(eq_index + 1)..-1]
+ key = arg.length == 3 ? :short_name : :full_name
+ found_options = @option_block_list
+ .select { |option| option[key] == option_name }
+ found_options[0][:block].call(
+ command_runner,
+ parameter ? parameter : found_options[0].fetch(:parameter, true)
+ )
+
+ end
+
+ def parse(command_runner, argv)
+ argv.each do |arg|
+ if arg[0] == '-'
+ parse_option(arg)
+ else
+ (@argument_block_dict[arg]).call(command_runner, arg)
+ end
+ end
+ end
+
+ def help
+ usage = "Usage: " + @command_name
+ @argument_block_dict.each do |key, _|
+ usage += " " + key
+ end
+ puts(usage)
+
+ @option_block_list.each do |option|
+ option = '-' + option[:short_name] +
+ ", --" + option[:full_name] + ", " + option[:description]
+ puts(option)
+ end
+ end
+end