Spec-Zone.ru › Ruby 2.3

класс GetoptLong

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

Класс GetoptLong позволяет парсить командные строки аналогично вызову функции GNU getopt_long() из библиотеки C. Однако обратите внимание, что GetoptLong — это чистое Ruby-реализация.

GetoptLong поддерживает варианты в стиле POSIX, такие как --file, а также однобуквенные варианты, такие как -f

Пустой вариант -- (два символа минус) используется для завершения обработки вариантов. Это особенно важно, если варианты имеют необязательные аргументы.

Вот простой пример использования:

require 'getoptlong'

opts = GetoptLong.new(
  [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
  [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
  [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
)

dir = nil
name = nil
repetitions = 1
opts.each do |opt, arg|
  case opt
    when '--help'
      puts <<-EOF
hello [OPTION] ... DIR

-h, --help:
   show help

--repeat x, -n x:
   repeat x times

--name [name]:
   greet user by name, if name not supplied default is John

DIR: The directory in which to issue the greeting.
      EOF
    when '--repeat'
      repetitions = arg.to_i
    when '--name'
      if arg == ''
        name = 'John'
      else
        name = arg
      end
  end
end

if ARGV.length != 1
  puts "Missing dir argument (try --help)"
  exit 0
end

dir = ARGV.shift

Dir.chdir(dir)
for i in (1..repetitions)
  print "Hello"
  if name
    print ", #{name}"
  end
  puts
end

Пример командной строки:

hello -n 6 --name -- /tmp

Константы

ARGUMENT_FLAGS

Флаги аргументов.

ORDERINGS

Порядок.

STATUS_TERMINATED

Атрибуты

error[R]

Проверить, произошла ли ошибка при обработке вариантов.

error?[R]

Проверить, произошла ли ошибка при обработке вариантов.

ordering[R]

Возвращает порядок.

quiet[RW]

Включить/выключить режим `quiet`.

quiet?[RW]

Включить/выключить режим `quiet`.

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

new(*arguments) Показать исходный код
# File lib/getoptlong.rb, line 129
def initialize(*arguments)
  #
  # Current ordering.
  #
  if ENV.include?('POSIXLY_CORRECT')
    @ordering = REQUIRE_ORDER
  else
    @ordering = PERMUTE
  end

  #
  # Hash table of option names.
  # Keys of the table are option names, and their values are canonical
  # names of the options.
  #
  @canonical_names = Hash.new

  #
  # Hash table of argument flags.
  # Keys of the table are option names, and their values are argument
  # flags of the options.
  #
  @argument_flags = Hash.new

  #
  # Whether error messages are output to $stderr.
  #
  @quiet = FALSE

  #
  # Status code.
  #
  @status = STATUS_YET

  #
  # Error code.
  #
  @error = nil

  #
  # Error message.
  #
  @error_message = nil

  #
  # Rest of catenated short options.
  #
  @rest_singles = ''

  #
  # List of non-option-arguments.
  # Append them to ARGV when option processing is terminated.
  #
  @non_option_arguments = Array.new

  if 0 < arguments.length
    set_options(*arguments)
  end
end

Настроить обработку вариантов.

Поддерживаемые варианты передаются в new() в виде массива массивов. Каждый подмассив содержит любое количество строк с именами вариантов, которые имеют одинаковое значение, и один из следующих флагов:

GetoptLong::NO_ARGUMENT

Вариант не принимает аргумент.

GetoptLong::REQUIRED_ARGUMENT

Вариант всегда принимает аргумент.

GetoptLong::OPTIONAL_ARGUMENT

Вариант может или не может принимать аргумент.

Первое имя варианта считается предпочтительным (каноническим). Помимо этого, элементы каждого подмассива могут быть в любом порядке.

Публичные методы экземпляра

each() { |option_name, option_argument| ... } Показать исходный код
# File lib/getoptlong.rb, line 601
def each
  loop do
    option_name, option_argument = get_option
    break if option_name == nil
    yield option_name, option_argument
  end
end

Итераторная версия `get`.

Блок вызывается многократно с двумя аргументами: первый — имя варианта, второй — аргумент, который за ним следует (если таковой имеется). Пример: ('–opt', 'value')

Имя варианта всегда преобразуется в первое (предпочтительное) имя, указанное в исходных вариантах для ::new.

Также алиас: each_option
each_option()

`each_option` — это алиас для `each`.

Алиас для: each
error_message() Показать исходный код
# File lib/getoptlong.rb, line 412
def error_message
  return @error_message
end

Возвращает соответствующее сообщение об ошибке в формате, определенном POSIX. Если ошибки не произошло, возвращает nil.

get() Показать исходный код
# File lib/getoptlong.rb, line 427
def get
  option_name, option_argument = nil, ''

  #
  # Check status.
  #
  return nil if @error != nil
  case @status
  when STATUS_YET
    @status = STATUS_STARTED
  when STATUS_TERMINATED
    return nil
  end

  #
  # Get next option argument.
  #
  if 0 < @rest_singles.length
    argument = '-' + @rest_singles
  elsif (ARGV.length == 0)
    terminate
    return nil
  elsif @ordering == PERMUTE
    while 0 < ARGV.length && ARGV[0] !~ /^-./
      @non_option_arguments.push(ARGV.shift)
    end
    if ARGV.length == 0
      terminate
      return nil
    end
    argument = ARGV.shift
  elsif @ordering == REQUIRE_ORDER
    if (ARGV[0] !~ /^-./)
      terminate
      return nil
    end
    argument = ARGV.shift
  else
    argument = ARGV.shift
  end

  #
  # Check the special argument `--'.
  # `--' indicates the end of the option list.
  #
  if argument == '--' && @rest_singles.length == 0
    terminate
    return nil
  end

  #
  # Check for long and short options.
  #
  if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0
    #
    # This is a long style option, which start with `--'.
    #
    pattern = $1
    if @canonical_names.include?(pattern)
      option_name = pattern
    else
      #
      # The option `option_name' is not registered in `@canonical_names'.
      # It may be an abbreviated.
      #
      matches = []
      @canonical_names.each_key do |key|
        if key.index(pattern) == 0
          option_name = key
          matches << key
        end
      end
      if 2 <= matches.length
        set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}")
      elsif matches.length == 0
        set_error(InvalidOption, "unrecognized option `#{argument}'")
      end
    end

    #
    # Check an argument to the option.
    #
    if @argument_flags[option_name] == REQUIRED_ARGUMENT
      if argument =~ /=(.*)$/
        option_argument = $1
      elsif 0 < ARGV.length
        option_argument = ARGV.shift
      else
        set_error(MissingArgument,
                  "option `#{argument}' requires an argument")
      end
    elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
      if argument =~ /=(.*)$/
        option_argument = $1
      elsif 0 < ARGV.length && ARGV[0] !~ /^-./
        option_argument = ARGV.shift
      else
        option_argument = ''
      end
    elsif argument =~ /=(.*)$/
      set_error(NeedlessArgument,
                "option `#{option_name}' doesn't allow an argument")
    end

  elsif argument =~ /^(-(.))(.*)/
    #
    # This is a short style option, which start with `-' (not `--').
    # Short options may be catenated (e.g. `-l -g' is equivalent to
    # `-lg').
    #
    option_name, ch, @rest_singles = $1, $2, $3

    if @canonical_names.include?(option_name)
      #
      # The option `option_name' is found in `@canonical_names'.
      # Check its argument.
      #
      if @argument_flags[option_name] == REQUIRED_ARGUMENT
        if 0 < @rest_singles.length
          option_argument = @rest_singles
          @rest_singles = ''
        elsif 0 < ARGV.length
          option_argument = ARGV.shift
        else
          # 1003.2 specifies the format of this message.
          set_error(MissingArgument, "option requires an argument -- #{ch}")
        end
      elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT
        if 0 < @rest_singles.length
          option_argument = @rest_singles
          @rest_singles = ''
        elsif 0 < ARGV.length && ARGV[0] !~ /^-./
          option_argument = ARGV.shift
        else
          option_argument = ''
        end
      end
    else
      #
      # This is an invalid option.
      # 1003.2 specifies the format of this message.
      #
      if ENV.include?('POSIXLY_CORRECT')
        set_error(InvalidOption, "invalid option -- #{ch}")
      else
        set_error(InvalidOption, "invalid option -- #{ch}")
      end
    end
  else
    #
    # This is a non-option argument.
    # Only RETURN_IN_ORDER fell into here.
    #
    return '', argument
  end

  return @canonical_names[option_name], option_argument
end

Получить имя следующего варианта и его аргумент в виде массива из двух элементов.

Имя варианта всегда преобразуется в первое (предпочтительное) имя, указанное в исходных вариантах для ::new.

Пример: ['–option', 'value']

Возвращает nil, если обработка завершена (определяется значением STATUS_TERMINATED).

Также алиас: get_option
get_option()

`get_option` — это алиас для `get`.

Алиас для: get
ordering=(ordering) Показать исходный код
# File lib/getoptlong.rb, line 238
def ordering=(ordering)
  #
  # The method is failed if option processing has already started.
  #
  if @status != STATUS_YET
    set_error(ArgumentError, "argument error")
    raise RuntimeError,
      "invoke ordering=, but option processing has already started"
  end

  #
  # Check ordering.
  #
  if !ORDERINGS.include?(ordering)
    raise ArgumentError, "invalid ordering `#{ordering}'"
  end
  if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
    @ordering = REQUIRE_ORDER
  else
    @ordering = ordering
  end
end

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

Передаваемое значение должно быть членом GetoptLong::ORDERINGS. Оно изменяет обработку вариантов следующим образом:

REQUIRE_ORDER :

Варианты должны следовать перед невариантами.

Обработка вариантов завершается, как только встречается слово, которое не предшествует соответствующему флагу варианта.

Например, если -a и -b — варианты без аргументов, при парсинге командной строки '-a one -b two' в ARGV останутся 'one', '-b', 'two', и только ('-a', '') будет обработано как пара вариант/аргумент.

Это порядок по умолчанию, если переменная окружения POSIXLY_CORRECT установлена. (Это для совместимости с GNU getopt_long.)

PERMUTE :

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

Каждая последовательность слов, которая может интерпретироваться как вариант (с аргументом или без), рассматривается как вариант; слова, не являющиеся вариантами, пропускаются.

Например, если -a не требует аргумента, а -b необязательно принимает аргумент, при парсинге '-a one -b two three' варианты/аргументы ('-a','') и ('-b', 'two') будут обработаны как пары, а 'one','three' останутся в ARGV.

Если порядок установлен в PERMUTE, но переменная окружения POSIXLY_CORRECT установлена, используется REQUIRE_ORDER. Это для совместимости с GNU getopt_long.

RETURN_IN_ORDER :

Все слова в командной строке обрабатываются как варианты. Слова, не предваряемые коротким или длинным флагом варианта, передаются как аргументы с вариантом '' (пустая строка).

Например, если -a требует аргумента, а -b не требует, в командной строке '-a one -b two three' вариантами/аргументами будут ('-a', 'one') ('-b', ''), ('', 'two'), ('', 'three').

set_options(*arguments) Показать исходный код
# File lib/getoptlong.rb, line 271
def set_options(*arguments)
  #
  # The method is failed if option processing has already started.
  #
  if @status != STATUS_YET
    raise RuntimeError,
      "invoke set_options, but option processing has already started"
  end

  #
  # Clear tables of option names and argument flags.
  #
  @canonical_names.clear
  @argument_flags.clear

  arguments.each do |arg|
    if !arg.is_a?(Array)
     raise ArgumentError, "the option list contains non-Array argument"
    end

    #
    # Find an argument flag and it set to `argument_flag'.
    #
    argument_flag = nil
    arg.each do |i|
      if ARGUMENT_FLAGS.include?(i)
        if argument_flag != nil
          raise ArgumentError, "too many argument-flags"
        end
        argument_flag = i
      end
    end

    raise ArgumentError, "no argument-flag" if argument_flag == nil

    canonical_name = nil
    arg.each do |i|
      #
      # Check an option name.
      #
      next if i == argument_flag
      begin
        if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
          raise ArgumentError, "an invalid option `#{i}'"
        end
        if (@canonical_names.include?(i))
          raise ArgumentError, "option redefined `#{i}'"
        end
      rescue
        @canonical_names.clear
        @argument_flags.clear
        raise
      end

      #
      # Register the option (`i') to the `@canonical_names' and
      # `@canonical_names' Hashes.
      #
      if canonical_name == nil
        canonical_name = i
      end
      @canonical_names[i] = canonical_name
      @argument_flags[i] = argument_flag
    end
    raise ArgumentError, "no option name" if canonical_name == nil
  end
  return self
end

Установить варианты. Принимает тот же аргумент, что и ::new.

Выбрасывает исключение RuntimeError, если обработка вариантов уже началась.

terminate() Показать исходный код
# File lib/getoptlong.rb, line 358
def terminate
  return nil if @status == STATUS_TERMINATED
  raise RuntimeError, "an error has occurred" if @error != nil

  @status = STATUS_TERMINATED
  @non_option_arguments.reverse_each do |argument|
    ARGV.unshift(argument)
  end

  @canonical_names = nil
  @argument_flags = nil
  @rest_singles = nil
  @non_option_arguments = nil

  return self
end

Явно завершить обработку вариантов.

terminated?() Показать исходный код
# File lib/getoptlong.rb, line 378
def terminated?
  return @status == STATUS_TERMINATED
end

Возвращает true, если обработка вариантов завершена, иначе — false.

Защищенные методы экземпляра

set_error(type, message) Показать исходный код
# File lib/getoptlong.rb, line 385
def set_error(type, message)
  $stderr.print("#{$0}: #{message}\n") if !@quiet

  @error = type
  @error_message = message
  @canonical_names = nil
  @argument_flags = nil
  @rest_singles = nil
  @non_option_arguments = nil

  raise type, message
end

Установить ошибку (защищенный метод).

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