Spec-Zone.ru › Ruby 2.7

класс 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

Set параметров обработки.

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

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')

Имя параметра всегда преобразуется в первое (предпочтительное) имя, указанное в исходных параметрах для GetoptLong.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] !~ /\A-./
      @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] !~ /\A-./)
      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 =~ /\A(--[^=]+)/ && @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 =~ /=(.*)/m
        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 =~ /=(.*)/m
        option_argument = $1
      elsif 0 < ARGV.length && ARGV[0] !~ /\A-./
        option_argument = ARGV.shift
      else
        option_argument = ''
      end
    elsif argument =~ /=(.*)/m
      set_error(NeedlessArgument,
                "option `#{option_name}' doesn't allow an argument")
    end

  elsif argument =~ /\A(-(.))(.*)/m
    #
    # 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] !~ /\A-./
          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

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

Имя параметра всегда преобразуется в первое (предпочтительное) имя, указанное в исходных параметрах для GetoptLong.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

Set обработку порядка параметров и аргументов. Если обработка параметров уже началась, генерируется 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 !~ /\A-([^-]|-.+)\z/
          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

Set параметров. Принимает те же аргументы, что и GetoptLong.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

Set ошибку (защищённый метод).

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