This module contains functions to parse command line options.
Low-level function that parses one option
The same as parse/2
but raises an OptionParser.ParseError
exception if any invalid options are given
Parses argv
into a keyword list
The same as parse_head/2
but raises an OptionParser.ParseError
exception if any invalid options are given
Similar to parse/2
but only parses the head of argv
; as soon as it finds a non-switch, it stops parsing
Splits a string into argv/0
chunks
Receives a key-value enumerable and converts it to argv/0
argv() :: [String.t()]
errors() :: [{String.t(), String.t() | nil}]
options() :: [switches: keyword(), strict: keyword(), aliases: keyword()]
parsed() :: keyword()
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()}
Low-level function that parses one option.
It accepts the same options as parse/2
and parse_head/2
as both functions are built on top of this function. This function may return:
{:ok, key, value, rest}
- the option key
with value
was successfully parsed
{:invalid, key, value, rest}
- the option key
is invalid with value
(returned when the value cannot be parsed according to the switch type)
{:undefined, key, value, rest}
- the option key
is undefined (returned in strict mode when the switch is unknown or on nonexistent atoms)
{:error, rest}
- there are no switches at the head of the given argv
parse!(argv(), options()) :: {parsed(), argv()} | no_return()
The same as parse/2
but raises an OptionParser.ParseError
exception if any invalid options are given.
If there are no errors, returns a {parsed, rest}
tuple where:
parsed
is the list of parsed switches (same as in parse/2
) rest
is the list of arguments (same as in 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(), options()) :: {parsed(), argv(), errors()}
Parses argv
into a keyword list.
It returns a three-element tuple with the form {parsed, args, invalid}
, where:
parsed
is a keyword list of parsed switches with {switch_name, value}
tuples in it; switch_name
is the atom representing the switch name while value
is the value for that switch parsed according to opts
(see the “Examples” section for more information) args
is a list of the remaining arguments in argv
as strings invalid
is a list of invalid options as {option_name, value}
where option_name
is the raw option and value
is nil
if the option wasn’t expected or the string value if the value didn’t have the expected type for the corresponding option Elixir converts switches to underscored atoms, so --source-path
becomes :source_path
. This is done to better suit Elixir conventions. However, this means that switches can’t contain underscores and switches that do contain underscores are always returned in the list of invalid switches.
When parsing, it is common to list switches and their expected types:
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"], []}
We will explore the valid switches and operation modes of option parser below.
The following options are supported:
:switches
or :strict
- see the “Switch definitions” section below :allow_nonexistent_atoms
- see the “Parsing unknown switches” section below :aliases
- see the “Aliases” section below Switches can be specified via one of two options:
:strict
- defines strict switches. Any switch in argv
that is not specified in the list is returned in the invalid options list. :switches
- defines some switches and their types. This function still attempts to parse switches that are not in this list. Both these options accept a keyword list of {name, type}
tuples where name
is an atom defining the name of the switch and type
is an atom that specifies the type for the value of this switch (see the “Types” section below for the possible types and more information about type casting).
Note that you should only supply the :switches
or the :strict
option. If you supply both, an ArgumentError
exception will be raised.
Switches parsed by OptionParser
may take zero or one arguments.
The following switches types take no arguments:
:boolean
- sets the value to true
when given (see also the “Negation switches” section below) :count
- counts the number of times the switch is given The following switches take one argument:
:integer
- parses the value as an integer :float
- parses the value as a float :string
- parses the value as a string If a switch can’t be parsed according to the given type, it is returned in the invalid options list.
Switches can be specified with modifiers, which change how they behave. The following modifiers are supported:
:keep
- keeps duplicated items instead of overriding them; works with all types except :count
. Specifying switch_name: :keep
assumes the type of :switch_name
will be :string
. To use :keep
with a type other than :string
, use a list as the type for the switch. For example: [foo: [:integer, :keep]]
.
In case a switch SWITCH
is specified to have type :boolean
, it may be passed as --no-SWITCH
as well which will set the option to false
:
iex> OptionParser.parse(["--no-op", "path/to/file"], switches: [op: :boolean]) {[op: false], ["path/to/file"], []}
When the :switches
option is given, OptionParser
will attempt to parse unknown switches:
iex> OptionParser.parse(["--debug"], switches: [key: :string]) {[debug: true], [], []}
Even though we haven’t specified --debug
in the list of switches, it is part of the returned options. This would also work:
iex> OptionParser.parse(["--debug", "value"], switches: [key: :string]) {[debug: "value"], [], []}
Switches followed by a value will be assigned the value, as a string. Switches without an argument will be set automatically to true
. Since we cannot assert the type of the switch value, it is preferred to use the :strict
option that accepts only known switches and always verify their types.
If you do want to parse unknown switches, remember that Elixir converts switches to atoms. Since atoms are not garbage-collected, OptionParser will only parse switches that translate to atoms used by the runtime to avoid leaking atoms. For instance, the code below will discard the --option-parser-example
switch because the :option_parser_example
atom is never used anywhere:
OptionParser.parse(["--option-parser-example"], switches: [debug: :boolean]) # The :option_parser_example atom is not used anywhere below
However, the code below would work as long as :option_parser_example
atom is used at some point later (or earlier) in the same module:
{opts, _, _} = OptionParser.parse(["--option-parser-example"], switches: [debug: :boolean]) opts[:option_parser_example]
In other words, Elixir will do the correct thing and only parse options that are used by the runtime, ignoring all others. If you would like to parse all switches, regardless if they exist or not, you can force creation of atoms by passing allow_nonexistent_atoms: true
as option. Use this option with care. It is only useful when you are building command-line applications that receive dynamically-named arguments and must be avoided in long-running systems.
A set of aliases can be specified in the :aliases
option:
iex> OptionParser.parse(["-d"], aliases: [d: :debug], strict: [debug: :boolean]) {[debug: true], [], []}
Here are some examples of working with different types and modifiers:
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(), options()) :: {parsed(), argv()} | no_return()
The same as parse_head/2
but raises an OptionParser.ParseError
exception if any invalid options are given.
If there are no errors, returns a {parsed, rest}
tuple where:
parsed
is the list of parsed switches (same as in parse_head/2
) rest
is the list of arguments (same as in 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(), options()) :: {parsed(), argv(), errors()}
Similar to parse/2
but only parses the head of argv
; as soon as it finds a non-switch, it stops parsing.
See parse/2
for more information.
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.t()) :: argv()
Splits a string into argv/0
chunks.
This function splits the given string
into a list of strings in a similar way to many shells.
iex> OptionParser.split("foo bar") ["foo", "bar"] iex> OptionParser.split("foo \"bar baz\"") ["foo", "bar baz"]
to_argv(Enumerable.t(), options()) :: argv()
Receives a key-value enumerable and converts it to argv/0
.
Keys must be atoms. Keys with nil
value are discarded, boolean values are converted to --key
or --no-key
(if the value is true
or false
, respectively), and all other values are converted using Kernel.to_string/1
.
It is advised to pass to to_argv/2
the same set of options
given to parse/2
. Some switches can only be reconstructed correctly with the switches
information in hand.
iex> OptionParser.to_argv(foo_bar: "baz") ["--foo-bar", "baz"] iex> OptionParser.to_argv(bool: true, bool: false, discarded: nil) ["--bool", "--no-bool"]
Some switches will output different values based on the switches flag:
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.7.3/OptionParser.html