JustBash.FlagParser (JustBash v0.4.0)
View SourceA shared module for parsing command-line flags in bash commands.
Supports:
- Boolean flags:
-a,-l,-v - Combined flags:
-la(equivalent to-l -a) - Value flags:
-n 10,-d ","(flag that takes next argument) - Getopt clusters ending in a value flag:
-nk2is-n -k 2 - Stop parsing at
-- --help, answered from the spec itself
A flag the spec does not describe is an error, never an operand. Demoting it
turned sort -Q file into a read of a file named -Q, which sort reports as
nothing at all: empty stdout, empty stderr, exit 0. Callers get
{:error, {:unknown_flag, flag}} and report it with format_error/3.
Usage
# Define your flag spec
spec = %{
boolean: [:a, :l, :v, :r],
value: [:n, :d],
integer: [:n],
value_labels: %{n: "number of lines"},
defaults: %{a: false, l: false, v: false, r: false, n: 10, d: nil}
}
# Parse arguments
case FlagParser.parse(args, spec) do
{:ok, flags, rest} -> ...
:help -> FlagParser.help("ls", spec)
{:error, reason} -> FlagParser.format_error("ls", reason, @usage)
endFlag Specification
:boolean- List of single-character atoms for boolean flags:value- List of single-character atoms for flags that take a value:defaults- Map of default values for all flags:aliases- Map of flag string to atom, for spellings that are not the atom itself ("R" => :r,"-recursive" => :r):multi_value- Value flags that accumulate a list instead of overwriting:integer- Value flags whose value is a count. Only these are converted; everything else stays a string, sosort -t 1is the delimiter"1":value_labels- What an:integerflag counts, as GNU names it ininvalid number of lines: 'abc'. Required for every:integerflag:usage- The synopsis linehelp/2prints, defaulting to"<command> [OPTION]..."
Summary
Types
Functions
Render a parse/2 error the way GNU coreutils words it, followed by usage.
A short option is named by its character and a long option in full, because
that is the unit that was rejected — -laQ is a bad Q, and
invalid option -- '-' for --nope identifies nothing.
Examples
iex> FlagParser.format_error("sort", {:unknown_flag, "Q"}, "")
"sort: invalid option -- 'Q'\n"
iex> FlagParser.format_error("sort", {:unknown_flag, "--nope"}, "")
"sort: unrecognized option '--nope'\n"
iex> FlagParser.format_error("head", {:invalid_value, "number of lines", "abc"}, "")
"head: invalid number of lines: 'abc'\n"
The usage Try '<command> --help' for more information. promises.
Rendered from the spec, so it lists exactly the flags the parser accepts and cannot drift from them.
Examples
iex> spec = %{boolean: [:a], value: [:n], defaults: %{a: false, n: nil}}
iex> FlagParser.help("demo", spec)
"Usage: demo [OPTION]...\nOptions this shell implements:\n -a\n -n VALUE\n"
@spec parse([String.t()], flag_spec()) :: parse_result()
Parse command-line arguments according to the given flag specification.
Returns {:ok, flags, remaining_args} where:
flagsis a map containing all flag valuesremaining_argsis a list of non-flag arguments
Returns :help for --help, and {:error, reason} for the first argument
that is flag-shaped but not in the spec, for a value flag with nothing after
it, and for a value declared :integer that is not a number.
Examples
iex> spec = %{boolean: [:a, :l], value: [:n], integer: [:n], value_labels: %{n: "number of lines"}, defaults: %{a: false, l: false, n: 10}}
iex> FlagParser.parse(["-a", "-n", "5", "file.txt"], spec)
{:ok, %{a: true, l: false, n: 5}, ["file.txt"]}
iex> spec = %{boolean: [:a, :l], value: [], defaults: %{a: false, l: false}}
iex> FlagParser.parse(["-al", "dir"], spec)
{:ok, %{a: true, l: true}, ["dir"]}
iex> spec = %{boolean: [:a, :l], value: [], defaults: %{a: false, l: false}}
iex> FlagParser.parse(["-Q", "dir"], spec)
{:error, {:unknown_flag, "Q"}}