TAP
|
This is TAP, a library for command line argument parsing ala get_opt_long(). It is a header-only library with a bunch of templated classes that ought to make argument parsing simple. The main reasons for the existence of this library:
Try before you buy, check some of the examples, and otherwise look at for instance boost::program_options, TCLAP, get_opt() (ha), "The Lean Mean C++ Option Parser", cpp-optparse, or just check http://stackoverflow.com/questions/865668/parse-command-line-arguments.
As this is a header-only library, no install is necessary. Just drop the directory 'tap' with all headers somewhere in your include path, and all should be fine.
To use the library, first add a
to your sources, then simply code away. All members of TAP are defined in the TAP namespace.
Quickstart:
Argument parsing starts with defining a number of TAP::Argument instances, adding them to an TAP::ArgumentParser, and passing along the actual program arguments (as received from main()) to the parser. If all goes well, you can read in the parsed data from the arguments, otherwise an TAP::exception will be thrown.
The examples below assume TAP_AUTOFLAG has been defined, see Configuration for details.
At the basic level, an argument consists of a description, and zero or more aliases. Aliases can be used to name the argument on the command line, either as a flag or as a name (see TAP::ArgumentParser for details). One particular remark about aliases: If an argument is created without an alias, it is marked as positional. Any alias defined later does not change this. This allows positional arguments to be defined, that can also be accessed via a name or flag.
The description can be used to define aliases as well. To do so, mark the flags or names to use in the description (see TAP::Argument::parse_description()). You can use this to save on typing when defining arguments.
Multiple argument classes exist that can be used, in short they are
By default, all arguments are optional, and can occur at most once. To change this behavior, each argument has the following functions:
Regular arguments by default are optional and can occur at most once. Multi* arguments can occur many times. Note that for most TypedArgument types (except Multi*), if the argument is allowed to occur multiple times, its value is overwritten on each occurrence.
A common occurrence of arguments that are allowed to occur multiple times, but sometimes limited, are verbosity or debugging level arguments. For example:
Note that there is a (small) semantic difference between a required argument and the minimum number of occurrences. If required() is true, this only means the argument has to occur somewhere. The min() value dictates how many times. If required() is false, the argument is also alowed to be absent, even if min is not zero. In fact, min is required to be always at least 1.
It is possible to assign a callback to an TAP::Argument that is called whenever the argument is set. For example:
For details see TAP::Argument::check() and TAP::ArgumentCheckFunc.
Similarly, TAP::TypedArgument also allows for a callback with the value that was set, for example:
For details see TAP::TypedArgument::check() and TAP::TypedArgumentCheckFunc.
Every now and then some arguments can only occur in certain combinations or have some sort of constraint associated with them (aside from the number of occurrences allowed or required, see Required arguments and argument counts). To specify this, arguments can be added (recursively) into TAP::ArgumentConstraint instances, which specify a certain constraint on the occurrences of arguments relative to each other. Most commonly, exactly one argument must be selected out of a group of many.
To specify such a constraint, create an instance of TAP::ArgumentConstraint, templated to TAP::ConstraintType to specify which constraint, and add the constrained arguments. For example:
In this example, left and right cannot be set both at the same time. Should either left or right be selected (so selecting neither is invalid), set the constraint as required with set_required().
Note: Be careful when adding arguments that are required to constraints with an upper bound on the number of allowed arguments (such as TAP::ConstraintType::One). This can lead to situations where the constraint can never be satisfied, as all of its arguments are required, but the constraint prohibits this.
For the common case of mutually exclusive arguments, the hat operator (binary XOR) has been defined for arguments to create a TAP::ConstraintType::One constraint of the given arguments. For example:
Similarly, the OR operator (|) is defined for TAP::ConstraintType::Any, and the AND operator (&) is defined for TAP::ConstraintType::All.
Furthermore, unary operators + and - set an argument respectively as required or optional. Thus, in the above example, to require exactly left or right to be set, you can use:
Parsing arguments is relatively straight-forward. After defining all arguments and an argument parser, with the arguments added to the parser, simply invoke TAP::ArgumentParser::parse and done. If an error occurs, an exception of the type TAP::exception (or a subclass thereof) will be thrown.
Arguments can be added either in the constructor, or using the TAP::ArgumentParser::add() method.
To group arguments (useful mostly for the help text) a TAP::ArgumentSet can be created (similar to a constraint), with a given name. When added to the parser, its children are grouped separately in the help text.
To determine if an argument is set, converting to bool is possible, e.g.
Keep in mind that for arguments that actually store a bool, this is not the same as its value.
To get the number of occurrences, see the TAP::Argument::count() method. For TAP::TypedArgument instances, the value can be retrieved using TAP::TypedArgument::value(). Note that for Multi valued arguments, the value is automatically set to a vector.
TAP allows for some configuration in the main header file. The following settings alter some of its behavior:
Aside from these options, other defines allow some of the syntax to be tweaked (see Tap.h for more details):
Though the library is intended to use relatively easy to use, it may not always do what is expected. Some quirks are listed here: