![]() |
CLI11 2.6.2
C++11 Command Line Interface Parser
|
You can tell your app to allow configure files with set_config("--config"). There are four arguments: the first is the option name. If empty, it will clear the config flag. The second item is the default file name. If that is specified, the config will try to read that file. The third item is the help string, with a reasonable default, and the final argument is a boolean (default: false) that indicates that the configuration file is required and an error will be thrown if the file is not found and this is set to true. The option pointer returned by set_config is the same type as returned by add_option and all modifiers including validators, and checks are valid.
if it is desired that config files be searched for a in a default path the CLI::FileOnDefaultPath transform can be used.
This will allow specified files to either exist as given or on a specified default path.
Multiple default paths can be specified through this mechanism. The last transform given is executed first so the error return must be disabled so it can be chained to the first. The same effect can be achieved though the or(|) operation with validators
Sometimes configuration files are used for multiple purposes so CLI11 allows options on how to deal with extra fields
will allow capture the extras in the extras field of the app. (NOTE: This also sets the allow_extras in the app to true)
will generate an error if there are any extra fields for slightly finer control there is a scoped enumeration of the modes or
will completely ignore extra parameters in the config file. This mode is the default.
will store the unrecognized options in the app extras fields. This option is the closest equivalent to app.allow_config_extras(true); with the exception that it does not also set the allow_extras flag so using this option without also setting allow_extras(true) will generate an error which may or may not be the desired behavior.
is equivalent to app.allow_config_extras(false);
will completely ignore any mismatches, extras, or other issues with the config file
Config file extras are stored in the remaining output as two components. The first is the name of the field including subcommands using dot notation the second (or more) are the argument fields.
If it is needed to get the configuration file name used this can be obtained via app.get_config_ptr()->as<std::string>() or app["--config"]->as<std::string>() assuming --config was the configuration option name.
By default if multiple configuration files are given they are read in reverse order. With the last one given taking precedence over the earlier ones. This behavior can be changed through the multi_option_policy. For example:
will read the files in the order given, which may be useful in some circumstances. Using CLI::MultiOptionPolicy::TakeLast would work similarly getting the last N files given. The default policy for config options is CLI::MultiOptionPolicy::Reverse which takes the last expected N and reverses them so the last option given is given precedence.
Here is an example configuration file, in TOML format:
Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be true, on, 1, y, t, +, yes, enable; or false, off, 0, no, n, f, -, disable, (case-insensitive). Sections (and . separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults". If a subcommand is set to configurable then passing the subcommand using [sub] in a configuration file will trigger the subcommand.)
CLI11 also supports configuration file in INI format.
The main differences are in vector notation and comment character. Note: CLI11 is not a full TOML parser as it just reads values as strings. It is possible (but not recommended) to mix notation.
The default config file parser supports multi-line strings like the toml standard TOML. It also supports multiline comments like python doc strings.
The key is that the closing of the multiline string must be at the end of a line and match the starting 3 quote sequence. Multiline sequences using """ allow escape sequences. Following TOML with the addition of allowing '\0' for a null character, and binary Strings described in the next section. This same formatting also applies to single line strings. Multiline strings are not allowed as part of an array.
Config files have a binary conversion capability, this is mainly to support writing config files but can be used by user generated files as well. Strings with the form B"(XXXXX)" will convert any characters inside the parenthesis with the form \xHH to the equivalent binary value. The HH are hexadecimal characters. Characters not in this form will be translated as given. If argument values with unprintable characters are used to generate a config file this binary form will be used in the output string.
Vector arguments can also be multiline
It is possible to specify vector of vector inputs in config file. This can be done in a few different ways
The %% is ignored in multiline format if the inject_separator modifier on the option is set to false, thus for vector 3 if the option is storing to a single vector all the elements will be in that vector.
For config file multiple sequential duplicate variable names are treated as if they are a vector input, with possible separator insertion in the case of multiple input vectors.
The config parser has a modifier
This modification will insert the separator between each line even if not sequential. This allows an input option to be configured with multiple lines.
The field insertion has a special processing for duplicate characters starting with "[[" in which case the "[]" gets translated to [[]] before getting passed into the option which converts it back into the correct string. This can also be used on the command line to handle unusual parsing situation with brackets.
There is an edge case with actual strings that are surrounded by brackets. For example if the string "[]" needed to be passed. this would normally trigger the bracket processing and result in an empty vector. In this case it can be enclosed in quotes and should be handled correctly.
If it is desired that multiple configuration be allowed. Use
Where X is some positive integer and will allow up to X configuration files to be specified by separate --config arguments.
To print a configuration file from the passed arguments, use one of the following overloads:
The write_description argument will include option descriptions and the App description.
if a prefix is needed to print before the options, for example to print a config for just a subcommand, the config formatter can be obtained directly.
The formatter also has an overload taking CLI::ConfigOutputMode:
The default config parser/generator has some customization points that allow variations on the TOML format. The default formatter has a base configuration that matches the TOML format. It defines 5 characters that define how different aspects of the configuration are handled. You must use get_config_formatter_base() to have access to these fields
These can be modified via setter functions
For example, to specify reading a configure file that used : to separate name and values:
The default configuration file will read INI files, but will write out files in the TOML format. To specify outputting INI formatted files use
which makes use of a predefined modification of the ConfigBase class which TOML also uses. If a custom formatter is used that is not inheriting from the from ConfigBase class get_config_formatter_base() will return a nullptr if RTTI is on (usually the default), or garbage if RTTI is off, so some care must be exercised in its use with custom configurations.
You can invent a custom format and set that instead of the default INI formatter. You need to inherit from CLI::Config and implement the following two functions:
The CLI::ConfigItems that you return are simple structures with a name, a vector of parents, and a vector of results. A optionally customizable to_flag method on the formatter lets you change what happens when a ConfigItem turns into a flag.
Finally, set your new class as new config formatter:
See examples/json.cpp for a complete JSON config example.
The parser can handle these structures with only a minor tweak
The open and close brackets must be on a separate line and the comma gets interpreted as an array separator but since no values are after the comma they get ignored as well. This will not support multiple layers or sections or any other moderately complex JSON, but can work if the input file is simple.
Configuration files can be used to trigger subcommands if a subcommand is set to configure. By default configuration file just set the default values of a subcommand. But if the configure() option is set on a subcommand then the if the subcommand is utilized via a [subname] block in the configuration file it will act as if it were called from the command line. Subsubcommands can be triggered via [subname.subsubname]. Using the [[subname]] will be as if the subcommand were triggered multiple times from the command line. This functionality can allow the configuration file to act as a scripting file.
For custom configuration files this behavior can be triggered by specifying the parent subcommands in the structure and ++ as the name to open a new subcommand scope and -- to close it. These names trigger the different callbacks of configurable subcommands.
In addition to the regular parse functions a parse_from_stream(std::istream &input) is available to directly parse a stream operator. For example to process some arguments in an already open file stream. The stream is fed directly in the config parser so bypasses the normal command line parsing.
The config file input works with any form of the option given: Long, short, positional, or the environment variable name. When generating a config file it will create an option name in following priority.
In config files the name will be enclosed in quotes if there is any potential ambiguities in parsing the name.