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

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

Към профила на Цветан Христов

Резултати

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

Код

# => It`s ugly, I know!
# => P.S. Yes I`ve heard about polymorphism! :D
module ParseArguments
def argument?(arg)
arg if !(option? arg) && !(option_with_parameter? arg)
end
def option?(arg)
arg.chars.take(1) == ['-'] && arg.length == 2 || \
arg.chars.take(2) == ['-', '-'] && !(arg.chars.include? '=')
end
def option_with_parameter?(arg)
arg.chars.take(1) == ['-'] && arg.length > 2 || \
arg.chars.take(2) == ['-', '-'] && (arg.chars.include? '=')
end
def get_arguments(argv)
argv.select { |arg| argument? arg }
end
def get_options(argv)
argv.select { |arg| option? arg }
end
def get_options_with_parameter(argv)
argv.select { |arg| option_with_parameter? arg }
end
end
class Argument
attr_accessor :name, :block
def initialize(name, block)
@name = name
@block = block
end
def parse(command_runner, arg)
@block.call command_runner, arg
end
def attributes
{name: name}
end
end
class Option
attr_accessor :short_name, :full_name, :help, :block
def initialize(short_name, full_name, help, block)
@short_name = short_name
@full_name = full_name
@help = help
@block = block
end
def exists?(options)
options.one? do |option|
option.include? ("-#{short_name}" || "--#{full_name}")
end
end
def attributes
{
short_name: short_name,
full_name: full_name,
help: help
}
end
def parse(command_runner, _)
@block.call command_runner, true
end
end
class OptionWithParameter
attr_accessor :short_name, :full_name, :help, :placeholder, :block
def initialize(short_name, full_name, help, placeholder, block)
@short_name = short_name
@full_name = full_name
@help = help
@placeholder = placeholder
@block = block
end
def attributes
{
short_name: short_name,
full_name: full_name,
help: help,
placeholder: placeholder,
}
end
end
class CommandParser
include ParseArguments
def initialize(command_name)
@command_name = command_name
@arguments = []
end
def argument(argument_name, &block)
@arguments << Argument.new(argument_name, block)
end
def option(short_name, full_name, help, &block)
@arguments << Option.new(short_name, full_name, help, block)
end
def option_with_parameter(short_name, full_name, help, placeholder, &block)
@arguments <<
OptionWithParameter.new(short_name, full_name, help, placeholder, block)
end
def parse(command_runner, argv)
arguments = get_arguments(argv)
options = get_options(argv)
@arguments.each.zip(arguments) do |element, arg|
element.parse(command_runner, arg) if element.instance_of? Argument
end
@arguments.each.zip(options) do |option, arg|
if option.instance_of?(Option) && option.exists?(options)
option.parse(command_runner, arg)
end
end
end
def help
a = argument_attributes
b = option_attributes
c = option_with_parameters_attributes
header = "Usage: #{@command_name} [#{a[:name]}]\n"
body = "\ -#{b[:short_name]}, --#{b[:full_name]} #{b[:help]}\n"
footer = "\ -#{c[:short_name]}, --#{c[:full_name]}"\
+"=#{c[:placeholder]} #{c[:help]}\n"
header + body + footer
end
private
def argument_attributes
dict = {}
@arguments.select { |element| element.instance_of? Argument }
.each { |arg| dict = arg.attributes }
dict
end
def option_attributes
dict = {}
@arguments.select { |element| element.instance_of? Option }
.each { |opt| dict = opt.attributes }
dict
end
def option_with_parameters_attributes
dict = {}
@arguments.select { |element| element.instance_of? OptionWithParameter }
.each { |opt| dict = opt.attributes }
dict
end
end

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

.....FFFFFFFFFF

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-1defk1d/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#option_with_parameter parses a option with parameter in long 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-1defk1d/spec.rb:98: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    -, --= \n"
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,4 @@
       -Usage: ls
       +Usage: ls []
       +    -, -- 
       +    -, --= 
     # /tmp/d20161113-27983-1defk1d/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    -, --= \n"
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,4 @@
        Usage: ls [FILE]
       +    -, -- 
       +    -, --= 
     # /tmp/d20161113-27983-1defk1d/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 [THIRD FILE]\n    -, -- \n    -, --= \n"
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,4 @@
       -Usage: ls [FIRST FILE] [SECOND FILE] [THIRD FILE]
       +Usage: ls [THIRD FILE]
       +    -, -- 
       +    -, --= 
     # /tmp/d20161113-27983-1defk1d/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-1defk1d/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:    ["    -, --= ", "    -d, --directory list directories themselves, not their contents"]
       the missing elements were:      ["    -a, --all do not ignore entries starting with ."]
       the extra elements were:        ["    -, --= "]
     # /tmp/d20161113-27983-1defk1d/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-1defk1d/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: nil
       
       (compared using ==)
     # /tmp/d20161113-27983-1defk1d/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(header).to eq 'Usage: ls [FIRST FILE] [SECOND FILE]'
       
       expected: "Usage: ls [FIRST FILE] [SECOND FILE]"
            got: "Usage: ls [SECOND FILE]"
       
       (compared using ==)
     # /tmp/d20161113-27983-1defk1d/spec.rb:182: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.01257 seconds
15 examples, 10 failures

Failed examples:

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

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

Цветан обнови решението на 06.11.2016 18:28 (преди над 7 години)

+module ParseArguments
+ def argument?
+ # is it really an argument?
+ end
+
+ def option?
+ # is it really an option?
+ end
+
+ def option_with_parameter?
+ # is it really an option_with_parameter?
+ end
+
+ # order of arguments matters!
+ def get_arguments(argv)
+ # return list of arguments
+ end
+
+ def get_options(argv)
+ # return list of options
+ end
+
+ def get_options_with_parameter(argv)
+ # return list of options with parameter
+ end
+end
+
+# argv: ['arg_one', '--list', 'arg_two', '-a'] ---> valid argv input
+class CommandParser
+ # include ParseArguments
+
+ def initialize(command_name)
+ @command_name = command_name
+ # @argument_block = []
+ end
+
+ def argument(_argument_name, &block)

Въпрос? Не разбрах много добре от условието за какво се използва _argument_name в метода argument? От условието пише:

parser.argument('FILE') do |runner, value|
  runner[:file] = value
end

command_runner = {}

parser.parse(command_runner, ['spec.rb'])

command_runner #=> {file: 'spec.rb'}

и после като разяснение: В този пример, FILE е името на първия позиционен аргумент в argv. Тоест, FILE има стойност spec.rb.

Това означава ли че аргумента FILE на метода, е само за да се генерира документация а не да се търси посредством него в масива argv?

Моля за разяснение, защото тук наистина се оплетох :)

Използва се само за документация. Няма как да търсиш по него, тъй като аргумента е позиционен - ключовото е позицията му, а FILE никъде не се съдържа в масива с подадените неща.

ПП. Коментарите използват Markdown - форматирай кода така, за да се чете по-добре. Виж как ти промених коментара.

+ @argument_block = block if block_given?
+ end
+
+ def option(_short_name, _full_name, _option_help, &block)
+ @option_block = block if block_given?
+ end
+
+ def parse(command_runner, argv)
+ @argument_block.call command_runner, argv[0] if @argument_block != nil
+ @option_block.call command_runner, true if @option_block != nil
+ end
+
+ def help
+ # TO-DO
+ end
+end

Цветан обнови решението на 07.11.2016 08:35 (преди над 7 години)

module ParseArguments
def argument?
# is it really an argument?
end
def option?
# is it really an option?
end
def option_with_parameter?
# is it really an option_with_parameter?
end
# order of arguments matters!
def get_arguments(argv)
# return list of arguments
end
def get_options(argv)
# return list of options
end
def get_options_with_parameter(argv)
# return list of options with parameter
end
end
# argv: ['arg_one', '--list', 'arg_two', '-a'] ---> valid argv input
class CommandParser
# include ParseArguments
def initialize(command_name)
@command_name = command_name
- # @argument_block = []
+ @argument_block = []
end
def argument(_argument_name, &block)
- @argument_block = block if block_given?
+ @argument_block << block if block_given?
end
def option(_short_name, _full_name, _option_help, &block)
@option_block = block if block_given?
end
def parse(command_runner, argv)
- @argument_block.call command_runner, argv[0] if @argument_block != nil
- @option_block.call command_runner, true if @option_block != nil
+ @argument_block.zip(argv).each do |arg_block, arg|
+ arg_block.call command_runner, arg
+ end
end
def help
# TO-DO
end
end

Цветан обнови решението на 09.11.2016 08:24 (преди над 7 години)

+# => It`s ugly, I know!
module ParseArguments
- def argument?
- # is it really an argument?
+ def argument?(arg)
+ arg if !(option? arg) && !(option_with_parameter? arg)
end
- def option?
- # is it really an option?
+ def option?(arg)
+ arg.chars.take(1) == ['-'] && arg.length == 2 || \
+ arg.chars.take(2) == ['-', '-'] && !(arg.chars.include? '=')
end
- def option_with_parameter?
- # is it really an option_with_parameter?
+ def option_with_parameter?(arg)
+ arg.chars.take(1) == ['-'] && arg.length > 2 || \
+ arg.chars.take(2) == ['-', '-'] && (arg.chars.include? '=')
end
- # order of arguments matters!
def get_arguments(argv)
- # return list of arguments
+ argv.select { |arg| argument? arg }
end
def get_options(argv)
- # return list of options
+ argv.select { |arg| option? arg }
end
def get_options_with_parameter(argv)
- # return list of options with parameter
+ argv.select { |arg| option_with_parameter? arg }
end
end
-# argv: ['arg_one', '--list', 'arg_two', '-a'] ---> valid argv input
+class Argument
+ attr_accessor :name
+ attr_accessor :block
+
+ def initialize(name, block)
+ @name = name
+ @block = block
+ end
+
+ def parse(command_runner, arg)
+ @block.call command_runner, arg
+ end
+end
+
+class Option
+ attr_accessor :short_name
+ attr_accessor :full_name
+ attr_accessor :help
+ attr_accessor :block
+
+ def initialize(short_name, full_name, help, block)
+ @short_name = short_name
+ @full_name = full_name
+ @help = help
+ @block = block
+ end
+
+ def exists?(options)
+ options.one? do |option|
+ option.include? ("-#{short_name}" || "--#{full_name}")
+ end
+ end
+
+ def parse(command_runner, _)
+ @block.call command_runner, true
+ end
+end
+
+class OptionWithParameter < Option
+ attr_accessor :placeholder
+end
+
class CommandParser
- # include ParseArguments
+ include ParseArguments
def initialize(command_name)
@command_name = command_name
- @argument_block = []
+ @arguments = []
end
- def argument(_argument_name, &block)
- @argument_block << block if block_given?
+ def argument(argument_name, &block)
+ @arguments << Argument.new(argument_name, block)
end
- def option(_short_name, _full_name, _option_help, &block)
- @option_block = block if block_given?
+ def option(short_name, full_name, help, &block)
+ @arguments << Option.new(short_name, full_name, help, block)
end
+ def option_with_parameter(short_name, full_name, help, placeholder, &_block)
+ @arguments <<
+ OptionWithParameter.new(short_name, full_name, help, placeholder)
+ end
+
def parse(command_runner, argv)
- @argument_block.zip(argv).each do |arg_block, arg|
- arg_block.call command_runner, arg
+ arguments = get_arguments(argv)
+ options = get_options(argv)
+
+ @arguments.each.zip(arguments) do |element, arg|
+ element.parse(command_runner, arg) if element.instance_of? Argument
end
+
+ @arguments.each.zip(options) do |option, arg|
+ if option.instance_of?(Option) && option.exists?(options)
+ option.parse(command_runner, arg)
+ end
+ end
end
def help
- # TO-DO
end
end

Цветан обнови решението на 09.11.2016 09:48 (преди над 7 години)

# => It`s ugly, I know!
+# => P.S. Yes I`ve heard about polymorphism! :D
module ParseArguments
def argument?(arg)
arg if !(option? arg) && !(option_with_parameter? arg)
end
def option?(arg)
arg.chars.take(1) == ['-'] && arg.length == 2 || \
arg.chars.take(2) == ['-', '-'] && !(arg.chars.include? '=')
end
def option_with_parameter?(arg)
arg.chars.take(1) == ['-'] && arg.length > 2 || \
arg.chars.take(2) == ['-', '-'] && (arg.chars.include? '=')
end
def get_arguments(argv)
argv.select { |arg| argument? arg }
end
def get_options(argv)
argv.select { |arg| option? arg }
end
def get_options_with_parameter(argv)
argv.select { |arg| option_with_parameter? arg }
end
end
class Argument
attr_accessor :name
attr_accessor :block
def initialize(name, block)
@name = name
@block = block
end
def parse(command_runner, arg)
@block.call command_runner, arg
end
+
+ def attributes
+ {name: name}
+ end
end
class Option
attr_accessor :short_name
attr_accessor :full_name
attr_accessor :help
attr_accessor :block
def initialize(short_name, full_name, help, block)
@short_name = short_name
@full_name = full_name
@help = help
@block = block
end
def exists?(options)
options.one? do |option|
option.include? ("-#{short_name}" || "--#{full_name}")
end
end
+ def attributes
+ {
+ short_name: short_name,
+ full_name: full_name,
+ help: help
+ }
+ end
+
def parse(command_runner, _)
@block.call command_runner, true
end
end
-class OptionWithParameter < Option
+class OptionWithParameter
+ attr_accessor :short_name
+ attr_accessor :full_name
+ attr_accessor :help
attr_accessor :placeholder
+ attr_accessor :block
+
+ def initialize(short_name, full_name, help, placeholder, block)
+ @short_name = short_name
+ @full_name = full_name
+ @help = help
+ @placeholder = placeholder
+ @block = block
+ end
+
+ def attributes
+ {
+ short_name: short_name,
+ full_name: full_name,
+ help: help,
+ placeholder: placeholder,
+ }
+ end
end
class CommandParser
include ParseArguments
def initialize(command_name)
@command_name = command_name
@arguments = []
end
def argument(argument_name, &block)
@arguments << Argument.new(argument_name, block)
end
def option(short_name, full_name, help, &block)
@arguments << Option.new(short_name, full_name, help, block)
end
- def option_with_parameter(short_name, full_name, help, placeholder, &_block)
+ def option_with_parameter(short_name, full_name, help, placeholder, &block)
@arguments <<
- OptionWithParameter.new(short_name, full_name, help, placeholder)
+ OptionWithParameter.new(short_name, full_name, help, placeholder, block)
end
def parse(command_runner, argv)
arguments = get_arguments(argv)
options = get_options(argv)
@arguments.each.zip(arguments) do |element, arg|
element.parse(command_runner, arg) if element.instance_of? Argument
end
@arguments.each.zip(options) do |option, arg|
if option.instance_of?(Option) && option.exists?(options)
option.parse(command_runner, arg)
end
end
end
+ def argument_attributes
+ dict = {}
+ @arguments.select { |element| element.instance_of? Argument }
+ .each { |arg| dict = arg.attributes }
+ dict
+ end
+
+ def option_attributes
+ dict = {}
+ @arguments.select { |element| element.instance_of? Option }
+ .each { |opt| dict = opt.attributes }
+ dict
+ end
+
+ def option_with_parameters_attributes
+ dict = {}
+ @arguments.select { |element| element.instance_of? OptionWithParameter }
+ .each { |opt| dict = opt.attributes }
+ dict
+ end
+
def help
+ a = argument_attributes
+ b = option_attributes
+ c = option_with_parameters_attributes
+ %(Usage: #{@command_name} [#{a[:name]}]\n\
+ -#{b[:short_name]}, --#{b[:full_name]} #{b[:help]}\n\
+ -#{c[:short_name]}, --#{c[:full_name]}=#{c[:placeholder]} #{c[:help]}\n)
end
end

Цветан обнови решението на 09.11.2016 15:29 (преди над 7 години)

# => It`s ugly, I know!
# => P.S. Yes I`ve heard about polymorphism! :D
module ParseArguments
def argument?(arg)
arg if !(option? arg) && !(option_with_parameter? arg)
end
def option?(arg)
arg.chars.take(1) == ['-'] && arg.length == 2 || \
arg.chars.take(2) == ['-', '-'] && !(arg.chars.include? '=')
end
def option_with_parameter?(arg)
arg.chars.take(1) == ['-'] && arg.length > 2 || \
arg.chars.take(2) == ['-', '-'] && (arg.chars.include? '=')
end
def get_arguments(argv)
argv.select { |arg| argument? arg }
end
def get_options(argv)
argv.select { |arg| option? arg }
end
def get_options_with_parameter(argv)
argv.select { |arg| option_with_parameter? arg }
end
end
class Argument
- attr_accessor :name
- attr_accessor :block
+ attr_accessor :name, :block
def initialize(name, block)
@name = name
@block = block
end
def parse(command_runner, arg)
@block.call command_runner, arg
end
def attributes
{name: name}
end
end
class Option
- attr_accessor :short_name
- attr_accessor :full_name
- attr_accessor :help
- attr_accessor :block
+ attr_accessor :short_name, :full_name, :help, :block
def initialize(short_name, full_name, help, block)
@short_name = short_name
@full_name = full_name
@help = help
@block = block
end
def exists?(options)
options.one? do |option|
option.include? ("-#{short_name}" || "--#{full_name}")
end
end
def attributes
{
short_name: short_name,
full_name: full_name,
help: help
}
end
def parse(command_runner, _)
@block.call command_runner, true
end
end
class OptionWithParameter
- attr_accessor :short_name
- attr_accessor :full_name
- attr_accessor :help
- attr_accessor :placeholder
- attr_accessor :block
+ attr_accessor :short_name, :full_name, :help, :placeholder, :block
def initialize(short_name, full_name, help, placeholder, block)
@short_name = short_name
@full_name = full_name
@help = help
@placeholder = placeholder
@block = block
end
def attributes
{
short_name: short_name,
full_name: full_name,
help: help,
placeholder: placeholder,
}
end
end
class CommandParser
include ParseArguments
def initialize(command_name)
@command_name = command_name
@arguments = []
end
def argument(argument_name, &block)
@arguments << Argument.new(argument_name, block)
end
def option(short_name, full_name, help, &block)
@arguments << Option.new(short_name, full_name, help, block)
end
def option_with_parameter(short_name, full_name, help, placeholder, &block)
@arguments <<
OptionWithParameter.new(short_name, full_name, help, placeholder, block)
end
def parse(command_runner, argv)
arguments = get_arguments(argv)
options = get_options(argv)
@arguments.each.zip(arguments) do |element, arg|
element.parse(command_runner, arg) if element.instance_of? Argument
end
@arguments.each.zip(options) do |option, arg|
if option.instance_of?(Option) && option.exists?(options)
option.parse(command_runner, arg)
end
end
end
+ def help
+ a = argument_attributes
+ b = option_attributes
+ c = option_with_parameters_attributes
+ %(Usage: #{@command_name} [#{a[:name]}]\n\
+ -#{b[:short_name]}, --#{b[:full_name]} #{b[:help]}\n\
+ -#{c[:short_name]}, --#{c[:full_name]}=#{c[:placeholder]} #{c[:help]}\n)
+ end
+
+ private
+
def argument_attributes
dict = {}
@arguments.select { |element| element.instance_of? Argument }
.each { |arg| dict = arg.attributes }
dict
end
def option_attributes
dict = {}
@arguments.select { |element| element.instance_of? Option }
.each { |opt| dict = opt.attributes }
dict
end
def option_with_parameters_attributes
dict = {}
@arguments.select { |element| element.instance_of? OptionWithParameter }
.each { |opt| dict = opt.attributes }
dict
- end
-
- def help
- a = argument_attributes
- b = option_attributes
- c = option_with_parameters_attributes
- %(Usage: #{@command_name} [#{a[:name]}]\n\
- -#{b[:short_name]}, --#{b[:full_name]} #{b[:help]}\n\
- -#{c[:short_name]}, --#{c[:full_name]}=#{c[:placeholder]} #{c[:help]}\n)
end
end

Цветан обнови решението на 09.11.2016 16:15 (преди над 7 години)

# => It`s ugly, I know!
# => P.S. Yes I`ve heard about polymorphism! :D
module ParseArguments
def argument?(arg)
arg if !(option? arg) && !(option_with_parameter? arg)
end
def option?(arg)
arg.chars.take(1) == ['-'] && arg.length == 2 || \
arg.chars.take(2) == ['-', '-'] && !(arg.chars.include? '=')
end
def option_with_parameter?(arg)
arg.chars.take(1) == ['-'] && arg.length > 2 || \
arg.chars.take(2) == ['-', '-'] && (arg.chars.include? '=')
end
def get_arguments(argv)
argv.select { |arg| argument? arg }
end
def get_options(argv)
argv.select { |arg| option? arg }
end
def get_options_with_parameter(argv)
argv.select { |arg| option_with_parameter? arg }
end
end
class Argument
attr_accessor :name, :block
def initialize(name, block)
@name = name
@block = block
end
def parse(command_runner, arg)
@block.call command_runner, arg
end
def attributes
{name: name}
end
end
class Option
attr_accessor :short_name, :full_name, :help, :block
def initialize(short_name, full_name, help, block)
@short_name = short_name
@full_name = full_name
@help = help
@block = block
end
def exists?(options)
options.one? do |option|
option.include? ("-#{short_name}" || "--#{full_name}")
end
end
def attributes
{
short_name: short_name,
full_name: full_name,
help: help
}
end
def parse(command_runner, _)
@block.call command_runner, true
end
end
class OptionWithParameter
attr_accessor :short_name, :full_name, :help, :placeholder, :block
def initialize(short_name, full_name, help, placeholder, block)
@short_name = short_name
@full_name = full_name
@help = help
@placeholder = placeholder
@block = block
end
def attributes
{
short_name: short_name,
full_name: full_name,
help: help,
placeholder: placeholder,
}
end
end
class CommandParser
include ParseArguments
def initialize(command_name)
@command_name = command_name
@arguments = []
end
def argument(argument_name, &block)
@arguments << Argument.new(argument_name, block)
end
def option(short_name, full_name, help, &block)
@arguments << Option.new(short_name, full_name, help, block)
end
def option_with_parameter(short_name, full_name, help, placeholder, &block)
@arguments <<
OptionWithParameter.new(short_name, full_name, help, placeholder, block)
end
def parse(command_runner, argv)
arguments = get_arguments(argv)
options = get_options(argv)
-
@arguments.each.zip(arguments) do |element, arg|
element.parse(command_runner, arg) if element.instance_of? Argument
end
-
@arguments.each.zip(options) do |option, arg|
if option.instance_of?(Option) && option.exists?(options)
option.parse(command_runner, arg)
end
end
end
def help
a = argument_attributes
b = option_attributes
c = option_with_parameters_attributes
- %(Usage: #{@command_name} [#{a[:name]}]\n\
- -#{b[:short_name]}, --#{b[:full_name]} #{b[:help]}\n\
- -#{c[:short_name]}, --#{c[:full_name]}=#{c[:placeholder]} #{c[:help]}\n)
+ header = "Usage: #{@command_name} [#{a[:name]}]\n"
+ body = "\ -#{b[:short_name]}, --#{b[:full_name]} #{b[:help]}\n"
+ footer = "\ -#{c[:short_name]}, --#{c[:full_name]}"\
+ +"=#{c[:placeholder]} #{c[:help]}\n"
+ header + body + footer
end
private
def argument_attributes
dict = {}
@arguments.select { |element| element.instance_of? Argument }
.each { |arg| dict = arg.attributes }
dict
end
def option_attributes
dict = {}
@arguments.select { |element| element.instance_of? Option }
.each { |opt| dict = opt.attributes }
dict
end
def option_with_parameters_attributes
dict = {}
@arguments.select { |element| element.instance_of? OptionWithParameter }
.each { |opt| dict = opt.attributes }
dict
end
end