Spec-Zone.ru › Ruby 2.6

класс OptionParser

Родитель:
Объект

OptionParser

Введение

OptionParser — это класс для анализа командно-строчных опций. Он намного более продвинутый, но и проще в использовании, чем GetoptLong, и является более ориентированным на Ruby решением.

Особенности

  1. Спецификация аргументов и код для их обработки написаны в одном месте.

  2. Он может выводить сводку опций; вам не нужно отдельно поддерживать эту строку.

  3. Необязательные и обязательные аргументы задаются очень элегантно.

  4. Аргументы могут быть автоматически преобразованы в указанный класс.

  5. Аргументы могут быть ограничены определённым набором.

Все эти особенности продемонстрированы в примерах ниже. Полная документация находится по адресу make_switch.

Минимальный пример

require 'optparse'

options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!

p options
p ARGV

Генерация справки

OptionParser может использоваться для автоматической генерации справки по вашим командам:

require 'optparse'

Options = Struct.new(:name)

class Parser
  def self.parse(options)
    args = Options.new("world")

    opt_parser = OptionParser.new do |opts|
      opts.banner = "Usage: example.rb [options]"

      opts.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
        args.name = n
      end

      opts.on("-h", "--help", "Prints this help") do
        puts opts
        exit
      end
    end

    opt_parser.parse!(options)
    return args
  end
end
options = Parser.parse %w[--help]

#=>
   # Usage: example.rb [options]
   #     -n, --name=NAME                  Name to say hello to
   #     -h, --help                       Prints this help

Обязательные аргументы

Для опций, требующих аргумент, строки спецификации опций могут содержать имя опции в верхнем регистре. Если опция используется без требуемого аргумента, будет возбуждено исключение.

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.on("-r", "--require LIBRARY",
            "Require the LIBRARY before executing your script") do |lib|
    puts "You required #{lib}!"
  end
end.parse!

Используется:

$ ruby optparse-test.rb -r
optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument)
$ ruby optparse-test.rb -r my-library
You required my-library!

Преобразование типов

OptionParser поддерживает возможность принудительного преобразования аргументов командной строки в объекты для нас.

OptionParser поставляется с несколькими готовыми типами преобразования типов. Это:

  • Date — Всё, что принимается Date.parse

  • DateTime — Всё, что принимается DateTime.parse

  • Time — Всё, что принимается Time.httpdate или Time.parse

  • URI — Всё, что принимается URI.parse

  • Shellwords — Всё, что принимается Shellwords.shellwords

  • String — Любая непустая строка

  • Integer — Любое целое число. Преобразует восьмеричные числа. (например, 124, -3, 040)

  • Float — Любое вещественное число. (например, 10, 3.14, -100E+13)

  • Numeric — Любое целое число, вещественное число или рациональное число (1, 3.4, 1/3)

  • DecimalInteger — Как Integer, но без восьмеричного формата.

  • OctalInteger — Как Integer, но без десятичного формата.

  • DecimalNumeric — Десятичное целое число или вещественное число.

  • TrueClass — Принимает '+, yes, true, -, no, false' и по умолчанию как true

  • FalseClass — То же, что и TrueClass, но по умолчанию false

  • Array — Строки, разделенные запятыми (например, 1,2,3)

  • Regexp — Регулярные выражения. Также включает опции.

Мы также можем добавить наши собственные преобразования, о которых мы расскажем вскоре.

Использование встроенных преобразований

В качестве примера используется встроенное преобразование Time. Другие встроенные преобразования ведут себя аналогично. OptionParser будет пытаться разобрать аргумент как Time. Если это удается, то время будет передано в блок обработки. В противном случае будет возбуждено исключение.

require 'optparse'
require 'optparse/time'
OptionParser.new do |parser|
  parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
    p time
  end
end.parse!

Используется:

$ ruby optparse-test.rb  -t nonsense
... invalid argument: -t nonsense (OptionParser::InvalidArgument)
$ ruby optparse-test.rb  -t 10-11-12
2010-11-12 00:00:00 -0500
$ ruby optparse-test.rb  -t 9:30
2014-08-13 09:30:00 -0400

Создание пользовательских преобразований

Метод accept в OptionParser может быть использован для создания преобразователей. Он указывает, какой блок преобразования вызывать, когда указан класс. В примере ниже используется метод для получения объекта User перед тем, как блок обработки on его получит.

require 'optparse'

User = Struct.new(:id, :name)

def find_user id
  not_found = ->{ raise "No User Found for id #{id}" }
  [ User.new(1, "Sam"),
    User.new(2, "Gandalf") ].find(not_found) do |u|
    u.id == id
  end
end

op = OptionParser.new
op.accept(User) do |user_id|
  find_user user_id.to_i
end

op.on("--user ID", User) do |user|
  puts user
end

op.parse!

Используется:

$ ruby optparse-test.rb --user 1
#<struct User id=1, name="Sam">
$ ruby optparse-test.rb --user 2
#<struct User id=2, name="Gandalf">
$ ruby optparse-test.rb --user 3
optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)

Сохранение опций в Hash

Опция into метода order, parse и т. д. сохраняет опции командной строки в Hash.

require 'optparse'

params = {}
OptionParser.new do |opts|
  opts.on('-a')
  opts.on('-b NUM', Integer)
  opts.on('-v', '--verbose')
end.parse!(into: params)

p params

Используется:

$ ruby optparse-test.rb -a
{:a=>true}
$ ruby optparse-test.rb -a -v
{:a=>true, :verbose=>true}
$ ruby optparse-test.rb -a -b 100
{:a=>true, :b=>100}

Полный пример

Следующий пример — полная программа Ruby. Вы можете запустить её и увидеть эффект от указания различных опций. Это, вероятно, лучший способ изучить возможности optparse.

require 'optparse'
require 'optparse/time'
require 'ostruct'
require 'pp'

class OptparseExample
  Version = '1.0.0'

  CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
  CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }

  class ScriptOptions
    attr_accessor :library, :inplace, :encoding, :transfer_type,
                  :verbose, :extension, :delay, :time, :record_separator,
                  :list

    def initialize
      self.library = []
      self.inplace = false
      self.encoding = "utf8"
      self.transfer_type = :auto
      self.verbose = false
    end

    def define_options(parser)
      parser.banner = "Usage: example.rb [options]"
      parser.separator ""
      parser.separator "Specific options:"

      # add additional options
      perform_inplace_option(parser)
      delay_execution_option(parser)
      execute_at_time_option(parser)
      specify_record_separator_option(parser)
      list_example_option(parser)
      specify_encoding_option(parser)
      optional_option_argument_with_keyword_completion_option(parser)
      boolean_verbose_option(parser)

      parser.separator ""
      parser.separator "Common options:"
      # No argument, shows at tail.  This will print an options summary.
      # Try it and see!
      parser.on_tail("-h", "--help", "Show this message") do
        puts parser
        exit
      end
      # Another typical switch to print the version.
      parser.on_tail("--version", "Show version") do
        puts Version
        exit
      end
    end

    def perform_inplace_option(parser)
      # Specifies an optional option argument
      parser.on("-i", "--inplace [EXTENSION]",
                "Edit ARGV files in place",
                "(make backup if EXTENSION supplied)") do |ext|
        self.inplace = true
        self.extension = ext || ''
        self.extension.sub!(/\A\.?(?=.)/, ".")  # Ensure extension begins with dot.
      end
    end

    def delay_execution_option(parser)
      # Cast 'delay' argument to a Float.
      parser.on("--delay N", Float, "Delay N seconds before executing") do |n|
        self.delay = n
      end
    end

    def execute_at_time_option(parser)
      # Cast 'time' argument to a Time object.
      parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
        self.time = time
      end
    end

    def specify_record_separator_option(parser)
      # Cast to octal integer.
      parser.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
                "Specify record separator (default \\0)") do |rs|
        self.record_separator = rs
      end
    end

    def list_example_option(parser)
      # List of arguments.
      parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
        self.list = list
      end
    end

    def specify_encoding_option(parser)
      # Keyword completion.  We are specifying a specific set of arguments (CODES
      # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
      # the shortest unambiguous text.
      code_list = (CODE_ALIASES.keys + CODES).join(', ')
      parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
                "(#{code_list})") do |encoding|
        self.encoding = encoding
      end
    end

    def optional_option_argument_with_keyword_completion_option(parser)
      # Optional '--type' option argument with keyword completion.
      parser.on("--type [TYPE]", [:text, :binary, :auto],
                "Select transfer type (text, binary, auto)") do |t|
        self.transfer_type = t
      end
    end

    def boolean_verbose_option(parser)
      # Boolean switch.
      parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
        self.verbose = v
      end
    end
  end

  #
  # Return a structure describing the options.
  #
  def parse(args)
    # The options specified on the command line will be collected in
    # *options*.

    @options = ScriptOptions.new
    @args = OptionParser.new do |parser|
      @options.define_options(parser)
      parser.parse!(args)
    end
    @options
  end

  attr_reader :parser, :options
end  # class OptparseExample

example = OptparseExample.new
options = example.parse(ARGV)
pp options # example.options
pp ARGV

Shell Completion

Для современных оболочек (например, bash, zsh и т. д.) вы можете использовать автодополнение для опций командной строки.

Дополнительная документация

Приведённых примеров должно быть достаточно, чтобы понять, как использовать этот класс. Если у вас есть вопросы, подайте заявку на сайте bugs.ruby-lang.org.

Константы

DecimalInteger

Формат десятичного целого числа, для преобразования в Integer.

DecimalNumeric

Формат десятичного целого/вещественного числа, для преобразования в Integer для целого формата, Float для вещественного формата.

OctalInteger

Формат восьмеричного/шестнадцатеричного/двоичного целого числа, как в Ruby/C, для преобразования в Integer.

Атрибуты

banner[W]

Заголовок-баннер, предшествующий описанию.

default_argv[RW]

Строки, которые будут обработаны по умолчанию.

program_name[W]

Имя программы, которое будет выводиться в сообщении об ошибке и в баннере по умолчанию, по умолчанию равно $0.

release[W]

Код релиза

set_banner[W]

Заголовок-баннер, предшествующий описанию.

set_program_name[W]

Имя программы, которое будет выводиться в сообщении об ошибке и в баннере по умолчанию, по умолчанию равно $0.

set_summary_indent[RW]

Отступ для сводки. Должен быть String (или иметь + String метод).

set_summary_width[RW]

Ширина части сводки со списком опций. Должна быть Numeric.

summary_indent[RW]

Отступ для сводки. Должен быть String (или иметь + String метод).

summary_width[RW]

Ширина части сводки со списком опций. Должна быть Numeric.

version[W]

Версия

Публичные методы класса

accept(*args, &blk) Показать исходный код
# File lib/optparse.rb, line 1126
def self.accept(*args, &blk) top.accept(*args, &blk) end

См. accept.

each_const(path, base = ::Object) Показать исходный код
# File lib/optparse/version.rb, line 50
def each_const(path, base = ::Object)
  path.split(/::|\//).inject(base) do |klass, name|
    raise NameError, path unless Module === klass
    klass.constants.grep(/#{name}/i) do |c|
      klass.const_defined?(c) or next
      klass.const_get(c)
    end
  end
end
getopts(*args) Показать исходный код
# File lib/optparse.rb, line 1727
def self.getopts(*args)
  new.getopts(*args)
end

См. getopts.

inc(arg, default = nil) Показать исходный код
# File lib/optparse.rb, line 1062
def self.inc(arg, default = nil)
  case arg
  when Integer
    arg.nonzero?
  when nil
    default.to_i + 1
  end
end

Возвращает увеличенное значение default согласно arg.

new(banner = nil, width = 32, indent = ' ' * 4) { |self| ... } Показать исходный код
# File lib/optparse.rb, line 1081
def initialize(banner = nil, width = 32, indent = ' ' * 4)
  @stack = [DefaultList, List.new, List.new]
  @program_name = nil
  @banner = banner
  @summary_width = width
  @summary_indent = indent
  @default_argv = ARGV
  add_officious
  yield self if block_given?
end

Инициализирует экземпляр и передает его, если вызывается с блоком.

banner

Сообщение баннера.

width

Ширина сводки.

indent

Отступ сводки.

reject(*args, &blk) Показать исходный код
# File lib/optparse.rb, line 1139
def self.reject(*args, &blk) top.reject(*args, &blk) end

См. reject.

search_const(klass, name) { |klass, cname, const| ... } Показать исходный код
# File lib/optparse/version.rb, line 60
def search_const(klass, name)
  klasses = [klass]
  while klass = klasses.shift
    klass.constants.each do |cname|
      klass.const_defined?(cname) or next
      const = klass.const_get(cname)
      yield klass, cname, const if name === cname
      klasses << const if Module === const and const != ::Object
    end
  end
end
show_version(*pkgs) Показать исходный код
# File lib/optparse/version.rb, line 5
def show_version(*pkgs)
  progname = ARGV.options.program_name
  result = false
  show = proc do |klass, cname, version|
    str = "#{progname}"
    unless klass == ::Object and cname == :VERSION
      version = version.join(".") if Array === version
      str << ": #{klass}" unless klass == Object
      str << " version #{version}"
    end
    [:Release, :RELEASE].find do |rel|
      if klass.const_defined?(rel)
        str << " (#{klass.const_get(rel)})"
      end
    end
    puts str
    result = true
  end
  if pkgs.size == 1 and pkgs[0] == "all"
    self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version|
      unless cname[1] == ?e and klass.const_defined?(:Version)
        show.call(klass, cname.intern, version)
      end
    end
  else
    pkgs.each do |pkg|
      begin
        pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)}
        v = case
            when pkg.const_defined?(:Version)
              pkg.const_get(n = :Version)
            when pkg.const_defined?(:VERSION)
              pkg.const_get(n = :VERSION)
            else
              n = nil
              "unknown"
            end
        show.call(pkg, n, v)
      rescue NameError
      end
    end
  end
  result
end
terminate(arg = nil) Показать исходный код
# File lib/optparse.rb, line 1106
def self.terminate(arg = nil)
  throw :terminate, arg
end
top() Показать исходный код
# File lib/optparse.rb, line 1111
def self.top() DefaultList end
with(*args, &block) Показать исходный код
# File lib/optparse.rb, line 1053
def self.with(*args, &block)
  opts = new(*args)
  opts.instance_eval(&block)
  opts
end

Инициализирует новый экземпляр и выполняет необязательный блок в контексте экземпляра. Аргументы args передаются в new, см. там описание параметров.

Этот метод устарел, его поведение соответствует более старому методу new.

Общедоступные методы экземпляров

abort(mesg = $!) Показать исходный код
# File lib/optparse.rb, line 1220
def abort(mesg = $!)
  super("#{program_name}: #{mesg}")
end
Вызывает метод суперкласса Kernel#abort
accept(*args, &blk) Показать исходный код
# File lib/optparse.rb, line 1122
def accept(*args, &blk) top.accept(*args, &blk) end

Направляет на принятие указанного класса t. Строка аргумента передается в блок, в котором она должна быть преобразована в желаемый класс.

t

Указатель класса аргумента, любой объект, включая Class.

pat

Шаблон для аргумента, по умолчанию t, если он отвечает на match.

accept(t, pat, &block)
banner() Показать исходный код
# File lib/optparse.rb, line 1164
def banner
  unless @banner
    @banner = +"Usage: #{program_name} [options]"
    visit(:add_banner, @banner)
  end
  @banner
end

Заголовок баннера, предшествующий сводке.

base() Показать исходный код
# File lib/optparse.rb, line 1234
def base
  @stack[1]
end

Предмет on_tail.

candidate(word) Показать исходный код
# File lib/optparse.rb, line 1774
def candidate(word)
  list = []
  case word
  when '-'
    long = short = true
  when /\A--/
    word, arg = word.split(/=/, 2)
    argpat = Completion.regexp(arg, false) if arg and !arg.empty?
    long = true
  when /\A-/
    short = true
  end
  pat = Completion.regexp(word, long)
  visit(:each_option) do |opt|
    next unless Switch === opt
    opts = (long ? opt.long : []) + (short ? opt.short : [])
    opts = Completion.candidate(word, true, pat, &opts.method(:each)).map(&:first) if pat
    if /\A=/ =~ opt.arg
      opts.map! {|sw| sw + "="}
      if arg and CompletingHash === opt.pattern
        if opts = opt.pattern.candidate(arg, false, argpat)
          opts.map!(&:last)
        end
      end
    end
    list.concat(opts)
  end
  list
end
def_head_option(*opts, &block)
Псевдоним для: define_head
def_option(*opts, &block)
Псевдоним для: define
def_tail_option(*opts, &block)
Псевдоним для: define_tail
define(*opts, &block) Показать исходный код
# File lib/optparse.rb, line 1495
def define(*opts, &block)
  top.append(*(sw = make_switch(opts, block)))
  sw[0]
end
Также является псевдонимом для: def_option
define_by_keywords(options, meth, **opts) Показать исходный код
# File lib/optparse/kwargs.rb, line 5
def define_by_keywords(options, meth, **opts)
  meth.parameters.each do |type, name|
    case type
    when :key, :keyreq
      op, cl = *(type == :key ? %w"[ ]" : ["", ""])
      define("--#{name}=#{op}#{name.upcase}#{cl}", *opts[name]) do |o|
        options[name] = o
      end
    end
  end
  options
end
define_head(*opts, &block) Показать исходный код
# File lib/optparse.rb, line 1510
def define_head(*opts, &block)
  top.prepend(*(sw = make_switch(opts, block)))
  sw[0]
end
Также является псевдонимом для: def_head_option
define_tail(*opts, &block) Показать исходный код
# File lib/optparse.rb, line 1524
def define_tail(*opts, &block)
  base.append(*(sw = make_switch(opts, block)))
  sw[0]
end
Также является псевдонимом для: def_tail_option
environment(env = File.basename($0, '.*')) Показать исходный код
# File lib/optparse.rb, line 1831
def environment(env = File.basename($0, '.*'))
  env = ENV[env] || ENV[env.upcase] or return
  require 'shellwords'
  parse(*Shellwords.shellwords(env))
end

Парсит переменную окружения env или её верхний регистр с разделением, как в оболочке.

env по умолчанию равно имени файла программы без расширения.

getopts(*args) Показать исходный код
# File lib/optparse.rb, line 1692
def getopts(*args)
  argv = Array === args.first ? args.shift : default_argv
  single_options, *long_options = *args

  result = {}

  single_options.scan(/(.)(:)?/) do |opt, val|
    if val
      result[opt] = nil
      define("-#{opt} VAL")
    else
      result[opt] = false
      define("-#{opt}")
    end
  end if single_options

  long_options.each do |arg|
    arg, desc = arg.split(';', 2)
    opt, val = arg.split(':', 2)
    if val
      result[opt] = val.empty? ? nil : val
      define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact)
    else
      result[opt] = false
      define("--#{opt}", *[desc].compact)
    end
  end

  parse_in_order(argv, result.method(:[]=))
  result
end

Метод-обёртка для getopts.rb.

params = ARGV.getopts("ab:", "foo", "bar:", "zot:Z;zot option")
# params["a"] = true   # -a
# params["b"] = "1"    # -b1
# params["foo"] = "1"  # --foo
# params["bar"] = "x"  # --bar x
# params["zot"] = "z"  # --zot Z
help() Показать исходный код
# File lib/optparse.rb, line 1276
def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end

Возвращает строку сводки параметров.

Также является псевдонимом для: to_s
inc(*args) Показать исходный код
# File lib/optparse.rb, line 1070
def inc(*args)
  self.class.inc(*args)
end
load(filename = nil) Показать исходный код
# File lib/optparse.rb, line 1811
def load(filename = nil)
  begin
    filename ||= File.expand_path(File.basename($0, '.*'), '~/.options')
  rescue
    return false
  end
  begin
    parse(*IO.readlines(filename).each {|s| s.chomp!})
    true
  rescue Errno::ENOENT, Errno::ENOTDIR
    false
  end
end

Загружает параметры из файлов как filename. Не делает ничего, если файл отсутствует. Возвращает, загрузился ли успешно.

filename по умолчанию равно имени файла программы без расширения в каталоге ~/.options.

make_switch(opts, block = nil) Показать исходный код
# File lib/optparse.rb, line 1362
def make_switch(opts, block = nil)
  short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
  ldesc, sdesc, desc, arg = [], [], []
  default_style = Switch::NoArgument
  default_pattern = nil
  klass = nil
  q, a = nil
  has_arg = false

  opts.each do |o|
    # argument class
    next if search(:atype, o) do |pat, c|
      klass = notwice(o, klass, 'type')
      if not_style and not_style != Switch::NoArgument
        not_pattern, not_conv = pat, c
      else
        default_pattern, conv = pat, c
      end
    end

    # directly specified pattern(any object possible to match)
    if (!(String === o || Symbol === o)) and o.respond_to?(:match)
      pattern = notwice(o, pattern, 'pattern')
      if pattern.respond_to?(:convert)
        conv = pattern.method(:convert).to_proc
      else
        conv = SPLAT_PROC
      end
      next
    end

    # anything others
    case o
    when Proc, Method
      block = notwice(o, block, 'block')
    when Array, Hash
      case pattern
      when CompletingHash
      when nil
        pattern = CompletingHash.new
        conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert)
      else
        raise ArgumentError, "argument pattern given twice"
      end
      o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
    when Module
      raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
    when *ArgumentStyle.keys
      style = notwice(ArgumentStyle[o], style, 'style')
    when /^--no-([^\[\]=\s]*)(.+)?/
      q, a = $1, $2
      o = notwice(a ? Object : TrueClass, klass, 'type')
      not_pattern, not_conv = search(:atype, o) unless not_style
      not_style = (not_style || default_style).guess(arg = a) if a
      default_style = Switch::NoArgument
      default_pattern, conv = search(:atype, FalseClass) unless default_pattern
      ldesc << "--no-#{q}"
      (q = q.downcase).tr!('_', '-')
      long << "no-#{q}"
      nolong << q
    when /^--\[no-\]([^\[\]=\s]*)(.+)?/
      q, a = $1, $2
      o = notwice(a ? Object : TrueClass, klass, 'type')
      if a
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      end
      ldesc << "--[no-]#{q}"
      (o = q.downcase).tr!('_', '-')
      long << o
      not_pattern, not_conv = search(:atype, FalseClass) unless not_style
      not_style = Switch::NoArgument
      nolong << "no-#{o}"
    when /^--([^\[\]=\s]*)(.+)?/
      q, a = $1, $2
      if a
        o = notwice(NilClass, klass, 'type')
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      end
      ldesc << "--#{q}"
      (o = q.downcase).tr!('_', '-')
      long << o
    when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
      q, a = $1, $2
      o = notwice(Object, klass, 'type')
      if a
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      else
        has_arg = true
      end
      sdesc << "-#{q}"
      short << Regexp.new(q)
    when /^-(.)(.+)?/
      q, a = $1, $2
      if a
        o = notwice(NilClass, klass, 'type')
        default_style = default_style.guess(arg = a)
        default_pattern, conv = search(:atype, o) unless default_pattern
      end
      sdesc << "-#{q}"
      short << q
    when /^=/
      style = notwice(default_style.guess(arg = o), style, 'style')
      default_pattern, conv = search(:atype, Object) unless default_pattern
    else
      desc.push(o)
    end
  end

  default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
  if !(short.empty? and long.empty?)
    if has_arg and default_style == Switch::NoArgument
      default_style = Switch::RequiredArgument
    end
    s = (style || default_style).new(pattern || default_pattern,
                                     conv, sdesc, ldesc, arg, desc, block)
  elsif !block
    if style or pattern
      raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
    end
    s = desc
  else
    short << pattern
    s = (style || default_style).new(pattern,
                                     conv, nil, nil, arg, desc, block)
  end
  return s, short, long,
    (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
    nolong
end

Создает OptionParser::Switch из параметров. Значение обработанного аргумента передается в заданный блок, где его можно обработать.

См. в начале OptionParser для некоторых полных примеров.

opts может включать следующие элементы:

Стиль аргумента:

Один из следующих:

:NONE, :REQUIRED, :OPTIONAL
Шаблон аргумента:

Допустимый формат аргумента параметра, должен быть предварительно определён с помощью OptionParser.accept или OptionParser#accept, или Regexp. Это может быть один раз или назначено как String, если не присутствует, иначе вызывает ArgumentError. Примеры:

Float, Time, Array
Возможные значения аргумента:

Hash или Array.

[:text, :binary, :auto]
%w[iso-2022-jp shift_jis euc-jp utf8 binary]
{ "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
Переключатель в длинном стиле:

Указывает переключатель в длинном стиле, который принимает обязательный, необязательный или без аргумента. Это строка следующего формата:

"--switch=MANDATORY" or "--switch MANDATORY"
"--switch[=OPTIONAL]"
"--switch"
Переключатель в коротком стиле:

Указывает переключатель в коротком стиле, который принимает обязательный, необязательный или без аргумента. Это строка следующего формата:

"-xMANDATORY"
"-x[OPTIONAL]"
"-x"

Также существует специальный формат, который соответствует диапазону символов (не полному набору регулярного выражения):

"-[a-z]MANDATORY"
"-[a-z][OPTIONAL]"
"-[a-z]"
Стиль аргумента и описание:

Вместо прямого указания обязательных или необязательных аргументов в параметре переключателя, можно использовать этот отдельный параметр.

"=MANDATORY"
"=[OPTIONAL]"
Описание:

Строка описания параметра.

"Run verbosely"

Если вы даете несколько строк описания, каждая строка будет напечатана по строке.

Обработчик:

Обработчик для значения обработанного аргумента. Либо укажите блок, либо передайте Proc или Method как аргумент.

new() { |self| ... } Показать исходный код
# File lib/optparse.rb, line 1241
def new
  @stack.push(List.new)
  if block_given?
    yield self
  else
    self
  end
end

Добавляет новый List.

on(*opts, &block) Показать исходный код
# File lib/optparse.rb, line 1504
def on(*opts, &block)
  define(*opts, &block)
  self
end

Добавить переключатель параметра и обработчик. См. make_switch для объяснения параметров.

on_head(*opts, &block) Показать исходный код
# File lib/optparse.rb, line 1518
def on_head(*opts, &block)
  define_head(*opts, &block)
  self
end

Добавить переключатель параметра, как с on, но в начале сводки.

END_OF_DOCUMENT_MARKER
on_tail(*opts, &block) Показать исходный код
# File lib/optparse.rb, line 1532
def on_tail(*opts, &block)
  define_tail(*opts, &block)
  self
end

Добавляет переключатель опции, как с on, но в конце сводки.

order(*argv, into: nil, &nonopt) Показать исходный код
# File lib/optparse.rb, line 1551
def order(*argv, into: nil, &nonopt)
  argv = argv[0].dup if argv.size == 1 and Array === argv[0]
  order!(argv, into: into, &nonopt)
end

Парсит аргументы командной строки argv в порядке. Когда задан блок, каждый не являющийся опцией аргумент передаётся.

Возвращает остаток argv необработанных аргументов.

order!(argv = default_argv, into: nil, &nonopt) Показать исходный код
# File lib/optparse.rb, line 1560
def order!(argv = default_argv, into: nil, &nonopt)
  setter = ->(name, val) {into[name.to_sym] = val} if into
  parse_in_order(argv, setter, &nonopt)
end

То же, что и order, но удаляет переключатели деструктивно. Не являющиеся опциями аргументы остаются в argv.

parse(*argv, into: nil) Показать исходный код
# File lib/optparse.rb, line 1665
def parse(*argv, into: nil)
  argv = argv[0].dup if argv.size == 1 and Array === argv[0]
  parse!(argv, into: into)
end

Парсит аргументы командной строки argv в порядке, когда переменная окружения POSIXLY_CORRECT установлена, и в режиме перестановки в противном случае.

parse!(argv = default_argv, into: nil) Показать исходный код
# File lib/optparse.rb, line 1674
def parse!(argv = default_argv, into: nil)
  if ENV.include?('POSIXLY_CORRECT')
    order!(argv, into: into)
  else
    permute!(argv, into: into)
  end
end

То же, что и parse, но удаляет переключатели деструктивно. Не являющиеся опциями аргументы остаются в argv.

permute(*argv, into: nil) Показать исходный код
# File lib/optparse.rb, line 1645
def permute(*argv, into: nil)
  argv = argv[0].dup if argv.size == 1 and Array === argv[0]
  permute!(argv, into: into)
end

Парсит аргументы командной строки argv в режиме перестановки и возвращает список не являющихся опциями аргументов.

permute!(argv = default_argv, into: nil) Показать исходный код
# File lib/optparse.rb, line 1654
def permute!(argv = default_argv, into: nil)
  nonopts = []
  order!(argv, into: into, &nonopts.method(:<<))
  argv[0, 0] = nonopts
  argv
end

То же, что и permute, но удаляет переключатели деструктивно. Не являющиеся опциями аргументы остаются в argv.

program_name() Показать исходный код
# File lib/optparse.rb, line 1176
def program_name
  @program_name || File.basename($0, '.*')
end

Имя программы, которое будет выведено в сообщении об ошибке и в стандартном заголовке, по умолчанию равно $0.

reject(*args, &blk) Показать исходный код
# File lib/optparse.rb, line 1135
def reject(*args, &blk) top.reject(*args, &blk) end

Направляет на отказ указанного аргумента класса.

t

Спецификатор класса аргумента, любой объект, включая Class.

reject(t)
release() Показать исходный код
# File lib/optparse.rb, line 1201
def release
  (defined?(@release) && @release) || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE)
end

Код релиза

remove() Показать исходный код
# File lib/optparse.rb, line 1253
def remove
  @stack.pop
end

Удаляет последний List.

separator(string) Показать исходный код
# File lib/optparse.rb, line 1541
def separator(string)
  top.append(string, nil, nil)
end

Добавляет разделитель в сводку.

summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk) Показать исходный код
# File lib/optparse.rb, line 1266
def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
  nl = "\n"
  blk ||= proc {|l| to << (l.index(nl, -1) ? l : l + nl)}
  visit(:summarize, {}, {}, width, max, indent, &blk)
  to
end

Помещает сводку опций в to и возвращает to. Передаёт каждую строку, если задан блок.

to

Место назначения вывода, у которого должен быть метод <<. По умолчанию [].

width

Ширина левой стороны, по умолчанию @summary_width.

max

Максимальная длина, разрешенная для левой стороны, по умолчанию width - 1.

indent

Отступ, по умолчанию @summary_indent.

terminate(arg = nil) Показать исходный код
# File lib/optparse.rb, line 1103
def terminate(arg = nil)
  self.class.terminate(arg)
end

Завершает парсинг опций. Необязательный параметр arg — строка, возвращённая как первый не являющийся опцией аргумент.

to_a() Показать исходный код
# File lib/optparse.rb, line 1282
def to_a; summarize("#{banner}".split(/^/)) end

Возвращает список сводки опций.

to_s()
Псевдоним для: help
top() Показать исходный код
# File lib/optparse.rb, line 1227
def top
  @stack[-1]
end

Объект on / on_head, accept / reject

ver() Показать исходный код
# File lib/optparse.rb, line 1208
def ver
  if v = version
    str = +"#{program_name} #{[v].join('.')}"
    str << " (#{v})" if v = release
    str
  end
end

Возвращает строку версии из program_name, версии и релиза.

version() Показать исходный код
# File lib/optparse.rb, line 1194
def version
  (defined?(@version) && @version) || (defined?(::Version) && ::Version)
end

Версия

warn(mesg = $!) Показать исходный код
# File lib/optparse.rb, line 1216
def warn(mesg = $!)
  super("#{program_name}: #{mesg}")
end
Вызывает метод суперкласса Kernel#warn

Скрытые методы экземпляра

complete(typ, opt, icase = false, *pat) Показать исходный код
# File lib/optparse.rb, line 1763
def complete(typ, opt, icase = false, *pat)
  if pat.empty?
    search(typ, opt) {|sw| return [sw, opt]} # exact match or...
  end
  raise AmbiguousOption, catch(:ambiguous) {
    visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw}
    raise InvalidOption, opt
  }
end

Завершает сокращенную запись длинного стиля опции переключателя и возвращает пару канонического переключателя и описания переключателя OptionParser::Switch.

typ

Таблица поиска.

opt

Ключ поиска.

icase

Поиск без учета регистра, если true.

pat

Дополнительный шаблон для завершения.

notwice(obj, prv, msg) Показать исходный код
# File lib/optparse.rb, line 1292
def notwice(obj, prv, msg)
  unless !prv or prv == obj
    raise(ArgumentError, "argument #{msg} given twice: #{obj}",
          ParseError.filter_backtrace(caller(2)))
  end
  obj
end

Проверяет, задан ли аргумент дважды, в этом случае поднимается ArgumentError. Вызывается только из OptionParser#switch.

obj

Новый аргумент.

prv

Ранее указанный аргумент.

msg

Сообщение об Exception.

search(id, key) { |k| ... } Показать исходный код
# File lib/optparse.rb, line 1746
def search(id, key)
  block_given = block_given?
  visit(:search, id, key) do |k|
    return block_given ? yield(k) : k
  end
end

Ищет key в @stack по хэшу id и возвращает или передает результат.

visit(id, *args, &block) Показать исходный код
# File lib/optparse.rb, line 1735
def visit(id, *args, &block)
  @stack.reverse_each do |el|
    el.send(id, *args, &block)
  end
  nil
end

Обходит @stack, отправляя каждому элементу метод id с args и block.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API