The core of Airline is its parser which takes in string arguments passed into the JVM and turns that into a command instance with appropriately populated fields that your code can then use to actually run its intended function.
The parser is designed to be highly customisable allowing various aspects to be configured to suit your purposes. For
example the User Defined Aliases feature allows you to permit end users to introduce their
own command shortcuts. Customisation is usually done by defining an appropriate @Parser
annotation on your @Command
annotated class or via the parserConfiguration
field of
your @Cli
annotation.
Please refer to the @Parser
documentation to understand the available fields for defining
your parser configuration. The rest of this page discusses the parser in general terms to help you understand how
Airline works in more detail.
Once you have a Cli
or SingleCommand
instance and call the parse()
or parseWithResult()
methods a complex
process kicks off. Airline takes the provided input arguments and attempts to interpret them according to your CLIs
metadata and your parser configuration. Broadly speaking the process has the following steps:
parse()
or parseWithResult()
was called)Steps 1-5 only apply to CLIs, for single commands step 6 onwards apply. Each of these steps may in of itself have multiple steps within it.
Error handling during the parsing process is described in the Error Handling and Exceptions document.
Command aliases are a feature of Airline that allows for both developer and user-defined command shortcuts. Please take a look at the User Defined Aliases document for more detail on this feature.
Airline optionally allows developers to enable a feature whereby command/group names and option names may be abbreviated
provided those abbreviations are unambiguous. This is described in more detail in the
@Parser
annotation documentation.
OptionParser
implementations control how Airline parses inputs into options and their values. By default Airline
supports 3 common option styles with a further two that may be enabled if desired. The default parsers are as follows:
StandardOptionParser
- Simple white space separated
option and values e.g. --name value
sets the option --name
to value
LongGetOptParser
- Long form GNU getopt
style e.g.
--name=value
sets the option --name
to value
ClassicGetOptParser
- Short form GNU getopt
style e.g.
-n1
sets the option -n
to 1
Additionally the following alternative styles are supported:
MaybePairValueOptionParser
- Arity 2 options where the
user may specify the values as whitespace/=
separated e.g. --name foo bar
and --name foo=bar
are both acceptable
and set the option --name
to the values foo
and bar
ListValueOptionParser
- Options that may be specified
multiple times can be specified in a compact comma separated list form e.g. --name foo,bar
sets the option --name
to the values foo
and bar
MaybeListValueOptionParser
- Options that may be
specified multiple times can be specified in a compact comma separated list form or whitespace separated e.g. e.g.
--name foo,bar
and --name foo bar
both sets the option --name
to the values foo
and bar
GreedyMaybeListValueOptionParser
- Similar to the above
MaybeListValueOptionParser
but greedy in how it consumes values for the list.Users may create their own option parsers if desired as discussed on the Custom Option Parsers page.
ClassicGetOptParser
The classic getopt
style parser only works with short form options i.e. those with a single character name e.g. -a
.
However, it is particularly useful for flag options, those which do not take a value (arity 0), in that it allows users
to specify multiple options together. For example the user input -ac
can be parsed into setting the -a
and -c
options assuming they are arity 0 i.e. flag options.
It also allows for a value to be provided to the final option in the sequence provided that it is an arity 1 option e.g.
-abe
sets the -a
option to true and the -b
options value as e
. Optionally the value to the last option in the
sequence may be provided as a separate value i.e. -ab e
is treated the same as -abe
As of 2.8.2 a bug fix to option parsers was made to make them less greedy when parsing options with values. Prior to
this change they could incorrectly parse a token that was intended to represent an option as a value. Considering the
above example if you had -abe
where -a
is a flag option and -b
has arity 1 the parser would previously have set
the value of -b
to be e
even if you also had a -e
option defined. From that release onwards this would now result
in an error if e
may itself be an option.
GreedyClassicGetOptParser
As of 2.8.2 a bug fix to option parsers was made that made them less greedy when parsing options with values, see the
example given for ClassicGetOptParser
above. While for most parsers this changes only impact was that parsing errors
were detected and reporting more reliably for the ClassicGetOptParser
this could cause noticeable change in behaviour.
In order to allow users the choice to preseve the old behaviour if needed a new
GreedyClassicGetOptParser
was provided in this release.
Per the above example with the greedy parser -abe
will set -a
and the value of -b
to e
regardless of whether
there is a -e
option defined.
MaybePairValueOptionParser
This parser is intended for arity 2 options where the user is providing key values pairs and so it may be natural for
the user to enter these as a single value separated by an =
sign but equally permits whitespace separation.
So both --conf key=value
and --conf key value
are acceptable to set the --conf
option to the values key
and
value
ListValueOptionParser
This parser requires that the list of values provided be an exact multiple of the arity of the option being set. So for
example if option --conf
has arity 2 it would allow --conf foo,bar
but not --conf foo,bar,faz
MaybeListValueOptionParser
Similar to the above ListValueOptionParser
except that it allows for whitespace separated values as well. So for
example if option --conf
has arity 2 it would allow --conf foo,bar
and --conf foo bar
This parser is non-greedy so when used with commands that also use @Arguments
or
@DefaultOption
it will not continue parsing list values that are whitespace
separated if those subsequent values could be considered as arguments/default option values.
GreedyMaybeListValueOptionParser
A greedy variant of the MaybeListValueOptionParser
that will continue to parse list values until it sees another
explicit option or the arguments separator. This could cause some values to be incorrectly interpreted so should be
used with care.
Airline converts the raw string values to the appropriate strong types as described in the Supported Types documentation. We make this process fully extensible as described in that document.
Global restrictions apply near the end of the passing process and so are able to inspect the final parser state and make appropriate decisions. See the Global Restrictions documentation for more details.
Assuming a successful parse of the user arguments Airline instantiates an instance of your command class and populates
it’s fields appropriately based upon the options and arguments that were seen. By default it uses the
DefaultCommandFactory
to create an instance of your command class, this supports any command class that has a zero
arguments constructor.
Like other aspects this can be customised where necessary by setting the commandFactory
field of your
@Parser
annotation. This might be useful this can be useful if you want to integrate
your CLI with a dependency injection framework or if your command classes have a more complex constructor.
Since 2.9.0 the annotations used to indicate to Airline that a field is used for composition and its type should be further inspected for relevant Airline annotations became fully configurable. This allows you to use an annotation of your choice for composition enabling better integration of Airline CLIs with dependency injection frameworks.
This can be customised via the compositionAnnotationClasses
field of your @Parser
annotation. Unlike similar fields of the annotation this takes the classes as String
class names rather than Class
objects. This allows Airline to have a default configuration that can dynamically support several different composition
annotations out of the box without knowing which is actually present at runtime in your application. See the
Composition documentation for more detail on this.
If your command class declares fields with the Java @AirlineModule
annotation (or another composition
annotation) that have Airline metadata types - GlobalMetadata
,
CommandGroupMetadata
and CommandMetadata
- then your command class instance will also have those populated with the
relevant parser metadata. This allows commands to introspect the CLI they belong to which can be extremely useful for
things like help commands.
This documentation is itself open source and lives in GitHub under the docs/ directory.
I am not a professional technical writer and as the developer of this software I can often make assumptions of
knowledge that you as a user reading this may not have. Improvements to the documentation are always welcome, if you
have suggestions for the documentation please submit pull requests to the main
branch.