CLI11, a powerful library for writing beautiful command line interfaces in C++11, has been updated to 1.6, the largest update ever. CLI11 output is more customizable than ever, and has a better functionality separation under the hood.
CLI11 has had the formatting system completely redesigned, with minor or complete customization of the output possible. Configuration files reading and writing also can be configured; a new example with json instead of ini formatting is included. Validators (finally) have custom help output, as well. Many odd corner cases have been made possible, such as interleaving options.
Key new features:
Formatters
You can customize the default CLI::Formatter
for small output changes:
app.get_formatter()->column_width(25);
app.get_formatter()->label("REQUIRED", "(MUST HAVE)");
The label in this case is a mapping from an internal label (which happens to be the default output of CLI11) to a new output string.
If you want to make larger changes, you can subclass and modify
CLI11::Formatter
, then set the formatter. You can also make your own brand new
formatter, either by inheriting from CLI::FormatterBase
or using an arbitrary
function in CLI::FormatterLambda
.
auto optfmt = std::make_shared<MyFormatter>();
app.formatter(optfmt);
To enable customization, all internal properties used by help printing now have
a public get_*
API. New support for adding a help_all
flag has been added,
as well.
Like most other parts of CLI11, formatters are inherited by subcommands, and you can set new ones per subcommand if you wish.
Config files
You can now customize a command’s configuration output and input. See
examples/json.cpp
for an example of reading and writing json instead of ini format.
Validators
Validators are now much, much more powerful. A new validator class has been added (with a lambda function version to allow old custom validators to still work). All built-in validators use the new technology. For example, if you have a file or a range:
app.add_option("--file", file)->check(CLI::ExistingFile);
app.add_option("--value", x)->check(CLI::Range(3, 6));
You now get much better help output:
--file FILE File name
--value INT in [3 - 6] Value in range
And much better error messages:
./examples/validators --value 9
--value: Value 9 not in range 3 to 6
Run with --help for more information.
And you can combine validators with |
and &
. A new Validators class allows
you to create your own validators with custom output.
Smaller features
The API for types has been improved; for example, to set up a vector of two
element items, where 2, 4, 6, … items are expected:
->type_name("X Y")->type_size(-2)
(also newly supported). Type names are now
internally lambda functions instead of strings; this means that changing a set
after creation will correctly be updated in the help message!
If you want to add a simple callback, ->each(void(string))
makes this easy.
You can also initialize with an empty function, so that makes odd constructions
like the following possible:
std::vector<std::string> vals;
app->add_option("--vals", {})
->each([&vals](std::string s){ vals.push_back(s); })
->type_name("STRING")
->type_size(-1);
This is basically how the vector add_option
is implemented, with the exception
that this one will add items exactly in parse order (only matters if
interleaving options).
The get_options
, get_subcommands
have learned to accept a filter; an empty
filter returns all items.
Testing has been improved, as well; you no longer have to write app.reset()
before rerunning the parser, even if an exception is thrown. Testing and
examples now expects submodules to be checked out.
See the release notes for more details, checkout the readme and the GitBook tutorial series, and update today!
CLI11 was developed at the University of Cincinnati to support of the GooFit library under NSF Award 1414736.