Решение на Трета задача - Четене на командни аргументи от Стефан Якимов

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

Към профила на Стефан Якимов

Резултати

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

Код

# frozen_string_literal: true
class CommandParser
def initialize(bin_command)
@bin_command = bin_command
@known_arguments = {}
@known_options = []
@helper = Helper.new
end
def argument(argument_name, &block)
@known_arguments[argument_name] = block
end
def option(short_handle, long_handle, description)
@known_options << {
short_handle: short_handle,
long_handle: long_handle,
description: description
}
end
def option_with_parameter(short, long, description, argument_name, &block)
@known_options << {
short_handle: short,
long_handle: long,
description: description,
argument_name: argument_name,
block: block
}
end
def parse(command_runner, argv)
@argv = argv
parse_arguments command_runner
parse_options command_runner
end
def help
[
@helper.create_header(@known_arguments, @bin_command),
@helper.create_body(@known_options)
].join("\n")
end
private
def parse_arguments(command_runner)
@known_arguments
.zip(@helper.extract_arguments(@argv)) do |argument, value|
argument[1].call(command_runner, value)
end
command_runner
end
def parse_options(command_runner)
@helper.extract_options(@argv).each do |argument_value_option|
@known_options.each do |known_option|
option, value = @helper.split_input(argument_value_option)
@helper.add_option(command_runner, known_option, option, value)
end
end
command_runner
end
end
class Helper
def create_header(known_arguments, bin_command)
arguments_help = known_arguments.keys.map { |key| "[#{key}]" }.join(' ')
"Usage: #{bin_command} #{arguments_help}"
end
def create_body(known_options)
known_options.map do |known_option|
s = " -#{known_option[:short_handle]}, --#{known_option[:long_handle]}"
s += "=#{known_option[:argument_name]}" if known_option[:argument_name]
s + ' ' + known_option[:description]
end.join("\n")
end
def split_input(argument_value_option)
argument_value_option.chomp('-').reverse.chomp('-').reverse.split('=')
end
def extract_arguments(argv)
argv.select { |argument| !option?(argument) }
end
def extract_options(argv)
argv.select { |argument| option?(argument) }
end
def option?(argument_value)
argument_value.start_with?('-', '--')
end
def add_option(command_runner, known_option, option, value)
return unless option == known_option[:short_handle] ||
known_option[:long_handle]
if known_option[:argument_name]
known_option[:block].call(command_runner, value)
else
command_runner[known_option[:long_handle].to_sym] = true
end
end
end

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

....FF.FFF...F.

Failures:

  1) CommandParser#option parses multiple options
     Failure/Error: expect(command_runner[:dir]).to be true
       
       expected #<TrueClass:20> => true
            got #<Symbol:252508> => :default
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
       
       
       Diff:
       @@ -1,2 +1,2 @@
       -true
       +:default
     # /tmp/d20161113-27983-y0h85y/spec.rb:77: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#option_with_parameter parses a option with parameter in short format
     Failure/Error: expect(command_runner[:sort]).to eq 'time'
       
       expected: "time"
            got: nil
       
       (compared using ==)
     # /tmp/d20161113-27983-y0h85y/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)>'

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

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

  5) 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-y0h85y/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)>'

  6) CommandParser when having options with and without values and parameters parses all the options and arguments correctly
     Failure/Error: expect(command_runner[:dir]).to be true
       
       expected #<TrueClass:20> => true
            got #<Symbol:252508> => :default
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       `expect(actual).to eq(expected)` if you don't care about
       object identity in this example.
       
       
       Diff:
       @@ -1,2 +1,2 @@
       -true
       +:default
     # /tmp/d20161113-27983-y0h85y/spec.rb:175: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.01142 seconds
15 examples, 6 failures

Failed examples:

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

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

Стефан обнови решението на 08.11.2016 16:22 (преди около 8 години)

+# frozen_string_literal: true
+class CommandParser
+ def initialize(bin_command)
+ @bin_command = bin_command
+ @known_arguments = {}
+ @known_options = []
+ @helper = Helper.new
+ end
+
+ def argument(argument_name, &block)
+ @known_arguments[argument_name] = block
+ end
+
+ def option(short_handle, long_handle, description)
+ @known_options << {
+ short_handle: short_handle,
+ long_handle: long_handle,
+ description: description
+ }
+ end
+
+ def option_with_parameter(short, long, description, argument_name, &block)
+ @known_options << {
+ short_handle: short,
+ long_handle: long,
+ description: description,
+ argument_name: argument_name,
+ block: block
+ }
+ end
+
+ def parse(command_runner, argv)
+ @argv = argv
+ parse_arguments command_runner
+ parse_options command_runner
+ end
+
+ def help
+ [
+ @helper.create_header(@known_arguments, @bin_command),
+ @helper.create_body(@known_options)
+ ].join("\n")
+ end
+
+ private
+
+ def parse_arguments(command_runner)
+ @known_arguments
+ .zip(@helper.extract_arguments(@argv)) do |argument, value|
+ argument[1].call(command_runner, value)
+ end
+
+ command_runner
+ end
+
+ def parse_options(command_runner)
+ @helper.extract_options(@argv).each do |argument_value_option|
+ @known_options.each do |known_option|
+ option, value = @helper.split_input(argument_value_option)
+ @helper.add_option(command_runner, known_option, option, value)
+ end
+ end
+
+ command_runner
+ end
+end
+
+class Helper
+ def create_header(known_arguments, bin_command)
+ arguments_help = known_arguments.keys.map { |key| "[#{key}]" }.join(' ')
+ "Usage: #{bin_command} #{arguments_help}"
+ end
+
+ def create_body(known_options)
+ known_options.map do |known_option|
+ s = " -#{known_option[:short_handle]}, --#{known_option[:long_handle]}"
+ s += "=#{known_option[:argument_name]}" if known_option[:argument_name]
+ s + ' ' + known_option[:description]
+ end.join("\n")
+ end
+
+ def split_input(argument_value_option)
+ argument_value_option.chomp('-').reverse.chomp('-').reverse.split('=')
+ end
+
+ def extract_arguments(argv)
+ argv.select { |argument| !argument.start_with?('-', '--') }
+ end
+
+ def extract_options(argv)
+ argv.select { |argument| argument.start_with?('-', '--') }
+ end
+
+ def add_option(command_runner, known_option, option, value)
+ return unless option == known_option[:short_handle] ||
+ known_option[:long_handle]
+
+ if known_option[:argument_name]
+ known_option[:block].call(command_runner, value)
+ else
+ command_runner[known_option[:long_handle].to_sym] = true
+ end
+ end
+end

Стефан обнови решението на 08.11.2016 16:32 (преди около 8 години)

# frozen_string_literal: true
class CommandParser
def initialize(bin_command)
@bin_command = bin_command
@known_arguments = {}
@known_options = []
@helper = Helper.new
end
def argument(argument_name, &block)
@known_arguments[argument_name] = block
end
def option(short_handle, long_handle, description)
@known_options << {
short_handle: short_handle,
long_handle: long_handle,
description: description
}
end
def option_with_parameter(short, long, description, argument_name, &block)
@known_options << {
short_handle: short,
long_handle: long,
description: description,
argument_name: argument_name,
block: block
}
end
def parse(command_runner, argv)
@argv = argv
parse_arguments command_runner
parse_options command_runner
end
def help
[
@helper.create_header(@known_arguments, @bin_command),
@helper.create_body(@known_options)
].join("\n")
end
private
def parse_arguments(command_runner)
@known_arguments
.zip(@helper.extract_arguments(@argv)) do |argument, value|
argument[1].call(command_runner, value)
end
command_runner
end
def parse_options(command_runner)
@helper.extract_options(@argv).each do |argument_value_option|
@known_options.each do |known_option|
option, value = @helper.split_input(argument_value_option)
@helper.add_option(command_runner, known_option, option, value)
end
end
command_runner
end
end
class Helper
def create_header(known_arguments, bin_command)
arguments_help = known_arguments.keys.map { |key| "[#{key}]" }.join(' ')
"Usage: #{bin_command} #{arguments_help}"
end
def create_body(known_options)
known_options.map do |known_option|
s = " -#{known_option[:short_handle]}, --#{known_option[:long_handle]}"
s += "=#{known_option[:argument_name]}" if known_option[:argument_name]
s + ' ' + known_option[:description]
end.join("\n")
end
def split_input(argument_value_option)
argument_value_option.chomp('-').reverse.chomp('-').reverse.split('=')
end
def extract_arguments(argv)
- argv.select { |argument| !argument.start_with?('-', '--') }
+ argv.select { |argument| !option?(argument) }
end
def extract_options(argv)
- argv.select { |argument| argument.start_with?('-', '--') }
+ argv.select { |argument| option?(argument) }
+ end
+
+ def option?(argument_value)
+ argument_value.start_with?('-', '--')
end
def add_option(command_runner, known_option, option, value)
return unless option == known_option[:short_handle] ||
known_option[:long_handle]
if known_option[:argument_name]
known_option[:block].call(command_runner, value)
else
command_runner[known_option[:long_handle].to_sym] = true
end
end
end