Spec-Zone.ru › Elixir 1.18

Исходный код 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()Исходный код

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

errors()Исходный код

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

options()Исходный код

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

parsed()Исходный код

@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 - см. раздел "Псевдонимы" ниже
  • :return_separator - см. раздел "Разделитель возвращаемых значений" ниже

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

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

  • :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 попытается проанализировать неизвестные переключатели.

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

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

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

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

Переключатели, за которыми следует значение, будут назначены это значение, как строку:

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

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

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

iex> OptionParser.parse(["--option-parser-example"], switches: [])
{[], [], []}

Если переключатель соответствует существующему атому Elixir, будь то из вашего кода, зависимости или из самого Elixir, он будет принят. Однако лучше не полагаться на внешний код и всегда определять атомы, которые нужно проанализировать, в том же модуле, который вызывает OptionParser, в качестве прямых аргументов к параметрам :switches или :strict.

Если вы хотите проанализировать все переключатели, независимо от их существования, вы можете принудительно создать атомы, передав 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"], [], []}

Разделитель возвращаемых значений

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

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

iex> OptionParser.parse(["--no-halt", "--", "lib"], return_separator: true, switches: [halt: :boolean])
{[halt: false], ["--", "lib"], []}

iex> OptionParser.parse(["script.exs", "--no-halt", "--", "foo"], return_separator: true, switches: [halt: :boolean])
{[{:halt, false}], ["script.exs", "--", "foo"], []}

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

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

Скачать версию ePub

Создано с помощью ExDoc (v0.36.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.18.1/OptionParser.html

Spec-Zone.ru

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