4.6.0
Freundlich's C++ toolkit
|
Library for command-line options.
Link to ${fcppt_options_TARGET}
, or to fcppt_options_interface
if you only need the headers.
Passing arguments to a program is done via the main function, int main(int argc, char **argv)
, where argc
is the number of arguments and argv
points to the arguments themselves. The first argument, argv[0]
, is usually the name of the program, but does not have to be. Now, consider a program that expects a single integer argument: It first has to check if argc
is 2
and if so, it has to convert argv[1]
into an integer. If any of these two steps fails, it should also print an appropriate error message and exit. Handling arguments this way quickly gets out of hand. For example, we might have to deal with optional arguments, flags or arbitrary many arguments.
fcppt.options
features declarative parsers. Instead of writing parsing code by hand, we only write down the arguments and their types that our program excepts. A parser (if it succeeds) produces an fcppt::record::object. For example, a parser that expects a single integer with label name age
has type { age : int }
. Parsers can be combined to yield more complicated parsers, so for example a parser that expects zero or more strings with label name first_names
has type { first_names : std::vector<std::string> }
. Combining these two parsers yields a parser of type { age : int, first_names : std::vector<std::string> }
.
To start off, let us look at a simple example, where we expect a single argument of type int
. First, we declare the label to be used in the parser type:
Next, we declare the parser type that uses age_label
to produce a single value of type int
.
Such a parser parses a command-line like ./program 123
, yielding the record { age_label = 123 }
, which is of type result_type = { age_label : int }
. Next, we define the actual parser:
Here, we see that an fcppt::options::argument gets two parameters:
help_text
which can be used to explain the argument's purpose to the user. Instead of using argc
and argv
directly, we first use the helper function fcppt::args_from_second which copies every argument except the first (which usually holds the program's name but does not have to) into a container:
Parsing the arguments using a parser is done by calling the fcppt::options::parse function. Its result is an fcppt::options::result which is an fcppt::either::object that encapsulates the fact that a parser can fail.
Now, all that needs to be done is to inspect result
: First, we define a function called on_success
that receives result_type
(remember, this is a record of type { age_label : int }
) and prints it.
In case of failure we get an fcppt::options::error, telling the user what went wrong. In addition to that, we also print parser.usage()
which tells the user what the expected format is:
Finally, we use fcppt::either::match to call one of these functions:
Here are a few example invocations:
Parser types are split into basic and combinator parsers.
There are three different types of basic parsers:
Type: | Description: |
---|---|
fcppt::options::argument | Parses a single argument, e.g. "arg" . If there is no argument or it cannot be converted to the parser's result type, an error occurs. |
fcppt::options::flag | Parses a flag, e.g. "-f" or "--flag" . Depending on whether the flag was specified or not, the result type is either its inactive value or its active value. Flags never produce an error. fcppt::options::switch_ is a short-hand for a flag of type bool . |
fcppt::options::option | Parses an option, e.g. "-o val" or "--opt val" . Option parsers can have an optional default value which is used in case the option has not been specified. If there is no such option and no default value has been specified or the option's value cannot be converted to the parser's result type, an error occurs. |
fcppt::options::unit | A parser that parses nothing. This is useful, for example, when you want a sub-command that takes no arguments or options. |
fcppt::options::unit_switch | A flag that always has to be specified (e.g. if you want to parse "--help" ). |
The following parsers can be used to create more advanced parsers:
Type: | Description: |
---|---|
fcppt::options::product | A parser of type fcppt::options::product<Left,Right> combines two parsers of type Left and Right , which must have disjoint records. The product parser first tries the left parser and then the right parser. It only succeeds if both succeed. Its result type is the disjoint union (see fcppt::record::multiply_disjoint) of Left's and Right's result types. To combine two or more parsers at once, use fcppt::options::apply. |
fcppt::options::sum | A parser of type |
fcppt::options::optional | A parser of type |
fcppt::options::many | A parser of type |
fcppt::options::commands | A commands parser combines several sub-commands into a single parser. It gets a parser that parses options common to all sub-commands and for each sub-command, it gets a parser plus the name of the sub-command. For parsers
See fcppt::options::make_sub_command and fcppt::options::make_commands.
|
Passing a parser to another can be done in three different ways:
Imagine a program that copies an input file to an output file, with the following requirements:
".bak"
. We first start by declaring the labels the parsers are going to use:
The input filename is an argument parser of type fcppt::string.
The output filename is an optional argument parser. Its type is fcppt::optional::object<fcppt::string>
.
The execute flag is just a switch. It can be activated using "-e"
or "--execute"
.
To handle whether to append to the output file, we use a flag parser of type std::ios_base::openmode
. Its inactive value is the empty openmode, while its active value is std::ios_base::trunc
.
The log level is an option parser of type fcppt::log::level. It can be set using "-l level"
or "--loglevel level"
, where level
has to be one of fcppt::log::level's values. The parser also gets a default value of fcppt::log::level::warning
.
Finally, the actual parser is created using fcppt::options::apply. Its type is complicated, so it is shortened using auto
here. See Hiding parser implementation on how to hide a parser's actual type.
We also check what the result type of the parser is to make sure we did not miss anything.
The main program is a lambda function that gets result_type
as its parameter. This is a record that contains all the options of the parsers combined.
First, we check if the execute flag has been specified. If not, the executing stops.
Next, we create a log context that uses the log-level specified. Notice how the string specified on the command-line has already been converted to a value of fcppt::log::level.
We then open the input file using the input filename.
Opening the output file consists of two things: First, we need to check whether the output filename has been specified. If not, we use the default of input_file.bak
.
Secondly, the openmode needs to be passed as well.
Here is the output of the parser's usage:
Instead of creating one program per command, it is useful to combine several commands into a single parser, where the sub-command is chosen by a specific name. Examples of this are found in several programs, namely git
. For example, git clone
and git pull
are different commands that take different arguments and options themselves. However, the git
program itself can also take options common to all sub-commands, for example "--git-dir"
which specifies the directory of the repository. In fcppt, this is handled by fcppt::options::commands. First, we declare the parser for the common options:
This parser can optionally take a "--git-dir"
option.
Then, we declare two parsers, one for each sub-command. We want the clone
command to take exactly one argument, which is the path to clone from. The pull command, on the other hand, should take no arguments, for which we make use of the unit parser.
Next, we turn each of the parsers into a sub-command, giving it a name, a label and an optional help text. The label is important to make the types of the sub-commands disjoint.
Finally, we combine everything into a commands parser.
Here is an example showing how to use the parser's result. We first check if the optional git directory has been specified.
We then match on the two different sub-commands.
The main program prints the parser's usage in case of an error.
Here are some example invocations:
A help option is a special flag like "--help"
. If specified, the program should print its help text and not accept any other arguments. This layering of two parsers is implemented by fcppt::options::parse_help. It gets a parser of type fcppt::options::help_switch as its first argument, and a regular parser as its second argument. fcppt::options::default_help_switch is a switch that accepts "--help"
:
If the help switch matches, the function returns an fcppt::options::usage, otherwise it returns a regular fcppt::options::result.
In this example, parser
is a simple parser that parses an int:
Here are a few example invocations:
As seen in A more complex example, the type of a parser can get very complex, because it carries the exact types of all the parsers used to build it. In order to hide this, the base class fcppt::options::base can be used. Its only type parameter is the parser's result type, which means that we need to know the result type in advance. In the following example, we are going to expect a parser that returns an int and a bool:
Next, we define a function that creates such a parser. In a real program, this can be hidden away inside another translation unit:
The parser can then be used like any other parser:
It is also possible to use such an fcppt::options::base_unique_ptr as an argument to another parser:
The implementation of a parser consists of the following functions and types:
Type/Function: | Description |
---|---|
result_type | The type returned by a successful parse. |
fcppt::options::flag_name_set flag_names() const | A set of flag names (parameters without an argument) this parser recognizes. |
fcppt::options::option_name_set option_names() const | A set of option names (parameters with an argument) this parser recognizes. |
fcppt::options::usage usage() const | A description on how to use this parser. |
fcppt::options::parse_result<result_type> parse(fcppt::options::state &&, fcppt::options::parse_context const &) const | This is the main parsing function. An fcppt::options::state contains the current command-line and an fcppt::options::parse_context contains information about the surrounding parsers. An fcppt::options::parse_result contains either an error or a result together with the remaining state. |
The function fcppt::options::deref dereferences a parser, which currently can be a copy, an fcppt::reference or an fcppt::unique_ptr. This is used internally by a parser to access its sub-parsers.
Typedefs | |
template<typename Type > | |
using | fcppt::options::active_value = fcppt::strong_typedef<Type, fcppt::options::active_value_tag> |
A strong typedef used as a parser's active value. | |
template<typename Result > | |
using | fcppt::options::base_unique_ptr = fcppt::unique_ptr<fcppt::options::base<Result>> |
A unique pointer for fcppt::options::base. | |
template<typename Type > | |
using | fcppt::options::default_value = fcppt::strong_typedef<Type, fcppt::options::default_value_tag> |
A strong typedef used as a parser's default value. | |
template<typename Parser > | |
using | fcppt::options::deref_type = std::remove_cvref_t<fcppt::deref_type<Parser>> |
The dereferenced type of a parser. | |
using | fcppt::options::error_variant |
using | fcppt::options::flag_name_set = std::set<fcppt::options::flag_name> |
The set of flag names. | |
template<typename Result > | |
using | fcppt::options::help_result |
The result of invoking a regular parser and a help parser. | |
using | fcppt::options::help_switch = fcppt::options::unit_switch<fcppt::options::detail::help_label> |
The type of a help parser. | |
using | fcppt::options::help_text = fcppt::strong_typedef< fcppt::string ,_> |
A string type representing a help text. | |
template<typename Type > | |
using | fcppt::options::inactive_value = fcppt::strong_typedef<Type, fcppt::options::inactive_value_tag> |
A strong typedef used as a parser's inactive value. | |
template<typename Type > | |
using | fcppt::options::left = fcppt::strong_typedef<Type, fcppt::options::detail::left_tag> |
The left result type of a sum parser. | |
using | fcppt::options::long_name = fcppt::strong_typedef< fcppt::string ,_> |
A string type representing a long name. | |
using | fcppt::options::name = fcppt::strong_typedef< fcppt::string ,_> |
using | fcppt::options::option_name_set = std::set<fcppt::options::option_name> |
The set of option names. | |
using | fcppt::options::optional_help_text = fcppt::optional::object<fcppt::options::help_text> |
An optional help text. | |
using | fcppt::options::optional_short_name = fcppt::optional::object<fcppt::options::short_name> |
An optional short name. | |
using | fcppt::options::parse_error = fcppt::variant::object<fcppt::options::missing_error, fcppt::options::error> |
The error type returned by parsers. | |
template<typename T > | |
using | fcppt::options::parse_result |
The result of a parser. | |
template<typename T > | |
using | fcppt::options::result = fcppt::either::object<fcppt::options::error, T> |
The result of a parse operation. | |
template<typename Parser > | |
using | fcppt::options::result_of = typename fcppt::options::deref_type<Parser>::result_type |
The result of a parser type. | |
template<typename Type > | |
using | fcppt::options::right = fcppt::strong_typedef<Type, fcppt::options::detail::right_tag> |
The right result type of a sum parser. | |
using | fcppt::options::short_name = fcppt::strong_typedef< fcppt::string ,_> |
A string type representing a short name. | |
using | fcppt::options::usage_variant |
Functions | |
template<typename... Parsers> | |
auto | fcppt::options::apply (Parsers &&..._parsers) |
Combines two or more parsers. | |
FCPPT_OPTIONS_DETAIL_SYMBOL fcppt::options::help_switch | fcppt::options::default_help_switch () |
The default help switch. | |
template<typename Parser > | |
decltype(auto) | fcppt::options::deref (Parser const &_parser) |
Dereferences a parser. | |
FCPPT_OPTIONS_DETAIL_SYMBOL fcppt::io::ostream & | fcppt::options::operator<< (fcppt::io::ostream &, fcppt::options::error const &) |
template<typename Type > | |
fcppt::options::active_value< std::remove_cvref_t< Type > > | fcppt::options::make_active_value (Type &&_value) |
Creates an active value. | |
template<typename Result , typename Parser > | |
fcppt::options::base_unique_ptr< Result > | fcppt::options::make_base (Parser &&_parser) |
Creates an fcppt::options::base. | |
template<typename OptionsParser , typename... SubCommands> | |
fcppt::options::commands< std::remove_cvref_t< OptionsParser >, std::remove_cvref_t< SubCommands >... > | fcppt::options::make_commands (OptionsParser &&_options_parser, SubCommands &&..._sub_commands) |
Makes a commands parser. | |
template<typename Type > | |
fcppt::options::default_value< std::remove_cvref_t< Type > > | fcppt::options::make_default_value (Type &&_value) |
Creates a default value. | |
template<typename Type > | |
fcppt::options::inactive_value< std::remove_cvref_t< Type > > | fcppt::options::make_inactive_value (Type &&_value) |
Creates an inactive value. | |
template<typename Type > | |
fcppt::options::left< std::remove_cvref_t< Type > > | fcppt::options::make_left (Type &&_value) |
Creates an fcppt::options::left. | |
template<typename Parser > | |
fcppt::options::many< std::remove_cvref_t< Parser > > | fcppt::options::make_many (Parser &&_parser) |
Turns a parser into a many parser. | |
template<typename Parser > | |
fcppt::options::optional< std::remove_cvref_t< Parser > > | fcppt::options::make_optional (Parser &&_parser) |
Turns a parser into an optional parser. | |
template<typename Type > | |
fcppt::options::right< std::remove_cvref_t< Type > > | fcppt::options::make_right (Type &&_value) |
Creates an fcppt::options::right. | |
template<typename Tag , typename Parser > | |
fcppt::options::sub_command< Tag, std::remove_cvref_t< Parser > > | fcppt::options::make_sub_command (fcppt::string &&_name, Parser &&_parser, fcppt::options::optional_help_text &&_help_text) |
Makes a sub command. | |
template<typename Type > | |
fcppt::options::result< std::remove_cvref_t< Type > > | fcppt::options::make_success (Type &&_value) |
Creates a success value. | |
template<typename Label , typename Left , typename Right > | |
fcppt::options::sum< Label, std::remove_cvref_t< Left >, std::remove_cvref_t< Right > > | fcppt::options::make_sum (Left &&_left, Right &&_right) |
Creates the sum of two parsers. | |
template<typename Type > | |
fcppt::options::default_value< fcppt::optional::object< Type > > | fcppt::options::no_default_value () |
Creates an empty default value. | |
fcppt::options::FCPPT_RECORD_MAKE_LABEL (options_label) | |
The options label name in fcppt::options::commands. | |
template<typename Parser > | |
fcppt::options::result< fcppt::options::result_of< Parser > > | fcppt::options::parse (Parser const &_parser, fcppt::args_vector const &_args) |
Parse a command-line. | |
template<typename Parser > | |
fcppt::options::help_result< fcppt::options::result_of< Parser > > | fcppt::options::parse_help (fcppt::options::help_switch const &_help, Parser const &_parser, fcppt::args_vector const &_args) |
Parse a command-line with a help parser. | |
template<typename Type > | |
fcppt::options::type_name | fcppt::options::pretty_type () |
Returns a pretty type used for help texts. | |
fcppt::options::FCPPT_RECORD_MAKE_LABEL (sub_command_label) | |
The sub-command label name in fcppt::options::commands. | |
FCPPT_OPTIONS_DETAIL_SYMBOL fcppt::io::ostream & | fcppt::options::operator<< (fcppt::io::ostream &, fcppt::options::usage const &) |
using fcppt::options::active_value = fcppt::strong_typedef<Type, fcppt::options::active_value_tag> |
A strong typedef used as a parser's active value.
using fcppt::options::base_unique_ptr = fcppt::unique_ptr<fcppt::options::base<Result>> |
A unique pointer for fcppt::options::base.
Result | The result type of the parser. Must be an fcppt::record::object. |
using fcppt::options::default_value = fcppt::strong_typedef<Type, fcppt::options::default_value_tag> |
A strong typedef used as a parser's default value.
using fcppt::options::deref_type = std::remove_cvref_t<fcppt::deref_type<Parser>> |
The dereferenced type of a parser.
Parser | A regular parser, an fcppt::reference to a parser or an fcppt::unique_ptr to a parser. |
using fcppt::options::flag_name_set = std::set<fcppt::options::flag_name> |
The set of flag names.
Each string in this set is expected not to be followed by a value, e.g. "--foo".
using fcppt::options::help_result |
The result of invoking a regular parser and a help parser.
A help result is either a regular result or the usage of the parser.
using fcppt::options::help_switch = fcppt::options::unit_switch<fcppt::options::detail::help_label> |
The type of a help parser.
A help parser is a switch used to display a help message.
using fcppt::options::help_text = fcppt::strong_typedef< fcppt::string ,_> |
A string type representing a help text.
using fcppt::options::inactive_value = fcppt::strong_typedef<Type, fcppt::options::inactive_value_tag> |
A strong typedef used as a parser's inactive value.
using fcppt::options::left = fcppt::strong_typedef<Type, fcppt::options::detail::left_tag> |
The left result type of a sum parser.
using fcppt::options::long_name = fcppt::strong_typedef< fcppt::string ,_> |
A string type representing a long name.
A long name is the name of an argument, e.g. "arg", or the long name of an option or flag, e.g. "--foo".
using fcppt::options::name = fcppt::strong_typedef< fcppt::string ,_> |
using fcppt::options::option_name_set = std::set<fcppt::options::option_name> |
The set of option names.
Each string in this set is expected to be followed by a value, e.g. "--foo bar".
An optional help text.
An optional short name.
using fcppt::options::parse_error = fcppt::variant::object<fcppt::options::missing_error, fcppt::options::error> |
The error type returned by parsers.
An error can either be caused by a missing argument or option, or by something else like a failed conversion.
using fcppt::options::parse_result |
The result of a parser.
On success, a parser returns a value and the remaining state.
using fcppt::options::result = fcppt::either::object<fcppt::options::error, T> |
The result of a parse operation.
The result of a parse is either T or an fcppt::options::error.
using fcppt::options::result_of = typename fcppt::options::deref_type<Parser>::result_type |
The result of a parser type.
using fcppt::options::right = fcppt::strong_typedef<Type, fcppt::options::detail::right_tag> |
The right result type of a sum parser.
using fcppt::options::short_name = fcppt::strong_typedef< fcppt::string ,_> |
A string type representing a short name.
A short name is the short name of an option or flag, e.g. "-f".
|
inline |
Combines two or more parsers.
Combines two or more parsers into a single one that parses everything the individual parsers do. Because the resulting parser produces a record that contains all labels of the individual parsers, the label sets of the individual parsers must be pairwise disjoint.
Parsers | Must be at least two parsers. |
FCPPT_OPTIONS_DETAIL_SYMBOL fcppt::options::help_switch fcppt::options::default_help_switch | ( | ) |
The default help switch.
The default help switch that use "-h" or "--help".
|
inline |
Dereferences a parser.
Parsers can be stored by copy, by reference or by unique pointer.
fcppt::options::FCPPT_RECORD_MAKE_LABEL | ( | options_label | ) |
The options label name in fcppt::options::commands.
fcppt::options::FCPPT_RECORD_MAKE_LABEL | ( | sub_command_label | ) |
The sub-command label name in fcppt::options::commands.
|
inline |
Creates an active value.
fcppt::options::base_unique_ptr< Result > fcppt::options::make_base | ( | Parser && | _parser | ) |
Creates an fcppt::options::base.
Creates a unique pointer to fcppt::options::base, using the concrete parser _parser as its implementation. It is possible that the result type of Parser is a permuted version of Result.
Result | The result type of the parser. Must be an fcppt::record::object. |
|
inline |
Makes a commands parser.
SubCommands | A parameter pack of fcppt::options::sub_command. |
|
inline |
Creates a default value.
Type | Must be an fcppt::optional::object. |
|
inline |
Creates an inactive value.
|
inline |
Creates an fcppt::options::left.
|
inline |
Turns a parser into a many parser.
Normally, a parser can be applied exactly once. This function turns a parser into a parser that can be applied zero or more times.
|
inline |
Turns a parser into an optional parser.
Normally, a parser can fail, for example in case an argument has not been specified. This function turns a parser into a parser that instead of failing returns optional results.
|
inline |
Creates an fcppt::options::right.
|
inline |
Makes a sub command.
|
inline |
Creates a success value.
|
inline |
Creates the sum of two parsers.
|
inline |
Creates an empty default value.
FCPPT_OPTIONS_DETAIL_SYMBOL fcppt::io::ostream & fcppt::options::operator<< | ( | fcppt::io::ostream & | , |
fcppt::options::error const & | ) |
FCPPT_OPTIONS_DETAIL_SYMBOL fcppt::io::ostream & fcppt::options::operator<< | ( | fcppt::io::ostream & | , |
fcppt::options::usage const & | ) |
fcppt::options::result< fcppt::options::result_of< Parser > > fcppt::options::parse | ( | Parser const & | _parser, |
fcppt::args_vector const & | _args ) |
Parse a command-line.
Applies _parser to _args.
fcppt::options::help_result< fcppt::options::result_of< Parser > > fcppt::options::parse_help | ( | fcppt::options::help_switch const & | _help, |
Parser const & | _parser, | ||
fcppt::args_vector const & | _args ) |
Parse a command-line with a help parser.
First, the switch parser _help is applied to _args. If its switch and nothing else is specified, the usage
string is gathered from _parser and returned. Otherwise, if the switch of _help was not specified, then the result of applying _parser to _args is returned.
|
inline |
Returns a pretty type used for help texts.
Using fcppt::options::pretty_type_impl, one can specialize how a type name is represented as a string. For example, the pretty name of std::string
is simply string
instead of std::basic_string<char,std::char_traits<char>,std::allocator<char>>
.