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 для разбора из строк и преобразования переключателей в строки.
Краткое описание
Типы
Функции
- 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()
Specs
argv() :: [String.t()]
errors()
Specs
errors() :: [{String.t(), String.t() | nil}] options()
Specs
options() :: [switches: keyword(), strict: keyword(), aliases: keyword()]
parsed()
Specs
parsed() :: keyword()
Функции
next(argv, opts \\ [])
Характеристики
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 \\ [])
Характеристики
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 \\ [])
Характеристики
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 \\ [])
Характеристики
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 \\ [])
Характеристики
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)
Характеристики
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 \\ [])
Характеристики
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.9.4/OptionParser.html