Spec-Zone.ru › Elixir 1.13

OptionParser

Функции для разбора аргументов командной строки.

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

Основной функцией в этом модуле является parse/2, которая анализирует список опций и аргументов командной строки и преобразует их в список ключевых слов:

iex> OptionParser.parse(["--debug"], strict: [debug: :boolean])
{[debug: true], [], []}

OptionParser предоставляет удобства, такие как псевдонимы и автоматическую обработку отрицательных флагов.

Функция parse_head/2 — альтернатива parse/2, которая останавливает разбор, как только встречает значение, которое не является ни флагом, ни значением для предыдущего флага.

Этот модуль также предоставляет низкоуровневые функции, такие как next/2, для ручного разбора флагов, а также split/1 и to_argv/1 для разбора из строк и преобразования флагов в строки.

Краткое описание

Типы

argv()
errors()
options()
parsed()

Функции

next(argv, opts \\ [])

Функция низкого уровня, которая анализирует одну опцию.

parse!(argv, opts \\ [])

То же, что и parse/2, но генерирует исключение OptionParser.ParseError, если заданы какие-либо недопустимые опции.

parse(argv, opts \\ [])

Анализирует argv в список ключевых слов.

parse_head!(argv, opts \\ [])

То же, что и parse_head/2, но генерирует исключение OptionParser.ParseError, если заданы какие-либо недопустимые опции.

parse_head(argv, opts \\ [])

Аналогично parse/2, но анализирует только начало argv; как только она находит не флаг, она останавливает разбор.

split(string)

Разделяет строку на части argv/0.

to_argv(enum, options \\ [])

Принимает перечислимое значение пар «ключ-значение» и преобразует его в argv/0.

Типы

argv()Source

@type argv() :: [String.t()]

errors()Source

@type errors() :: [{String.t(), String.t() | nil}]

options()Source

@type options() :: [switches: keyword(), strict: keyword(), aliases: keyword()]

parsed()Source

@type parsed() :: keyword()

Функции

next(argv, opts \\ [])Source

@spec next(argv(), options()) ::
  {:ok, key :: atom(), value :: term(), argv()}
  | {:invalid, String.t(), String.t() | nil, argv()}
  | {:undefined, String.t(), String.t() | nil, argv()}
  | {:error, argv()}

Функция низкого уровня, которая анализирует один параметр.

Она принимает те же параметры, что и parse/2 и parse_head/2, так как обе функции построены на основе этой функции. Эта функция может возвращать:

  • {:ok, key, value, rest} - параметр key со value был успешно проанализирован

  • {:invalid, key, value, rest} - параметр key является недопустимым со value (возвращается, когда значение не может быть проанализировано в соответствии с типом переключателя)

  • {:undefined, key, value, rest} - параметр key не определен (возвращается в строгом режиме, когда переключатель неизвестен или на несуществующих атомах)

  • {:error, rest} - нет переключателей в начале заданного argv

parse!(argv, opts \\ [])Source

@spec parse!(argv(), options()) :: {parsed(), argv()}

То же самое, что и parse/2, но генерирует исключение OptionParser.ParseError, если заданы какие-либо недопустимые параметры.

Если ошибок нет, возвращается кортеж {parsed, rest}, где:

  • parsed — список проанализированных переключателей (такой же, как в parse/2)
  • rest — список аргументов (такой же, как в parse/2)

Примеры

iex> OptionParser.parse!(["--debug", "path/to/file"], strict: [debug: :boolean])
{[debug: true], ["path/to/file"]}

iex> OptionParser.parse!(["--limit", "xyz"], strict: [limit: :integer])
** (OptionParser.ParseError) 1 error found!
--limit : Expected type integer, got "xyz"

iex> OptionParser.parse!(["--unknown", "xyz"], strict: [])
** (OptionParser.ParseError) 1 error found!
--unknown : Unknown option

iex> OptionParser.parse!(
...>   ["-l", "xyz", "-f", "bar"],
...>   switches: [limit: :integer, foo: :integer],
...>   aliases: [l: :limit, f: :foo]
...> )
** (OptionParser.ParseError) 2 errors found!
-l : Expected type integer, got "xyz"
-f : Expected type integer, got "bar"

parse(argv, opts \\ [])Source

@spec parse(argv(), options()) :: {parsed(), argv(), errors()}

Анализирует argv в список ключевых слов.

Возвращает кортеж из трех элементов вида {parsed, args, invalid}, где:

  • parsed — список ключевых слов проанализированных переключателей со {switch_name, value} кортежами в нём; switch_name — атом, представляющий имя переключателя, а value — значение для данного переключателя, проанализированное в соответствии с opts (см. раздел «Примеры» для получения дополнительной информации)
  • args — список оставшихся аргументов в argv в виде строк
  • invalid — список недопустимых параметров в виде {option_name, value}, где option_name — исходный параметр, а value — nil, если параметр не ожидался, или строковое значение, если значение не имело ожидаемого типа для соответствующего параметра

Elixir преобразует переключатели в атомы с нижним подчеркиванием, поэтому --source-path становится :source_path. Это сделано для лучшей совместимости с соглашениями Elixir. Однако это означает, что переключатели не могут содержать нижние подчеркивания, а переключатели, содержащие нижние подчеркивания, всегда возвращаются в списке недопустимых переключателей.

При анализе обычно указываются переключатели и ожидаемые типы:

iex> OptionParser.parse(["--debug"], strict: [debug: :boolean])
{[debug: true], [], []}

iex> OptionParser.parse(["--source", "lib"], strict: [source: :string])
{[source: "lib"], [], []}

iex> OptionParser.parse(
...>   ["--source-path", "lib", "test/enum_test.exs", "--verbose"],
...>   strict: [source_path: :string, verbose: :boolean]
...> )
{[source_path: "lib", verbose: true], ["test/enum_test.exs"], []}

Ниже мы рассмотрим допустимые переключатели и режимы работы анализатора параметров.

Параметры

Поддерживаются следующие параметры:

  • :switches или :strict — см. раздел «Определения переключателей» ниже
  • :allow_nonexistent_atoms — см. раздел «Анализ неизвестных переключателей» ниже
  • :aliases — см. раздел «Псевдонимы» ниже

Определения переключателей

Переключатели можно указать с помощью одного из двух параметров:

  • :strict — определяет строгие переключатели и их типы. Любой переключатель в argv, который не указан в списке, возвращается в списке недопустимых параметров. Это предпочтительный способ анализа параметров.

  • :switches — определяет переключатели и их типы. Эта функция всё ещё пытается проанализировать переключатели, которые не указаны в этом списке.

Оба этих параметра принимают список ключевых слов, где ключ — атом, определяющий имя переключателя, а значение — type переключателя (см. раздел «Типы» ниже для получения дополнительной информации).

Обратите внимание, что вы должны указать только :switches или :strict параметр. Если вы укажете оба, будет выброшено исключение ArgumentError.

Типы

Переключатели, проанализированные функцией OptionParser, могут принимать ноль или один аргумент.

Следующие типы переключателей не принимают аргументов:

  • :boolean — устанавливает значение в true при указании (см. также раздел «Отрицающие переключатели» ниже)
  • :count — подсчитывает количество раз, когда задан переключатель

Следующие переключатели принимают один аргумент:

  • :integer — анализирует значение как целое число
  • :float — анализирует значение как число с плавающей точкой
  • :string — анализирует значение как строку

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

Модификаторы

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

  • :keep — сохраняет дублированные элементы вместо их перезаписи; работает со всеми типами, кроме :count. Указание switch_name: :keep предполагает, что тип :switch_name будет :string.

Чтобы использовать :keep с типом, отличным от :string, используйте список в качестве типа для переключателя. Например: [foo: [:integer, :keep]].

Отрицающие переключатели

В случае, если переключатель SWITCH указан с типом :boolean, его можно также передать как --no-SWITCH, что установит параметр в значение false.

iex> OptionParser.parse(["--no-op", "path/to/file"], switches: [op: :boolean])
{[op: false], ["path/to/file"], []}

Анализ неизвестных переключателей

При указании параметра :switches, функция OptionParser попытается проанализировать неизвестные переключатели:

iex> OptionParser.parse(["--debug"], switches: [key: :string])
{[debug: true], [], []}

Даже если мы не указали --debug в списке переключателей, он входит в возвращаемые параметры. То же самое будет работать и в случае:

iex> OptionParser.parse(["--debug", "value"], switches: [key: :string])
{[debug: "value"], [], []}

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

Если вы всё же хотите проанализировать неизвестные переключатели, помните, что Elixir преобразует переключатели в атомы. Поскольку атомы не подлежат сборке мусора, OptionParser будет анализировать только переключатели, которые переводятся в атомы, используемые средой выполнения, чтобы избежать утечки атомов. Например, код ниже отбросит переключатель --option-parser-example, потому что атом :option_parser_example нигде не используется:

OptionParser.parse(["--option-parser-example"], switches: [debug: :boolean])
# The :option_parser_example atom is not used anywhere below

Однако, код ниже будет работать, если атом :option_parser_example используется где-либо позже (или ранее) в том же модуле. Например:

{opts, _, _} = OptionParser.parse(["--option-parser-example"], switches: [debug: :boolean])
# ... then somewhere in the same module you access it ...
opts[:option_parser_example]

Другими словами, Elixir будет анализировать только параметры, которые используются средой выполнения, игнорируя все остальные. Если вы хотите проанализировать все переключатели, независимо от того, существуют они или нет, вы можете принудительно создать атомы, передав allow_nonexistent_atoms: true в качестве параметра. Используйте этот параметр с осторожностью. Он полезен только при разработке командных строк с динамическими именами аргументов и должен быть избегнут в долгоживущих системах.

Псевдонимы

Набор псевдонимов можно указать в параметре :aliases:

iex> OptionParser.parse(["-d"], aliases: [d: :debug], strict: [debug: :boolean])
{[debug: true], [], []}

Примеры

Вот несколько примеров работы с разными типами и модификаторами:

iex> OptionParser.parse(["--unlock", "path/to/file"], strict: [unlock: :boolean])
{[unlock: true], ["path/to/file"], []}

iex> OptionParser.parse(
...>   ["--unlock", "--limit", "0", "path/to/file"],
...>   strict: [unlock: :boolean, limit: :integer]
...> )
{[unlock: true, limit: 0], ["path/to/file"], []}

iex> OptionParser.parse(["--limit", "3"], strict: [limit: :integer])
{[limit: 3], [], []}

iex> OptionParser.parse(["--limit", "xyz"], strict: [limit: :integer])
{[], [], [{"--limit", "xyz"}]}

iex> OptionParser.parse(["--verbose"], switches: [verbose: :count])
{[verbose: 1], [], []}

iex> OptionParser.parse(["-v", "-v"], aliases: [v: :verbose], strict: [verbose: :count])
{[verbose: 2], [], []}

iex> OptionParser.parse(["--unknown", "xyz"], strict: [])
{[], ["xyz"], [{"--unknown", nil}]}

iex> OptionParser.parse(
...>   ["--limit", "3", "--unknown", "xyz"],
...>   switches: [limit: :integer]
...> )
{[limit: 3, unknown: "xyz"], [], []}

iex> OptionParser.parse(
...>   ["--unlock", "path/to/file", "--unlock", "path/to/another/file"],
...>   strict: [unlock: :keep]
...> )
{[unlock: "path/to/file", unlock: "path/to/another/file"], [], []}

parse_head!(argv, opts \\ [])Source

@spec parse_head!(argv(), options()) :: {parsed(), argv()}

То же самое, что и parse_head/2, но генерирует исключение OptionParser.ParseError, если заданы какие-либо недопустимые параметры.

Если ошибок нет, возвращается кортеж {parsed, rest}, где:

  • parsed — список проанализированных переключателей (такой же, как в parse_head/2)
  • rest — список аргументов (такой же, как в parse_head/2)

Примеры

iex> OptionParser.parse_head!(
...>   ["--source", "lib", "path/to/file", "--verbose"],
...>   switches: [source: :string, verbose: :boolean]
...> )
{[source: "lib"], ["path/to/file", "--verbose"]}

iex> OptionParser.parse_head!(
...>   ["--number", "lib", "test/enum_test.exs", "--verbose"],
...>   strict: [number: :integer]
...> )
** (OptionParser.ParseError) 1 error found!
--number : Expected type integer, got "lib"

iex> OptionParser.parse_head!(
...>   ["--verbose", "--source", "lib", "test/enum_test.exs", "--unlock"],
...>   strict: [verbose: :integer, source: :integer]
...> )
** (OptionParser.ParseError) 2 errors found!
--verbose : Missing argument of type integer
--source : Expected type integer, got "lib"

parse_head(argv, opts \\ [])Source

@spec parse_head(argv(), options()) :: {parsed(), argv(), errors()}

Аналогично parse/2, но анализирует только начало argv; как только находит параметр, не являющийся переключателем, прекращает анализ.

См. parse/2 для получения дополнительной информации.

Пример

iex> OptionParser.parse_head(
...>   ["--source", "lib", "test/enum_test.exs", "--verbose"],
...>   switches: [source: :string, verbose: :boolean]
...> )
{[source: "lib"], ["test/enum_test.exs", "--verbose"], []}

iex> OptionParser.parse_head(
...>   ["--verbose", "--source", "lib", "test/enum_test.exs", "--unlock"],
...>   switches: [source: :string, verbose: :boolean, unlock: :boolean]
...> )
{[verbose: true, source: "lib"], ["test/enum_test.exs", "--unlock"], []}

split(string)Source

@spec split(String.t()) :: argv()

Разделяет строку на куски argv/0.

Эта функция разделяет заданную string на список строк аналогичным образом, как и многие оболочки.

Примеры

iex> OptionParser.split("foo bar")
["foo", "bar"]

iex> OptionParser.split("foo \"bar baz\"")
["foo", "bar baz"]

to_argv(enum, options \\ [])Source

@spec to_argv(Enumerable.t(), options()) :: argv()

Принимает перечисляемый ключ-значение и преобразует его в argv/0.

Ключи должны быть атомами. Ключи со значением nil игнорируются, логические значения преобразуются в --key или --no-key (если значение соответственно true или false), а все остальные значения преобразуются с помощью Kernel.to_string/1.

Рекомендуется передавать в to_argv/2 тот же набор options, что и в parse/2. Некоторые переключатели могут быть правильно реконструированы только с помощью :switches информации.

Примеры

iex> OptionParser.to_argv(foo_bar: "baz")
["--foo-bar", "baz"]
iex> OptionParser.to_argv(bool: true, bool: false, discarded: nil)
["--bool", "--no-bool"]

Некоторые переключатели выведут разные значения в зависимости от типа переключателей:

iex> OptionParser.to_argv([number: 2], switches: [])
["--number", "2"]
iex> OptionParser.to_argv([number: 2], switches: [number: :count])
["--number", "--number"]

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.13.4/OptionParser.html

Spec-Zone.ru

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