ArgumentParser
Description
Tool for accepting command-line arguments, intended to be functionally similar to python's argparse
Parser
ArgumentParser is a struct with the following attributes:
:flags | A list of Flag Arguments
:positional | A list of Positional Arguments
:description | A string to print before generated help
:epilog | A string to print after generated help
:prefix_char | Char preceding flag arguments. Default `-`
:add_help | Print help when -h or --help is passed. Default true
:strict | Throw an error when an unexpected argument is found. Default false
An ArgumentParser can be created with new. Positional args can be added
with add_arg, flags with add_flag. When the parser is setup use
parse to parse.
Arguments
There are 2 types or arguments: positional and flag
Arguments are option lists where the first element is the name of the argument
as an atom. This name will be the key of the map returned by parse.
Arguments take the following options:
Flag Arguments
Flag arguments are defined with a prefix char. The default is -.
Flags can be either long form --flag or single character alias -f
Alias flags can be grouped: -flag == -f -l -a -g
Grouping only works if flags take no args.
Positional Arguments
Positional arguments have as their first element an atom which is their name Positional arguments will be consumed in the order they are defined. For example:
iex>ArgumentParser.parse(
...> ArgumentParser.new(positional: [[:one], [:two]]),
...> ["foo", "bar"])
{:ok, %{one: "foo", two: "bar"}}
Actions
Valid actions are
:store [default] | collects one argument and sets as string
{:store, nargs} | collects [nargs] arguments and sets as string
{:store, convert} | collects one argument and applys [convert] to it
{:store, nargs, convert} | collects [nargs] arguments and applys [convert] to them
{:store_const, term} | sets value to [term] when flag is present
:store_true | sets value to true when flag is present
:store_false | sets value to false when flag is present
:append | same as `:store`, but can use multiple times and stores as list
{:append, nargs} | ''
{:append, convert} | ''
{:append, nargs, convert} | ''
{:append_const, term, atom}| ''
:count | stores a count of # of times the flag is used
:help | print help and exit
{:version, version_sting} | print version_sting and exit
examples:
iex> ArgumentParser.new(flags: [[:tru, action: :store_true],
...> [:fls, action: :store_false],
...> [:cst, action: {:store_const, Foo}]]) |>
...> ArgumentParser.parse(~w[--tru --fls --cst])
{:ok, %{tru: true, fls: false, cst: Foo}}
iex> ArgumentParser.new() |>
...> ArgumentParser.add_flag(:apnd, action: :append) |>
...> ArgumentParser.add_arg(:star, action: {:store, :*}) |>
...> ArgumentParser.parse(~w[--apnd foo one two --apnd bar])
{:ok, %{apnd: ["bar", "foo"], star: ["one", "two"]}}
nargs
nargs can be:
postitive integer N | collect the next [N] arguments
:* | collect remaining arguments until a flag argument in encountered
:+ | same as :* but thows an error if no arguments are collected
:'?' | collect one argument if there is any left
:remainder | collect all remaining args regardless of type
actions :store and :append are the same as {:store, 1} and {:append, 1}
iex> ArgumentParser.new() |>
...> ArgumentParser.add_flag(:apnd, action: :append) |>
...> ArgumentParser.add_arg(:rmdr, action: {:store, :remainder}) |>
...> ArgumentParser.parse(~w[--apnd foo one two --apnd bar])
{:ok, %{apnd: ["foo"], rmdr: ["one", "two", "--apnd", "bar"]}}
convert
Convert can be any function with an arity of 1. If nargs is 1 or :'?' a String will be passed, otherwise a list of String will be
iex> ArgumentParser.new(positional: [
...> [:hex, action: {:store, &String.to_integer(&1, 16)}]]) |>
...> ArgumentParser.parse(["BADA55"])
{:ok, %{hex: 12245589}}
choices
A list of terms. If an argument is passed that does not match the coices an error will be returned.
iex> ArgumentParser.new() |>
iex> ArgumentParser.add_arg([:foo, choices: ["a", "b", "c"]]) |>
iex> ArgumentParser.parse(["foo", "x"], :false)
{:error, "value for foo should be one of ["a", "b", "c"], got foo"}
required
If true an error will be thown if a value is not set. Defaults to false.
flags only
default
Default value.
iex> ArgumentParser.new(positional: [[:dft, default: :foo]]) |>
...> ArgumentParser.parse([])
{:ok, %{dft: :foo}}
help
String to print for this flag's entry in the generated help output
Types
action ::
:store |
{:store, nargs} |
{:store, convert} |
{:store, nargs, convert} |
{:store_const, term} |
:store_true |
:store_false |
:append |
{:append, nargs} |
{:append, convert} |
{:append, nargs, convert} |
{:append_const, term, atom} |
:count |
:help |
{:version, String.t}
argument :: [atom | argument_option]
argument_option ::
{:alias, atom} |
{:action, action} |
{:choices, term} |
{:required, boolean} |
{:default, term} |
{:help, String.t} |
{:metavar, atom}
convert :: (String.t -> term)
nargs :: pos_integer | :"?" | :* | :+ | :remainder
t :: %ArgumentParser{add_help: boolean, description: String.t, epilog: String.t, flags: [argument], positional: [argument], prefix_char: char, strict: boolean}
Functions
print_help(parser)
Generate help string for a parser
Will print the description, followed by a generated description of all arguments followed by an epilog.
parse(parser, args, print_and_exit \ true)
Parse arguments according to the passed ArgumentParser.
Usually returns an {:ok, result} tuple. Exceptions are:
if error was encountered during parsing
If print_and_exit is :true a helpful error message is sent to stdout and
the process exits.
If print_and_exit is :false an {:error, reason} tuple is returned.
if help or version message should be printed
If print_and_exit is :true the message is sent to stdout and
the process exits.
If print_and_exit is :false a {:message, string} tuple is returned.
new(arguments \ [])
Create a new ArgumentParser
example:
iex> ArgumentParser.new(description: "Lorem Ipsum")
%ArgumentParser{description: "Lorem Ipsum", add_help: :true,
prefix_char: ?-, epilog: "",
flags: [], positional: []}
add_flag(parser, name, opts)
add_flag(parser, flag)
Append a flag arg to an ArgumentParser.
example:
iex> ArgumentParser.new(description: "Lorem Ipsum") |>
...> ArgumentParser.add_flag(:foo, required: :false, action: :store_true)
%ArgumentParser{description: "Lorem Ipsum", add_help: :true,
prefix_char: ?-, epilog: "",
flags: [[:foo, required: :false, action: :store_true]],
positional: []}
add_arg(parser, name, opts)
add_arg(parser, arg)
Append a positional arg to an ArgumentParser.
example:
iex> ArgumentParser.new(description: "Lorem Ipsum") |>
...> ArgumentParser.add_arg(:foo, required: :false, action: :store_true)
%ArgumentParser{description: "Lorem Ipsum", add_help: :true,
prefix_char: ?-, epilog: "",
flags: [],
positional: [[:foo, required: :false, action: :store_true]]}
ArgumentParser.Builder
Utility for easily creating modules that parse args using ArgumentParser.
@arg and @flag attributes can be used to define arguments similar to
the add_flag/2 and add_arg/2 functions.
Will create a private parse function.
The first argument to the parser function should be a list of binarys.
the second option is the print_and_exit flag, which defaults to :true.
parse([binary], :true) :: {:ok, Map.t}
parse([binary], :false) :: {:ok, Map.t} | {:error, term} | {:message,
iodata}
When the print_and_exit flag is :true messages and errors will be printed
to stdout and the process will exit.
ArgumentParser options can be passed in the use options.
use ArgumentParser.Builder, add_help: :false, strict: :true
If :description is not passed the @shortdoc or @moduledoc will be used
if present.
Example:
defmodule Script.Example do
use ArgumentParser.Builder
@arg [:name]
@flag [:bar, alias: :b, help: "get some beer at the bar"]
def run(args) do
{:ok, parsed} = parse(args)
main(parsed)
end
def main(%{name: "Homer"}) do
IO.puts("No Homers!")
end
def main(%{name: name, bar: bar}) do
IO.puts("Hey #{name} let's go to #{bar}!")
end
end