Spec-Zone.ru › Elixir 1.14

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 \\ [])

Разбирает argv в список ключевых слов.

parse!(argv, opts \\ [])

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

parse_head(argv, opts \\ [])

Аналогично parse/2, но разбирает только начало argv; как только найдёт не-ключ, разбор останавливается.

parse_head!(argv, opts \\ [])

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

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(),
  allow_nonexistent_atoms: boolean()
]

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(), 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!(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_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"], []}

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"

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"]
END_OF_DOCUMENT_MARKER

to_argv(enum, options \\ [])Source

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

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

Ключи должны быть атомами. Ключи со значением nil игнорируются, значения булевого типа преобразуются в --key или --no-key (если значение true или false, соответственно), а все остальные значения преобразуются с помощью 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.14.1/OptionParser.html

Spec-Zone.ru

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