Решение на Трета задача - Четене на командни аргументи от Константин Нецов

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

Към профила на Константин Нецов

Резултати

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

Код

module M
def self.check_argv(argv)
argv[0].include?("-") || argv[0].include?("--")
end
def self.check_opt_param(argv, o)
if argv.include?("--")
return true if argv.split("=")[0][2..-1] == o[:f_n]
elsif argv.include?("-")
return true if argv.split("=")[0][1..1] == o[:s_n]
end
end
def self.p_opt(e)
e.size == 1 ? (return "-#{e}") : (return "--#{e}")
end
def self.extract(s)
return s.split("=")[1] if s.include?("=")
return s[2..-1] if s.include?("-")
end
def self.format_for_help(el, op)
if op == 1
"#{M.p_opt(el[:s_n])}, #{M.p_opt(el[:f_n])} #{el[:desc]}"
elsif op == 2
"#{M.p_opt(el[:s_n])}, #{M.p_opt(el[:f_n])}=#{el[:p]} #{el[:desc]}"
end
end
def self.format_help(s)
s.split("\n").each_with_index do |row, i|
row.sub!(/^\s+/, "") if i == 0
row.sub!(/^\s+/, " ")
end
end
end
class CommandParser
include M
def initialize(command_name)
@command_name = command_name
@command_runner = {}
@args_ns = []
@a = {}
@opt = []
@opt_p = []
@c = {}
@d = {}
end
def argument(named_opt_param)
@args_ns << named_opt_param
yield(@a, nil)
end
def option(s_n, f_n, desc)
@opt << {s_n: s_n, f_n: f_n, desc: desc}
yield(@c, true) if block_given?
end
def option_with_parameter(s_n, f_n, desc, p)
@opt_p << {s_n: s_n, f_n: f_n, desc: desc, p: p }
yield(@d, nil) if block_given?
end
def parse(command_runner, argv)
@a.keys.each_with_index { |e, i| command_runner[e.to_sym] = argv[i] }
if M.check_argv(argv[0]) && !argv[0].include?("=")
command_runner[@c.keys[0]] = @c.values[0]
end
if M.check_argv(argv[0]) && argv[0].include?("=")
if M.check_opt_param(argv[0], @opt_p[0])
command_runner[@d.keys[0]] = M.extract(argv[0])
end
end
end
def help
txt = <<-HELP
Usage: #{@command_name} #{arg_help}
#{opt_help(@opt, 1)}
#{opt_help(@opt_p, 2)}
HELP
M.format_help(txt).join("\n")
end
def arg_help
@args_ns.map { |e| "[#{e}]" }.join(" ") unless @args_ns.empty?
end
def opt_help(h, o)
a = []
h.each do |el|
a << M.format_for_help(el, o)
end
a.join
end
end

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

....FF.FFFFFFFF

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-tc50cl/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: :default
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -"time"
       +:default
     # /tmp/d20161113-27983-tc50cl/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    \n    "
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,4 @@
       -Usage: ls
       +Usage: ls 
       +    
       +    
     # /tmp/d20161113-27983-tc50cl/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    \n    "
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,4 @@
        Usage: ls [FILE]
       +    
       +    
     # /tmp/d20161113-27983-tc50cl/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    \n    "
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,4 @@
        Usage: ls [FIRST FILE] [SECOND FILE] [THIRD FILE]
       +    
       +    
     # /tmp/d20161113-27983-tc50cl/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#help shows single option help
     Failure/Error: expect(options_help_messages(parser)).to match_array([
       expected collection contained:  ["    -a, --all do not ignore entries starting with ."]
       actual collection contained:    ["    ", "    -a, --all do not ignore entries starting with ."]
       the extra elements were:        ["    "]
     # /tmp/d20161113-27983-tc50cl/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)>'

  7) CommandParser#help shows multiple options help
     Failure/Error: expect(options_help_messages(parser)).to match_array([
       expected collection contained:  ["    -a, --all do not ignore entries starting with .", "    -d, --directory list directories themselves, not their contents"]
       actual collection contained:    ["    ", "    -a, --all do not ignore entries starting with .-d, --directory list directories themselves, not their contents"]
       the missing elements were:      ["    -a, --all do not ignore entries starting with .", "    -d, --directory list directories themselves, not their contents"]
       the extra elements were:        ["    ", "    -a, --all do not ignore entries starting with .-d, --directory list directories themselves, not their contents"]
     # /tmp/d20161113-27983-tc50cl/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)>'

  8) CommandParser#help shows options with parameter
     Failure/Error: expect(options_help_messages(parser)).to match_array([
       expected collection contained:  ["    -s, --sort=WORD sort by WORD instead of name"]
       actual collection contained:    ["    ", "    -s, --sort=WORD sort by WORD instead of name"]
       the extra elements were:        ["    "]
     # /tmp/d20161113-27983-tc50cl/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)>'

  9) CommandParser when having options with and without values and parameters parses all the options and arguments correctly
     Failure/Error: expect(command_runner[:first_file]).to eq 'first.rb'
       
       expected: "first.rb"
            got: "--all"
       
       (compared using ==)
     # /tmp/d20161113-27983-tc50cl/spec.rb:171: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 when having options with and without values and parameters generates a correct help usage
     Failure/Error: expect(options_help_messages(parser)).to match_array([
       expected collection contained:  ["    -a, --all do not ignore entries starting with .", "    -d, --directory list directories themselves, not their contents", "    -s, --sort=WORD sort by WORD instead of name"]
       actual collection contained:    ["    -a, --all do not ignore entries starting with .-d, --directory list directories themselves, not their contents", "    -s, --sort=WORD sort by WORD instead of name"]
       the missing elements were:      ["    -a, --all do not ignore entries starting with .", "    -d, --directory list directories themselves, not their contents"]
       the extra elements were:        ["    -a, --all do not ignore entries starting with .-d, --directory list directories themselves, not their contents"]
     # /tmp/d20161113-27983-tc50cl/spec.rb:184: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.01262 seconds
15 examples, 10 failures

Failed examples:

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

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

Константин обнови решението на 09.11.2016 13:07 (преди над 7 години)

+module M
+ def self.check_argv(argv)
+ argv[0].include?("-") || argv[0].include?("--")
+ end
+
+ def self.check_opt_param(argv, o)
+ if argv.include?("--")
+ return true if argv.split("=")[0][2..-1] == o[:f_n]
+ elsif argv.include?("-")
+ return true if argv.split("=")[0][1..1] == o[:s_n]
+ end
+ end
+
+ def self.p_opt(e)
+ e.size == 1 ? (return "-#{e}") : (return "--#{e}")
+ end
+
+ def self.extract(s)
+ return s.split("=")[1] if s.include?("=")
+ return s[2..-1] if s.include?("-")
+ end
+
+ def self.format_for_help(el, op)
+ if op == 1
+ "#{M.p_opt(el[:s_n])}, #{M.p_opt(el[:f_n])} #{el[:desc]}"
+ elsif op == 2
+ "#{M.p_opt(el[:s_n])}, #{M.p_opt(el[:f_n])}=#{el[:p]} #{el[:desc]}"
+ end
+ end
+
+ def self.format_help(s)
+ s.split("\n").each_with_index do |row, i|
+ row.sub!(/^\s+/, "") if i == 0
+ row.sub!(/^\s+/, " ")
+ end
+ end
+end
+
+class CommandParser
+ include M
+ def initialize(command_name)
+ @command_name = command_name
+ @command_runner = {}
+ @args_ns = []
+ @a = {}
+ @opt = []
+ @opt_p = []
+ @c = {}
+ @d = {}
+ end
+
+ def argument(named_opt_param)
+ @args_ns << named_opt_param
+ yield(@a, nil)
+ end
+
+ def option(s_n, f_n, desc)
+ @opt << {s_n: s_n, f_n: f_n, desc: desc}
+ yield(@c, true) if block_given?
+ end
+
+ def option_with_parameter(s_n, f_n, desc, p)
+ @opt_p << {s_n: s_n, f_n: f_n, desc: desc, p: p }
+ yield(@d, nil) if block_given?
+ end
+
+ def parse(command_runner, argv)
+ @a.keys.each_with_index { |e, i| command_runner[e.to_sym] = argv[i] }
+ if M.check_argv(argv[0]) && !argv[0].include?("=")
+ command_runner[@c.keys[0]] = @c.values[0]
+ end
+ if M.check_argv(argv[0]) && argv[0].include?("=")
+ if M.check_opt_param(argv[0], @opt_p[0])
+ command_runner[@d.keys[0]] = M.extract(argv[0])
+ end
+ end
+ end
+
+ def help
+ txt = <<-HELP
+ Usage: #{@command_name} #{arg_help}
+ #{opt_help(@opt, 1)}
+ #{opt_help(@opt_p, 2)}
+ HELP
+ M.format_help(txt).join("\n")
+ end
+
+ def arg_help
+ @args_ns.map { |e| "[#{e}]" }.join(" ") unless @args_ns.empty?
+ end
+
+ def opt_help(h, o)
+ a = []
+ h.each do |el|
+ a << M.format_for_help(el, o)
+ end
+ a.join
+ end
+end