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 valueLongGetOptParser - Long form GNU getopt style e.g.
--name=value sets the option --name to valueClassicGetOptParser - Short form GNU getopt style e.g.
-n1 sets the option -n to 1Additionally 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 barListValueOptionParser - 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 barMaybeListValueOptionParser - 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 barGreedyMaybeListValueOptionParser - 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.
ClassicGetOptParserThe 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.
GreedyClassicGetOptParserAs 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.
MaybePairValueOptionParserThis 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
ListValueOptionParserThis 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
MaybeListValueOptionParserSimilar 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.
GreedyMaybeListValueOptionParserA 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.