1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-04-29 12:13:52 +00:00

style: run pre-commit on linewidth

This commit is contained in:
Henry Schreiner 2022-05-07 00:03:47 -04:00 committed by Henry Schreiner
parent c1465e6163
commit 4f14dbde63
22 changed files with 2077 additions and 734 deletions

View File

@ -19,7 +19,9 @@ install:
build_script:
- mkdir build
- cd build
- ps: cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_GENERATOR="Visual Studio 14 2015"
- ps:
cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE_TESTS=ON
-DCMAKE_BUILD_TYPE=Debug -DCMAKE_GENERATOR="Visual Studio 14 2015"
- ps: cmake --build .
- cd ..
- conan create . CLIUtils/CLI11

View File

@ -1,7 +1,11 @@
steps:
- task: CMake@1
inputs:
cmakeArgs: .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=$(cli11.single) -DCMAKE_CXX_STANDARD=$(cli11.std) -DCLI11_SINGLE_FILE_TESTS=$(cli11.single) -DCMAKE_BUILD_TYPE=$(cli11.build_type) $(cli11.options)
cmakeArgs:
.. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=$(cli11.single)
-DCMAKE_CXX_STANDARD=$(cli11.std)
-DCLI11_SINGLE_FILE_TESTS=$(cli11.single)
-DCMAKE_BUILD_TYPE=$(cli11.build_type) $(cli11.options)
displayName: "Configure"
- script: cmake --build .

View File

@ -11,5 +11,7 @@ steps:
destinationFolder: "cmake_program"
displayName: Extract CMake
- bash: echo "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.14.3-Linux-x86_64/bin"
- bash:
echo
"##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.14.3-Linux-x86_64/bin"
displayName: Add CMake to PATH

View File

@ -4,15 +4,9 @@
FormatStyle: file
Checks: >
-*,
google-*,
-google-runtime-references,
llvm-include-order,
llvm-namespace-comment,
misc-throw-by-value-catch-by-reference,
modernize*,
-modernize-use-trailing-return-type,
readability-container-size-empty,
-*, google-*, -google-runtime-references, llvm-include-order,
llvm-namespace-comment, misc-throw-by-value-catch-by-reference, modernize*,
-modernize-use-trailing-return-type, readability-container-size-empty,
WarningsAsErrors: "*"

View File

@ -1,8 +1,10 @@
# Contributing
Thanks for considering to write a Pull Request (PR) for CLI11! Here are a few guidelines to get you started:
Thanks for considering to write a Pull Request (PR) for CLI11! Here are a few
guidelines to get you started:
Make sure you are comfortable with the license; all contributions are licensed under the original license.
Make sure you are comfortable with the license; all contributions are licensed
under the original license.
## Adding functionality
@ -13,25 +15,36 @@ Make sure any new functions you add are are:
- Explained in your PR (or previously explained in an Issue mentioned in the PR)
- Completely covered by tests
In general, make sure the addition is well thought out and does not increase the complexity of CLI11 needlessly.
In general, make sure the addition is well thought out and does not increase the
complexity of CLI11 needlessly.
## Things you should know
- Once you make the PR, tests will run to make sure your code works on all supported platforms
- Once you make the PR, tests will run to make sure your code works on all
supported platforms
- The test coverage is also measured, and that should remain 100%
- Formatting should be done with pre-commit, otherwise the format check will not pass. However, it is trivial to apply this to your PR, so don't worry about this check. If you do want to run it, see below.
- Everything must pass clang-tidy as well, run with `-DCLI11_CLANG_TIDY=ON` (if you set `-DCLI11_CLANG_TIDY_OPTIONS="-fix"`, make sure you use a single threaded build process, or just build one example target).
- Your changes must also conform to most of the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) rules checked by [cpplint](https://github.com/cpplint/cpplint). For unused cpplint filters and justifications, see [CPPLINT.cfg](/CPPLINT.cfg).
- Formatting should be done with pre-commit, otherwise the format check will not
pass. However, it is trivial to apply this to your PR, so don't worry about
this check. If you do want to run it, see below.
- Everything must pass clang-tidy as well, run with `-DCLI11_CLANG_TIDY=ON` (if
you set `-DCLI11_CLANG_TIDY_OPTIONS="-fix"`, make sure you use a single
threaded build process, or just build one example target).
- Your changes must also conform to most of the
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
rules checked by [cpplint](https://github.com/cpplint/cpplint). For unused
cpplint filters and justifications, see [CPPLINT.cfg](/CPPLINT.cfg).
## Pre-commit
Format is handled by pre-commit. You should install it (or use [pipx](https://pypa.github.io/pipx/)):
Format is handled by pre-commit. You should install it (or use
[pipx](https://pypa.github.io/pipx/)):
```bash
python3 -m pip install pre-commit
```
Then, you can run it on the items you've added to your staging area, or all files:
Then, you can run it on the items you've added to your staging area, or all
files:
```bash
pre-commit run
@ -39,7 +52,8 @@ pre-commit run
pre-commit run --all-files
```
And, if you want to always use it, you can install it as a git hook (hence the name, pre-commit):
And, if you want to always use it, you can install it as a git hook (hence the
name, pre-commit):
```bash
pre-commit install
@ -47,7 +61,8 @@ pre-commit install
## For developers releasing to Conan.io
This is now done by the CI system on tagged releases. Previously, the steps to make a Conan.io release were:
This is now done by the CI system on tagged releases. Previously, the steps to
make a Conan.io release were:
```bash
conan remove '*' # optional, I like to be clean
@ -59,7 +74,10 @@ Here I've assumed that the remote is `cli11`.
## For maintainers: remember to add contributions
In a commit to a PR, just add "`@all-contributors please add <username> for <contributions>`" or similar (see <https://allcontributors.org>). Use `code` for code, `bug` if an issue was submitted, `platform` for packaging stuff, and `doc` for documentation updates.
In a commit to a PR, just add
"`@all-contributors please add <username> for <contributions>`" or similar (see
<https://allcontributors.org>). Use `code` for code, `bug` if an issue was
submitted, `platform` for packaging stuff, and `doc` for documentation updates.
To run locally, do:
@ -70,7 +88,8 @@ yarn all-contributors add username code,bug
## For maintainers: Making a release
Remember to replace the emoji in the readme, being careful not to replace the ones in all-contributors if any overlap.
Remember to replace the emoji in the readme, being careful not to replace the
ones in all-contributors if any overlap.
Steps:

View File

@ -2,28 +2,55 @@
## Version 2.2: Option and Configuration Flexibility
New features include support for output of an empty vector, a summing option policy that can be applied more broadly, and an option to validate optional arguments to discriminate from positional arguments. A new validator to check for files on a default path is included to allow one or more default paths for configuration files or other file arguments. A number of bug fixes and code cleanup for various build configurations. Clean up of some error outputs and extension of existing capability to new types or situations.
New features include support for output of an empty vector, a summing option
policy that can be applied more broadly, and an option to validate optional
arguments to discriminate from positional arguments. A new validator to check
for files on a default path is included to allow one or more default paths for
configuration files or other file arguments. A number of bug fixes and code
cleanup for various build configurations. Clean up of some error outputs and
extension of existing capability to new types or situations.
There is a possible minor breaking change in behavior of certain types which wrapped an integer, such as `std::atomic<int>` or `std::optional<int>` when used in a flag. The default behavior is now as a single argument value vs. summing all the arguments. The default summing behavior is now restricted to pure integral types, int64_t, int, uint32_t, etc. Use the new `sum` multi option policy to revert to the older behavior. The summing behavior on wrapper types was not originally intended.
There is a possible minor breaking change in behavior of certain types which
wrapped an integer, such as `std::atomic<int>` or `std::optional<int>` when used
in a flag. The default behavior is now as a single argument value vs. summing
all the arguments. The default summing behavior is now restricted to pure
integral types, int64_t, int, uint32_t, etc. Use the new `sum` multi option
policy to revert to the older behavior. The summing behavior on wrapper types
was not originally intended.
- Add `MultiOptionPolicy::Sum` and refactor the `add_flag` to fix a bug when using `std::optional<bool>` as type. [#709][]
- Add support for an empty vector result in TOML and as a default string. [#660][]
- Add `.validate_optional_arguments()` to support discriminating positional arguments from vector option arguments. [#668][]
- Add `CLI::FileOnDefaultPath` to check for files on a specified default path. [#698][]
- Change default value display in help messages from `=XXXX` to `[XXXXX]` to make it clearer. [#666][]
- Modify the Range Validator to support additional types and clean up the error output. [#690][]
- Bugfix: The trigger on parse modifier did not work on positional argument.s [#713][]
- Bugfix: The single header file generation was missing custom namespace generation. [#707][]
- Add `MultiOptionPolicy::Sum` and refactor the `add_flag` to fix a bug when
using `std::optional<bool>` as type. [#709][]
- Add support for an empty vector result in TOML and as a default string.
[#660][]
- Add `.validate_optional_arguments()` to support discriminating positional
arguments from vector option arguments. [#668][]
- Add `CLI::FileOnDefaultPath` to check for files on a specified default path.
[#698][]
- Change default value display in help messages from `=XXXX` to `[XXXXX]` to
make it clearer. [#666][]
- Modify the Range Validator to support additional types and clean up the error
output. [#690][]
- Bugfix: The trigger on parse modifier did not work on positional argument.s
[#713][]
- Bugfix: The single header file generation was missing custom namespace
generation. [#707][]
- Bugfix: Clean up File Error handling in the argument processing. [#678][]
- Bugfix: Fix a stack overflow error if nameless commands had fallthrough. [#665][]
- Bugfix: A subcommand callback could be executed multiple times if it was a member of an option group. [#666][]
- Bugfix: Fix an issue with vectors of multi argument types where partial argument sets did not result in an error. [#661][]
- Bugfix: Fix an issue with type the template matching on C++20 and add some CI builds for C++20. [#663][]
- Bugfix: Fix a stack overflow error if nameless commands had fallthrough.
[#665][]
- Bugfix: A subcommand callback could be executed multiple times if it was a
member of an option group. [#666][]
- Bugfix: Fix an issue with vectors of multi argument types where partial
argument sets did not result in an error. [#661][]
- Bugfix: Fix an issue with type the template matching on C++20 and add some CI
builds for C++20. [#663][]
- Bugfix: Fix typo in C++20 detection on MSVC. [#706][]
- Bugfix: An issue where the detection of RTTI being disabled on certain MSVC platforms did not disable the use of dynamic cast calls. [#666][]
- Bugfix: An issue where the detection of RTTI being disabled on certain MSVC
platforms did not disable the use of dynamic cast calls. [#666][]
- Bugfix: Resolve strict-overflow warning on some GCC compilers. [#666][]
- Backend: Add additional tests concerning the use of aliases for option groups in config files. [#666][]
- Build: Add support for testing in meson and cleanup symbolic link generation. [#701][], [#697][]
- Backend: Add additional tests concerning the use of aliases for option groups
in config files. [#666][]
- Build: Add support for testing in meson and cleanup symbolic link generation.
[#701][], [#697][]
- Build: Support building in WebAssembly. [#679][]
[#660]: https://github.com/CLIUtils/CLI11/pull/660
@ -49,15 +76,21 @@ The name restrictions for options and subcommands are now much looser, allowing
a wider variety of characters than before, even spaces can be used (use quotes
to include a space in most shells). The default configuration parser was
improved, allowing your configuration to sit in a larger file. And option
callbacks have a few new settings, allowing them to be run even if the option
is not passed, or every time the option is parsed.
callbacks have a few new settings, allowing them to be run even if the option is
not passed, or every time the option is parsed.
- Option/subcommand name restrictions have been relaxed. Most characters are now allowed. [#627][]
- The config parser can accept streams, specify a specific section, and inline comment characters are supported [#630][]
- `force_callback` & `trigger_on_parse` added, allowing a callback to always run on parse even if not present or every time the option is parsed [#631][]
- Bugfix(cmake): Only add `CONFIGURE_DEPENDS` if CLI11 is the main project [#633][]
- Bugfix(cmake): Ensure the cmake/pkg-config files install to a arch independent path [#635][]
- Bugfix: The single header file generation was missing the include guard. [#620][]
- Option/subcommand name restrictions have been relaxed. Most characters are now
allowed. [#627][]
- The config parser can accept streams, specify a specific section, and inline
comment characters are supported [#630][]
- `force_callback` & `trigger_on_parse` added, allowing a callback to always run
on parse even if not present or every time the option is parsed [#631][]
- Bugfix(cmake): Only add `CONFIGURE_DEPENDS` if CLI11 is the main project
[#633][]
- Bugfix(cmake): Ensure the cmake/pkg-config files install to a arch independent
path [#635][]
- Bugfix: The single header file generation was missing the include guard.
[#620][]
[#620]: https://github.com/CLIUtils/CLI11/pull/620
[#627]: https://github.com/CLIUtils/CLI11/pull/627
@ -70,7 +103,8 @@ is not passed, or every time the option is parsed.
- A collision with `min`/`max` macros on Windows has been fixed. [#642][]
- Tests pass with Boost again [#646][]
- Running the pre-commit hooks in development no longer requires docker for clang-format [#647][]
- Running the pre-commit hooks in development no longer requires docker for
clang-format [#647][]
[#642]: https://github.com/CLIUtils/CLI11/pull/642
[#646]: https://github.com/CLIUtils/CLI11/pull/646
@ -92,11 +126,11 @@ is not passed, or every time the option is parsed.
This version focuses on cleaning up deprecated functionality, and some minor
default changes. The config processing is TOML compliant now. Atomics and
complex numbers are directly supported, along with other container
improvements. A new version flag option has finally been added. Subcommands are
significantly improved with new features and bugfixes for corner cases. This
release contains a lot of backend cleanup, including a complete overhaul of the
testing system and single file generation system.
complex numbers are directly supported, along with other container improvements.
A new version flag option has finally been added. Subcommands are significantly
improved with new features and bugfixes for corner cases. This release contains
a lot of backend cleanup, including a complete overhaul of the testing system
and single file generation system.
- Built-in config format is TOML compliant now [#435][]
- Support multiline TOML [#528][]
@ -109,13 +143,15 @@ testing system and single file generation system.
- Support `->silent()` on subcommands. [#529][]
- Add alias section to help for subcommands [#545][]
- Allow quotes to specify a program name [#605][]
- Backend: redesigned MakeSingleFiles to have a higher level of manual control, to support future features. [#546][]
- Backend: redesigned MakeSingleFiles to have a higher level of manual control,
to support future features. [#546][]
- Backend: moved testing from GTest to Catch2 [#574][]
- Bugfix: avoid duplicated and missed calls to the final callback [#584][]
- Bugfix: support embedded newlines in more places [#592][]
- Bugfix: avoid listing helpall as a required flag [#530][]
- Bugfix: avoid a clash with WINDOWS define [#563][]
- Bugfix: the help flag didn't get processed when a config file was required [#606][]
- Bugfix: the help flag didn't get processed when a config file was required
[#606][]
- Bugfix: fix description of non-configurable subcommands in config [#604][]
- Build: support pkg-config [#523][]
@ -123,9 +159,10 @@ testing system and single file generation system.
>
> - Removed deprecated set commands, use validators instead. [#565][]
> - The final "defaulted" bool has been removed, use `->capture_default_str()`
> instead. Use `app.option_defaults()->always_capture_default()` to set this for
> all future options. [#597][]
> - Use `add_option` on a complex number instead of `add_complex`, which has been removed.
> instead. Use `app.option_defaults()->always_capture_default()` to set this
> for all future options. [#597][]
> - Use `add_option` on a complex number instead of `add_complex`, which has
> been removed.
[#423]: https://github.com/CLIUtils/CLI11/pull/423
[#435]: https://github.com/CLIUtils/CLI11/pull/435
@ -153,23 +190,30 @@ testing system and single file generation system.
## Version 1.9: Config files and cleanup
Config file handling was revamped to fix common issues, and now supports reading [TOML](https://github.com/toml-lang/toml).
Config file handling was revamped to fix common issues, and now supports reading
[TOML](https://github.com/toml-lang/toml).
Adding options is significantly more powerful with support for things like
`std::tuple` and `std::array`, including with transforms. Several new
configuration options were added to facilitate a wider variety of apps. GCC
4.7 is no longer supported.
configuration options were added to facilitate a wider variety of apps. GCC 4.7
is no longer supported.
- Config files refactored, supports TOML (may become default output in 2.0) [#362][]
- Added two template parameter form of `add_option`, allowing `std::optional` to be supported without a special import [#285][]
- Config files refactored, supports TOML (may become default output in 2.0)
[#362][]
- Added two template parameter form of `add_option`, allowing `std::optional` to
be supported without a special import [#285][]
- `string_view` now supported in reasonable places [#300][], [#285][]
- `immediate_callback`, `final_callback`, and `parse_complete_callback` added to support controlling the App callback order [#292][], [#313][]
- Multiple positional arguments maintain order if `positionals_at_end` is set. [#306][]
- Pair/tuple/array now supported, and validators indexed to specific components in the objects [#307][], [#310][]
- `immediate_callback`, `final_callback`, and `parse_complete_callback` added to
support controlling the App callback order [#292][], [#313][]
- Multiple positional arguments maintain order if `positionals_at_end` is set.
[#306][]
- Pair/tuple/array now supported, and validators indexed to specific components
in the objects [#307][], [#310][]
- Footer callbacks supported [#309][]
- Subcommands now support needs (including nameless subcommands) [#317][]
- More flexible type size, more useful `add_complex` [#325][], [#370][]
- Added new validators `CLI::NonNegativeNumber` and `CLI::PositiveNumber` [#342][]
- Added new validators `CLI::NonNegativeNumber` and `CLI::PositiveNumber`
[#342][]
- Transform now supports arrays [#349][]
- Option groups can be hidden [#356][]
- Add `CLI::deprecate_option` and `CLI::retire_option` functions [#358][]
@ -178,23 +222,29 @@ configuration options were added to facilitate a wider variety of apps. GCC
- Backend: File checking updates [#341][]
- Backend: Using pre-commit to format, checked in GitHub Actions [#336][]
- Backend: Clang-tidy checked again, CMake option now `CL11_CLANG_TIDY` [#390][]
- Backend: Warning cleanup, more checks from klocwork [#350][], Effective C++ [#354][], clang-tidy [#360][], CUDA NVCC [#365][], cross compile [#373][], sign conversion [#382][], and cpplint [#400][]
- Docs: CLI11 Tutorial now hosted in the same repository [#304][], [#318][], [#374][]
- Backend: Warning cleanup, more checks from klocwork [#350][], Effective C++
[#354][], clang-tidy [#360][], CUDA NVCC [#365][], cross compile [#373][],
sign conversion [#382][], and cpplint [#400][]
- Docs: CLI11 Tutorial now hosted in the same repository [#304][], [#318][],
[#374][]
- Bugfix: Fixed undefined behavior in `checked_multiply` [#290][]
- Bugfix: `->check()` was adding the name to the wrong validator [#320][]
- Bugfix: Resetting config option works properly [#301][]
- Bugfix: Hidden flags were showing up in error printout [#333][]
- Bugfix: Enum conversion no longer broken if stream operator added [#348][]
- Build: The meson build system supported [#299][]
- Build: GCC 4.7 is no longer supported, due mostly to GoogleTest. GCC 4.8+ is now required. [#160][]
- Build: GCC 4.7 is no longer supported, due mostly to GoogleTest. GCC 4.8+ is
now required. [#160][]
- Build: Restructured significant portions of CMake build system [#394][]
> ### Converting from CLI11 1.8
>
> - Some deprecated methods dropped
> - `add_set*` should be replaced with `->check`/`->transform` and `CLI::IsMember` since 1.8
> - `add_set*` should be replaced with `->check`/`->transform` and
> `CLI::IsMember` since 1.8
> - `get_defaultval` was replaced by `get_default_str` in 1.8
> - The true/false 4th argument to `add_option` is expected to be removed in 2.0, use `->capture_default_str()` since 1.8
> - The true/false 4th argument to `add_option` is expected to be removed in
> 2.0, use `->capture_default_str()` since 1.8
[#160]: https://github.com/CLIUtils/CLI11/pull/160
[#285]: https://github.com/CLIUtils/CLI11/pull/285
@ -258,41 +308,73 @@ This is a patch version that backports fixes from the development of 2.0.
## Version 1.8: Transformers, default strings, and flags
Set handling has been completely replaced by a new backend that works as a Validator or Transformer. This provides a single interface instead of the 16 different functions in App. It also allows ordered collections to be used, custom functions for filtering, and better help and error messages. You can also use a collection of pairs (like `std::map`) to transform the match into an output. Also new are inverted flags, which can cancel or reduce the count of flags, and can also support general flag types. A new `add_option_fn` lets you more easily program CLI11 options with the types you choose. Vector options now support a custom separator. Apps can now be composed with unnamed subcommand support. The final bool "defaults" flag when creating options has been replaced by `->capture_default_str()` (ending an old limitation in construction made this possible); the old method is still available but may be removed in future versions.
Set handling has been completely replaced by a new backend that works as a
Validator or Transformer. This provides a single interface instead of the 16
different functions in App. It also allows ordered collections to be used,
custom functions for filtering, and better help and error messages. You can also
use a collection of pairs (like `std::map`) to transform the match into an
output. Also new are inverted flags, which can cancel or reduce the count of
flags, and can also support general flag types. A new `add_option_fn` lets you
more easily program CLI11 options with the types you choose. Vector options now
support a custom separator. Apps can now be composed with unnamed subcommand
support. The final bool "defaults" flag when creating options has been replaced
by `->capture_default_str()` (ending an old limitation in construction made this
possible); the old method is still available but may be removed in future
versions.
- Replaced default help capture: `.add_option("name", value, "", True)` becomes `.add_option("name", value)->capture_default_str()` [#242][]
- Replaced default help capture: `.add_option("name", value, "", True)` becomes
`.add_option("name", value)->capture_default_str()` [#242][]
- Added `.always_capture_default()` [#242][]
- New `CLI::IsMember` validator replaces set validation [#222][]
- `IsMember` also supports container of pairs, transform allows modification of result [#228][]
- Added new Transformers, `CLI::AsNumberWithUnit` and `CLI::AsSizeValue` [#253][]
- Much more powerful flags with different values [#211][], general types [#235][]
- `IsMember` also supports container of pairs, transform allows modification of
result [#228][]
- Added new Transformers, `CLI::AsNumberWithUnit` and `CLI::AsSizeValue`
[#253][]
- Much more powerful flags with different values [#211][], general types
[#235][]
- `add_option` now supports bool due to unified bool handling [#211][]
- Support for composable unnamed subcommands [#216][]
- Reparsing is better supported with `.remaining_for_passthrough()` [#265][]
- Custom vector separator using `->delimiter(char)` [#209][], [#221][], [#240][]
- Validators added for IP4 addresses and positive numbers [#210][] and numbers [#262][]
- Minimum required Boost for optional Optionals has been corrected to 1.61 [#226][]
- Positionals can stop options from being parsed with `app.positionals_at_end()` [#223][]
- Validators added for IP4 addresses and positive numbers [#210][] and numbers
[#262][]
- Minimum required Boost for optional Optionals has been corrected to 1.61
[#226][]
- Positionals can stop options from being parsed with `app.positionals_at_end()`
[#223][]
- Added `validate_positionals` [#262][]
- Positional parsing is much more powerful [#251][], duplicates supported [#247][]
- Validators can be negated with `!` [#230][], and now handle tname functions [#228][]
- Positional parsing is much more powerful [#251][], duplicates supported
[#247][]
- Validators can be negated with `!` [#230][], and now handle tname functions
[#228][]
- Better enum support and streaming helper [#233][] and [#228][]
- Cleanup for shadow warnings [#232][]
- Better alignment on multiline descriptions [#269][]
- Better support for aarch64 [#266][]
- Respect `BUILD_TESTING` only if CLI11 is the main project; otherwise, `CLI11_TESTING` must be used [#277][]
- Drop auto-detection of experimental optional and boost::optional; must be enabled explicitly (too fragile) [#277][] [#279][]
- Respect `BUILD_TESTING` only if CLI11 is the main project; otherwise,
`CLI11_TESTING` must be used [#277][]
- Drop auto-detection of experimental optional and boost::optional; must be
enabled explicitly (too fragile) [#277][] [#279][]
> ### Converting from CLI11 1.7
>
> - `.add_option(..., true)` should be replaced by `.add_option(...)->capture_default_str()` or `app.option_defaults()->always_capture_default()` can be used
> - `app.add_set("--name", value, {"choice1", "choice2"})` should become `app.add_option("--name", value)->check(CLI::IsMember({"choice1", "choice2"}))`
> - The `_ignore_case` version of this can be replaced by adding `CLI::ignore_case` to the argument list in `IsMember`
> - The `_ignore_underscore` version of this can be replaced by adding `CLI::ignore_underscore` to the argument list in `IsMember`
> - The `_ignore_case_underscore` version of this can be replaced by adding both functions listed above to the argument list in `IsMember`
> - If you want an exact match to the original choice after one of the modifier functions matches, use `->transform` instead of `->check`
> - The `_mutable` versions of this can be replaced by passing a pointer or shared pointer into `IsMember`
> - An error with sets now produces a `ValidationError` instead of a `ConversionError`
> - `.add_option(..., true)` should be replaced by
> `.add_option(...)->capture_default_str()` or
> `app.option_defaults()->always_capture_default()` can be used
> - `app.add_set("--name", value, {"choice1", "choice2"})` should become
> `app.add_option("--name", value)->check(CLI::IsMember({"choice1", "choice2"}))`
> - The `_ignore_case` version of this can be replaced by adding
> `CLI::ignore_case` to the argument list in `IsMember`
> - The `_ignore_underscore` version of this can be replaced by adding
> `CLI::ignore_underscore` to the argument list in `IsMember`
> - The `_ignore_case_underscore` version of this can be replaced by adding both
> functions listed above to the argument list in `IsMember`
> - If you want an exact match to the original choice after one of the modifier
> functions matches, use `->transform` instead of `->check`
> - The `_mutable` versions of this can be replaced by passing a pointer or
> shared pointer into `IsMember`
> - An error with sets now produces a `ValidationError` instead of a
> `ConversionError`
[#209]: https://github.com/CLIUtils/CLI11/pull/209
[#210]: https://github.com/CLIUtils/CLI11/pull/210
@ -321,29 +403,50 @@ Set handling has been completely replaced by a new backend that works as a Valid
## Version 1.7: Parse breakup
The parsing procedure now maps much more sensibly to complex, nested subcommand structures. Each phase of the parsing happens on all subcommands before moving on with the next phase of the parse. This allows several features, like required environment variables, to work properly even through subcommand boundaries.
Passing the same subcommand multiple times is better supported. Several new features were added as well, including Windows style option support, parsing strings directly, and ignoring underscores in names. Adding a set that you plan to change later must now be done with `add_mutable_set`.
The parsing procedure now maps much more sensibly to complex, nested subcommand
structures. Each phase of the parsing happens on all subcommands before moving
on with the next phase of the parse. This allows several features, like required
environment variables, to work properly even through subcommand boundaries.
Passing the same subcommand multiple times is better supported. Several new
features were added as well, including Windows style option support, parsing
strings directly, and ignoring underscores in names. Adding a set that you plan
to change later must now be done with `add_mutable_set`.
- Support Windows style options with `->allow_windows_style_options`. [#187][] On by default on Windows. [#190][]
- Added `parse(string)` to split up and parse a command-line style string directly. [#186][]
- Added `ignore_underscore` and related functions, to ignore underscores when matching names. [#185][]
- Support Windows style options with `->allow_windows_style_options`. [#187][]
On by default on Windows. [#190][]
- Added `parse(string)` to split up and parse a command-line style string
directly. [#186][]
- Added `ignore_underscore` and related functions, to ignore underscores when
matching names. [#185][]
- The default INI Config will now add quotes to strings with spaces [#195][]
- The default message now will mention the help-all flag also if present [#197][]
- The default message now will mention the help-all flag also if present
[#197][]
- Added `->description` to set Option descriptions [#199][]
- Mutating sets (introduced in Version 1.6) now have a clear add method, `add_mutable_set*`, since the set reference should not expire [#200][]
- Subcommands now track how many times they were parsed in a parsing process. `count()` with no arguments will return the number of times a subcommand was encountered. [#178][]
- Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and `requirements`; all subcommands complete a phase before moving on. [#178][]
- Calling parse multiple times is now officially supported without `clear` (automatic). [#178][]
- Dropped the mostly undocumented `short_circuit` property, as help flag parsing is a bit more complex, and the default callback behavior of options now works properly. [#179][]
- Mutating sets (introduced in Version 1.6) now have a clear add method,
`add_mutable_set*`, since the set reference should not expire [#200][]
- Subcommands now track how many times they were parsed in a parsing process.
`count()` with no arguments will return the number of times a subcommand was
encountered. [#178][]
- Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and
`requirements`; all subcommands complete a phase before moving on. [#178][]
- Calling parse multiple times is now officially supported without `clear`
(automatic). [#178][]
- Dropped the mostly undocumented `short_circuit` property, as help flag parsing
is a bit more complex, and the default callback behavior of options now works
properly. [#179][]
- Use the standard `BUILD_TESTING` over `CLI11_TESTING` if defined [#183][]
- Cleanup warnings [#191][]
- Remove deprecated names: `set_footer`, `set_name`, `set_callback`, and `set_type_name`. Use without the `set_` instead. [#192][]
- Remove deprecated names: `set_footer`, `set_name`, `set_callback`, and
`set_type_name`. Use without the `set_` instead. [#192][]
> ### Converting from CLI11 1.6
>
> - `->short_circuit()` is no longer needed, just remove it if you were using it - raising an exception will happen in the proper place now without it.
> - `->add_set*` becomes `->add_mutable_set*` if you were using the editable set feature
> - `footer`, `name`, `callback`, and `type_name` must be used instead of the `set_*` versions (deprecated previously).
> - `->short_circuit()` is no longer needed, just remove it if you were using
> it - raising an exception will happen in the proper place now without it.
> - `->add_set*` becomes `->add_mutable_set*` if you were using the editable set
> feature
> - `footer`, `name`, `callback`, and `type_name` must be used instead of the
> `set_*` versions (deprecated previously).
[#178]: https://github.com/CLIUtils/CLI11/pull/178
[#183]: https://github.com/CLIUtils/CLI11/pull/183
@ -360,7 +463,8 @@ Passing the same subcommand multiple times is better supported. Several new feat
### Version 1.7.1: Quick patch
This version provides a quick patch for a (correct) warning from GCC 8 for the windows options code.
This version provides a quick patch for a (correct) warning from GCC 8 for the
windows options code.
- Fix for Windows style option parsing [#201][]
- Improve `add_subcommand` when throwing an exception [#204][]
@ -372,7 +476,9 @@ This version provides a quick patch for a (correct) warning from GCC 8 for the w
## Version 1.6: Formatting help
Added a new formatting system [#109][]. You can now set the formatter on Apps. This has also simplified the internals of Apps and Options a bit by separating most formatting code.
Added a new formatting system [#109][]. You can now set the formatter on Apps.
This has also simplified the internals of Apps and Options a bit by separating
most formatting code.
- Added `CLI::Formatter` and `formatter` slot for apps, inherited.
- `FormatterBase` is the minimum required.
@ -387,7 +493,8 @@ Changes to the help system (most normal users will not notice this):
- Removed `help_*` functions.
- Protected function `_has_help_positional` removed.
- `format_help` can now be chained.
- Added getters for the missing parts of options (help no longer uses any private parts).
- Added getters for the missing parts of options (help no longer uses any
private parts).
- Help flags now use new `short_circuit` property to simplify parsing. [#121][]
New for Config file reading and writing [#121][]:
@ -400,7 +507,8 @@ New for Config file reading and writing [#121][]:
- Added `ConfigItem`.
- Added an example of a custom config format using [nlohmann/json][]. [#138][]
Validators are now much more powerful [#118][], all built in validators upgraded to the new form:
Validators are now much more powerful [#118][], all built in validators upgraded
to the new form:
- A subclass of `CLI::Validator` is now also accepted.
- They now can set the type name to things like `PATH` and `INT in [1-4]`.
@ -410,24 +518,32 @@ Validators are now much more powerful [#118][], all built in validators upgraded
Other changes:
- Fixing `parse(args)`'s `args` setting and ordering after parse. [#141][]
- Replaced `set_custom_option` with `type_name` and `type_size` instead of `set_custom_option`. Methods return `this`. [#136][]
- Dropped `set_` on Option's `type_name`, `default_str`, and `default_val`. [#136][]
- Removed `set_` from App's `failure_message`, `footer`, `callback`, and `name`. [#136][]
- Replaced `set_custom_option` with `type_name` and `type_size` instead of
`set_custom_option`. Methods return `this`. [#136][]
- Dropped `set_` on Option's `type_name`, `default_str`, and `default_val`.
[#136][]
- Removed `set_` from App's `failure_message`, `footer`, `callback`, and `name`.
[#136][]
- Fixed support `N<-1` for `type_size`. [#140][]
- Added `->each()` to make adding custom callbacks easier. [#126][]
- Allow empty options `add_option("-n",{})` to be edited later with `each` [#142][]
- Added filter argument to `get_subcommands`, `get_options`; use empty filter `{}` to avoid filtering.
- Allow empty options `add_option("-n",{})` to be edited later with `each`
[#142][]
- Added filter argument to `get_subcommands`, `get_options`; use empty filter
`{}` to avoid filtering.
- Added `get_groups()` to get groups.
- Better support for manual options with `get_option`, `set_results`, and `empty`. [#119][]
- Better support for manual options with `get_option`, `set_results`, and
`empty`. [#119][]
- `lname` and `sname` have getters, added `const get_parent`. [#120][]
- Using `add_set` will now capture L-values for sets, allowing further modification. [#113][]
- Using `add_set` will now capture L-values for sets, allowing further
modification. [#113][]
- Dropped duplicate way to run `get_type_name` (`get_typeval`).
- Removed `requires` in favor of `needs` (deprecated in last version). [#112][]
- Const added to argv. [#126][]
Backend and testing changes:
- Internally, `type_name` is now a lambda function; for sets, this reads the set live. [#116][]
- Internally, `type_name` is now a lambda function; for sets, this reads the set
live. [#116][]
- Cleaner tests without `app.reset()` (and `reset` is now `clear`). [#141][]
- Better CMake policy handling. [#110][]
- Includes are properly sorted. [#120][]
@ -453,12 +569,14 @@ Backend and testing changes:
### Version 1.6.1: Platform fixes
This version provides a few fixes for special cases, such as mixing with `Windows.h` and better defaults
for systems like Hunter. The one new feature is the ability to produce "branded" single file output for
providing custom namespaces or custom macro names.
This version provides a few fixes for special cases, such as mixing with
`Windows.h` and better defaults for systems like Hunter. The one new feature is
the ability to produce "branded" single file output for providing custom
namespaces or custom macro names.
- Added fix and test for including Windows.h [#145][]
- No longer build single file by default if main project, supports systems stuck on Python 2.6 [#149][], [#151][]
- No longer build single file by default if main project, supports systems stuck
on Python 2.6 [#149][], [#151][]
- Branding support for single file output [#150][]
[#145]: https://github.com/CLIUtils/CLI11/pull/145
@ -468,18 +586,22 @@ providing custom namespaces or custom macro names.
### Version 1.6.2: Help-all
This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. Several smaller fixes.
This version fixes some formatting bugs with help-all. It also adds fixes for
several warnings, including an experimental optional error on Clang 7. Several
smaller fixes.
- Fixed help-all formatting [#163][]
- Printing help-all on nested command now fixed (App)
- Missing space after help-all restored (Default formatter)
- More detail printed on help all (Default formatter)
- Help-all subcommands get indented with inner blank lines removed (Default formatter)
- Help-all subcommands get indented with inner blank lines removed (Default
formatter)
- `detail::find_and_replace` added to utilities
- Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156][]
- Fixed warning about local variable hiding class member with MSVC [#157][]
- Fixed compile error with default settings on Clang 7 and libc++ [#158][]
- Fixed special case of `--help` on subcommands (general fix planned for 1.7) [#168][]
- Fixed special case of `--help` on subcommands (general fix planned for 1.7)
[#168][]
- Removing an option with links [#179][]
[#156]: https://github.com/CLIUtils/CLI11/issues/156
@ -491,15 +613,24 @@ This version fixes some formatting bugs with help-all. It also adds fixes for se
## Version 1.5: Optionals
This version introduced support for optionals, along with clarification and examples of custom conversion overloads. Enums now have been dropped from the automatic conversion system, allowing explicit protection for out-of-range ints (or a completely custom conversion). This version has some internal cleanup and improved support for the newest compilers. Several bugs were fixed, as well.
This version introduced support for optionals, along with clarification and
examples of custom conversion overloads. Enums now have been dropped from the
automatic conversion system, allowing explicit protection for out-of-range ints
(or a completely custom conversion). This version has some internal cleanup and
improved support for the newest compilers. Several bugs were fixed, as well.
Note: This is the final release with `requires`, please switch to `needs`.
- Fix unlimited short options eating two values before checking for positionals when no space present [#90][]
- Symmetric exclude text when excluding options, exclude can be called multiple times [#64][]
- Support for `std::optional`, `std::experimental::optional`, and `boost::optional` added if `__has_include` is supported [#95][]
- All macros/CMake variables now start with `CLI11_` instead of just `CLI_` [#95][]
- The internal stream was not being cleared before use in some cases. Fixed. [#95][]
- Fix unlimited short options eating two values before checking for positionals
when no space present [#90][]
- Symmetric exclude text when excluding options, exclude can be called multiple
times [#64][]
- Support for `std::optional`, `std::experimental::optional`, and
`boost::optional` added if `__has_include` is supported [#95][]
- All macros/CMake variables now start with `CLI11_` instead of just `CLI_`
[#95][]
- The internal stream was not being cleared before use in some cases. Fixed.
[#95][]
- Using an enum now requires explicit conversion overload [#97][]
- The separator `--` now is removed when it ends unlimited arguments [#100][]
@ -510,8 +641,10 @@ Other, non-user facing changes:
- C++17 is now tested on supported platforms [#95][]
- Informational printout now added to CTest [#95][]
- Better single file generation [#95][]
- Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next version of GTest)
- Types now have a specific size, separate from the expected number - cleaner and more powerful internally [#92][]
- Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next
version of GTest)
- Types now have a specific size, separate from the expected number - cleaner
and more powerful internally [#92][]
- Examples now run as part of testing [#99][]
[#64]: https://github.com/CLIUtils/CLI11/issues/64
@ -524,11 +657,15 @@ Other, non-user facing changes:
### Version 1.5.1: Access
This patch release adds better access to the App programmatically, to assist with writing custom converters to other formats. It also improves the help output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way unlimited options and positionals interact.
This patch release adds better access to the App programmatically, to assist
with writing custom converters to other formats. It also improves the help
output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way
unlimited options and positionals interact.
- Make mixing unlimited positionals and options more intuitive [#102][]
- Add missing getters `get_options` and `get_description` to App [#105][]
- The app name now can be set, and will override the auto name if present [#105][]
- The app name now can be set, and will override the auto name if present
[#105][]
- Add `(REQUIRED)` for required options [#104][]
- Print simple name for Needs/Excludes [#104][]
- Use Needs instead of Requires in help print [#104][]
@ -541,21 +678,30 @@ This patch release adds better access to the App programmatically, to assist wit
### Version 1.5.2: LICENSE in single header mode
This is a quick patch release that makes LICENSE part of the single header file, making it easier to include. Minor cleanup from codacy. No significant code changes from 1.5.1.
This is a quick patch release that makes LICENSE part of the single header file,
making it easier to include. Minor cleanup from codacy. No significant code
changes from 1.5.1.
### Version 1.5.3: Compiler compatibility
This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported.
This version fixes older AppleClang compilers by removing the optimization for
casting. The minimum version of Boost Optional supported has been clarified to
be 1.58. CUDA 7.0 NVCC is now supported.
### Version 1.5.4: Optionals
This version fixes the optional search in the single file version; some macros were not yet defined when it did the search. You can define the `CLI11_*_OPTIONAL` macros to 0 if needed to eliminate the search.
This version fixes the optional search in the single file version; some macros
were not yet defined when it did the search. You can define the
`CLI11_*_OPTIONAL` macros to 0 if needed to eliminate the search.
## Version 1.4: More feedback
This version adds lots of smaller fixes and additions after the refactor in version 1.3. More ways to download and use CLI11 in CMake have been added. INI files have improved support.
This version adds lots of smaller fixes and additions after the refactor in
version 1.3. More ways to download and use CLI11 in CMake have been added. INI
files have improved support.
- Lexical cast is now more strict than before [#68][] and fails on overflow [#84][]
- Lexical cast is now more strict than before [#68][] and fails on overflow
[#84][]
- Added `get_parent()` to access the parent from a subcommand
- Added `ExistingPath` validator [#73][]
- `app.allow_ini_extras()` added to allow extras in INI files [#70][]
@ -564,7 +710,8 @@ This version adds lots of smaller fixes and additions after the refactor in vers
- Double printing of error message fixed [#77][]
- Renamed `requires` to `needs` to avoid C++20 keyword [#75][], [#82][]
- MakeSingleHeader now works if outside of git [#78][]
- Adding install support for CMake [#79][], improved support for `find_package` [#83][], [#84][]
- Adding install support for CMake [#79][], improved support for `find_package`
[#83][], [#84][]
- Added support for Conan.io [#83][]
[#70]: https://github.com/CLIUtils/CLI11/issues/70
@ -581,73 +728,128 @@ This version adds lots of smaller fixes and additions after the refactor in vers
## Version 1.3: Refactor
This version focused on refactoring several key systems to ensure correct behavior in the interaction of different settings. Most caveats about
features only working on the main App have been addressed, and extra arguments have been reworked. Inheritance
of defaults makes configuring CLI11 much easier without having to subclass. Policies add new ways to handle multiple arguments to match your
favorite CLI programs. Error messages and help messages are better and more flexible. Several bugs and odd behaviors in the parser have been fixed.
This version focused on refactoring several key systems to ensure correct
behavior in the interaction of different settings. Most caveats about features
only working on the main App have been addressed, and extra arguments have been
reworked. Inheritance of defaults makes configuring CLI11 much easier without
having to subclass. Policies add new ways to handle multiple arguments to match
your favorite CLI programs. Error messages and help messages are better and more
flexible. Several bugs and odd behaviors in the parser have been fixed.
- Added a version macro, `CLI11_VERSION`, along with `*_MAJOR`, `*_MINOR`, and `*_PATCH`, for programmatic access to the version.
- Reworked the way defaults are set and inherited; explicit control given to user with `->option_defaults()` [#48](https://github.com/CLIUtils/CLI11/pull/48)
- Hidden options now are based on an empty group name, instead of special "hidden" keyword [#48](https://github.com/CLIUtils/CLI11/pull/48)
- `parse` no longer returns (so `CLI11_PARSE` is always usable) [#37](https://github.com/CLIUtils/CLI11/pull/37)
- Added `remaining()` and `remaining_size()` [#37](https://github.com/CLIUtils/CLI11/pull/37)
- `allow_extras` and `prefix_command` are now valid on subcommands [#37](https://github.com/CLIUtils/CLI11/pull/37)
- Added `take_last` to only take last value passed [#40](https://github.com/CLIUtils/CLI11/pull/40)
- Added `multi_option_policy` and shortcuts to provide more control than just a take last policy [#59](https://github.com/CLIUtils/CLI11/pull/59)
- More detailed error messages in a few cases [#41](https://github.com/CLIUtils/CLI11/pull/41)
- Added a version macro, `CLI11_VERSION`, along with `*_MAJOR`, `*_MINOR`, and
`*_PATCH`, for programmatic access to the version.
- Reworked the way defaults are set and inherited; explicit control given to
user with `->option_defaults()`
[#48](https://github.com/CLIUtils/CLI11/pull/48)
- Hidden options now are based on an empty group name, instead of special
"hidden" keyword [#48](https://github.com/CLIUtils/CLI11/pull/48)
- `parse` no longer returns (so `CLI11_PARSE` is always usable)
[#37](https://github.com/CLIUtils/CLI11/pull/37)
- Added `remaining()` and `remaining_size()`
[#37](https://github.com/CLIUtils/CLI11/pull/37)
- `allow_extras` and `prefix_command` are now valid on subcommands
[#37](https://github.com/CLIUtils/CLI11/pull/37)
- Added `take_last` to only take last value passed
[#40](https://github.com/CLIUtils/CLI11/pull/40)
- Added `multi_option_policy` and shortcuts to provide more control than just a
take last policy [#59](https://github.com/CLIUtils/CLI11/pull/59)
- More detailed error messages in a few cases
[#41](https://github.com/CLIUtils/CLI11/pull/41)
- Footers can be added to help [#42](https://github.com/CLIUtils/CLI11/pull/42)
- Help flags are easier to customize [#43](https://github.com/CLIUtils/CLI11/pull/43)
- Help flags are easier to customize
[#43](https://github.com/CLIUtils/CLI11/pull/43)
- Subcommand now support groups [#46](https://github.com/CLIUtils/CLI11/pull/46)
- `CLI::RuntimeError` added, for easy exit with error codes [#45](https://github.com/CLIUtils/CLI11/pull/45)
- The clang-format script is now no longer "hidden" [#48](https://github.com/CLIUtils/CLI11/pull/48)
- The order is now preserved for subcommands (list and callbacks) [#49](https://github.com/CLIUtils/CLI11/pull/49)
- Tests now run individually, utilizing CMake 3.10 additions if possible [#50](https://github.com/CLIUtils/CLI11/pull/50)
- Failure messages are now customizable, with a shorter default [#52](https://github.com/CLIUtils/CLI11/pull/52)
- Some improvements to error codes [#53](https://github.com/CLIUtils/CLI11/pull/53)
- `require_subcommand` now offers a two-argument form and negative values on the one-argument form are more useful [#51](https://github.com/CLIUtils/CLI11/pull/51)
- Subcommands no longer match after the max required number is obtained [#51](https://github.com/CLIUtils/CLI11/pull/51)
- Unlimited options no longer prioritize over remaining/unlimited positionals [#51](https://github.com/CLIUtils/CLI11/pull/51)
- Added `->transform` which modifies the string parsed [#54](https://github.com/CLIUtils/CLI11/pull/54)
- Changed of API in validators to `void(std::string &)` (const for users), throwing providing nicer errors [#54](https://github.com/CLIUtils/CLI11/pull/54)
- Added `CLI::ArgumentMismatch` [#56](https://github.com/CLIUtils/CLI11/pull/56) and fixed missing failure if one arg expected [#55](https://github.com/CLIUtils/CLI11/issues/55)
- Support for minimum unlimited expected arguments [#56](https://github.com/CLIUtils/CLI11/pull/56)
- Single internal arg parse function [#56](https://github.com/CLIUtils/CLI11/pull/56)
- Allow options to be disabled from INI file, rename `add_config` to `set_config` [#60](https://github.com/CLIUtils/CLI11/pull/60)
- `CLI::RuntimeError` added, for easy exit with error codes
[#45](https://github.com/CLIUtils/CLI11/pull/45)
- The clang-format script is now no longer "hidden"
[#48](https://github.com/CLIUtils/CLI11/pull/48)
- The order is now preserved for subcommands (list and callbacks)
[#49](https://github.com/CLIUtils/CLI11/pull/49)
- Tests now run individually, utilizing CMake 3.10 additions if possible
[#50](https://github.com/CLIUtils/CLI11/pull/50)
- Failure messages are now customizable, with a shorter default
[#52](https://github.com/CLIUtils/CLI11/pull/52)
- Some improvements to error codes
[#53](https://github.com/CLIUtils/CLI11/pull/53)
- `require_subcommand` now offers a two-argument form and negative values on the
one-argument form are more useful
[#51](https://github.com/CLIUtils/CLI11/pull/51)
- Subcommands no longer match after the max required number is obtained
[#51](https://github.com/CLIUtils/CLI11/pull/51)
- Unlimited options no longer prioritize over remaining/unlimited positionals
[#51](https://github.com/CLIUtils/CLI11/pull/51)
- Added `->transform` which modifies the string parsed
[#54](https://github.com/CLIUtils/CLI11/pull/54)
- Changed of API in validators to `void(std::string &)` (const for users),
throwing providing nicer errors
[#54](https://github.com/CLIUtils/CLI11/pull/54)
- Added `CLI::ArgumentMismatch` [#56](https://github.com/CLIUtils/CLI11/pull/56)
and fixed missing failure if one arg expected
[#55](https://github.com/CLIUtils/CLI11/issues/55)
- Support for minimum unlimited expected arguments
[#56](https://github.com/CLIUtils/CLI11/pull/56)
- Single internal arg parse function
[#56](https://github.com/CLIUtils/CLI11/pull/56)
- Allow options to be disabled from INI file, rename `add_config` to
`set_config` [#60](https://github.com/CLIUtils/CLI11/pull/60)
> ### Converting from CLI11 1.2
>
> - `app.parse` no longer returns a vector. Instead, use `app.remaining(true)`.
> - `"hidden"` is no longer a special group name, instead use `""`
> - Validators API has changed to return an error string; use `.empty()` to get the old bool back
> - Use `.set_help_flag` instead of accessing the help pointer directly (discouraged, but not removed yet)
> - Validators API has changed to return an error string; use `.empty()` to get
> the old bool back
> - Use `.set_help_flag` instead of accessing the help pointer directly
> (discouraged, but not removed yet)
> - `add_config` has been renamed to `set_config`
> - Errors thrown in some cases are slightly more specific
## Version 1.2: Stability
This release focuses on making CLI11 behave properly in corner cases, and with config files on the command line. This includes fixes for a variety of reported issues. A few features were added to make life easier, as well; such as a new flag callback and a macro for the parse command.
This release focuses on making CLI11 behave properly in corner cases, and with
config files on the command line. This includes fixes for a variety of reported
issues. A few features were added to make life easier, as well; such as a new
flag callback and a macro for the parse command.
- Added functional form of flag [#33](https://github.com/CLIUtils/CLI11/pull/33), automatic on C++14
- Fixed Config file search if passed on command line [#30](https://github.com/CLIUtils/CLI11/issues/30)
- Added `CLI11_PARSE(app, argc, argv)` macro for simple parse commands (does not support returning arg)
- The name string can now contain spaces around commas [#29](https://github.com/CLIUtils/CLI11/pull/29)
- `set_default_str` now only sets string, and `set_default_val` will evaluate the default string given [#26](https://github.com/CLIUtils/CLI11/issues/26)
- Required positionals now take priority over subcommands [#23](https://github.com/CLIUtils/CLI11/issues/23)
- Added functional form of flag
[#33](https://github.com/CLIUtils/CLI11/pull/33), automatic on C++14
- Fixed Config file search if passed on command line
[#30](https://github.com/CLIUtils/CLI11/issues/30)
- Added `CLI11_PARSE(app, argc, argv)` macro for simple parse commands (does not
support returning arg)
- The name string can now contain spaces around commas
[#29](https://github.com/CLIUtils/CLI11/pull/29)
- `set_default_str` now only sets string, and `set_default_val` will evaluate
the default string given [#26](https://github.com/CLIUtils/CLI11/issues/26)
- Required positionals now take priority over subcommands
[#23](https://github.com/CLIUtils/CLI11/issues/23)
- Extra requirements enforced by Travis
## Version 1.1: Feedback
This release incorporates feedback from the release announcement. The examples are slowly being expanded, some corner cases improved, and some new functionality for tricky parsing situations.
This release incorporates feedback from the release announcement. The examples
are slowly being expanded, some corner cases improved, and some new
functionality for tricky parsing situations.
- Added simple support for enumerations, allow non-printable objects [#12](https://github.com/CLIUtils/CLI11/issues/12)
- Added `app.parse_order()` with original parse order ([#13](https://github.com/CLIUtils/CLI11/issues/13), [#16](https://github.com/CLIUtils/CLI11/pull/16))
- Added `prefix_command()`, which is like `allow_extras` but instantly stops and returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8), [#17](https://github.com/CLIUtils/CLI11/pull/17))
- Removed Windows warning ([#10](https://github.com/CLIUtils/CLI11/issues/10), [#20](https://github.com/CLIUtils/CLI11/pull/20))
- Some improvements to CMake, detect Python and no dependencies on Python 2 (like Python 3) ([#18](https://github.com/CLIUtils/CLI11/issues/18), [#21](https://github.com/CLIUtils/CLI11/pull/21))
- Added simple support for enumerations, allow non-printable objects
[#12](https://github.com/CLIUtils/CLI11/issues/12)
- Added `app.parse_order()` with original parse order
([#13](https://github.com/CLIUtils/CLI11/issues/13),
[#16](https://github.com/CLIUtils/CLI11/pull/16))
- Added `prefix_command()`, which is like `allow_extras` but instantly stops and
returns. ([#8](https://github.com/CLIUtils/CLI11/issues/8),
[#17](https://github.com/CLIUtils/CLI11/pull/17))
- Removed Windows warning ([#10](https://github.com/CLIUtils/CLI11/issues/10),
[#20](https://github.com/CLIUtils/CLI11/pull/20))
- Some improvements to CMake, detect Python and no dependencies on Python 2
(like Python 3) ([#18](https://github.com/CLIUtils/CLI11/issues/18),
[#21](https://github.com/CLIUtils/CLI11/pull/21))
## Version 1.0: Official release
This is the first stable release for CLI11. Future releases will try to remain backward compatible and will follow semantic versioning if possible. There were a few small changes since version 0.9:
This is the first stable release for CLI11. Future releases will try to remain
backward compatible and will follow semantic versioning if possible. There were
a few small changes since version 0.9:
- Cleanup using `clang-tidy` and `clang-format`
- Small improvements to Timers, easier to subclass Error
@ -655,13 +857,16 @@ This is the first stable release for CLI11. Future releases will try to remain b
## Version 0.9: Polish
This release focused on cleaning up the most exotic compiler warnings, fixing a few oddities of the config parser, and added a more natural method to check subcommands.
This release focused on cleaning up the most exotic compiler warnings, fixing a
few oddities of the config parser, and added a more natural method to check
subcommands.
- Better CMake named target (CLI11)
- More warnings added, fixed
- Ini output now includes `=false` when `default_also` is true
- Ini no longer lists the help pointer
- Added test for inclusion in multiple files and linking, fixed issues (rarely needed for CLI, but nice for tools)
- Added test for inclusion in multiple files and linking, fixed issues (rarely
needed for CLI, but nice for tools)
- Support for complex numbers
- Subcommands now test true/false directly or with `->parsed()`, cleaner parse
@ -674,20 +879,25 @@ This release moved the repository to the CLIUtils main organization.
## Version 0.7: Code coverage 100%
Lots of small bugs fixed when adding code coverage, better in edge cases. Much more powerful ini support.
Lots of small bugs fixed when adding code coverage, better in edge cases. Much
more powerful ini support.
- Allow comments in ini files (lines starting with `;`)
- Ini files support flags, vectors, subcommands
- Added CodeCov code coverage reports
- Lots of small bugfixes related to adding tests to increase coverage to 100%
- Error handling now uses scoped enum in errors
- Reparsing rules changed a little to accommodate Ini files. Callbacks are now called when parsing INI, and reset any time results are added.
- Adding extra utilities in full version only, `Timer` (not needed for parsing, but useful for general CLI applications).
- Reparsing rules changed a little to accommodate Ini files. Callbacks are now
called when parsing INI, and reset any time results are added.
- Adding extra utilities in full version only, `Timer` (not needed for parsing,
but useful for general CLI applications).
- Better support for custom `add_options` like functions.
## Version 0.6: Cleanup
Lots of cleanup and docs additions made it into this release. Parsing is simpler and more robust; fall through option added and works as expected; much more consistent variable names internally.
Lots of cleanup and docs additions made it into this release. Parsing is simpler
and more robust; fall through option added and works as expected; much more
consistent variable names internally.
- Simplified parsing to use `vector<string>` only
- Fixed fallthrough, made it optional as well (default: off): `.fallthrough()`.
@ -698,11 +908,20 @@ Lots of cleanup and docs additions made it into this release. Parsing is simpler
## Version 0.5: Windows support
- Allow `Hidden` options.
- Throw `OptionAlreadyAdded` errors for matching subcommands or options, with ignore-case included, tests
- `->ignore_case()` added to subcommands, options, and `add_set_ignore_case`. Subcommands inherit setting from parent App on creation.
- Subcommands now can be "chained", that is, left over arguments can now include subcommands that then get parsed. Subcommands are now a list (`get_subcommands`). Added `got_subcommand(App_or_name)` to check for subcommands.
- Added `.allow_extras()` to disable error on failure. Parse returns a vector of leftover options. Renamed error to `ExtrasError`, and now triggers on extra options too.
- Added `require_subcommand` to `App`, to simplify forcing subcommands. Do **not** do `add_subcommand()->require_subcommand`, since that is the subcommand, not the main `App`.
- Throw `OptionAlreadyAdded` errors for matching subcommands or options, with
ignore-case included, tests
- `->ignore_case()` added to subcommands, options, and `add_set_ignore_case`.
Subcommands inherit setting from parent App on creation.
- Subcommands now can be "chained", that is, left over arguments can now include
subcommands that then get parsed. Subcommands are now a list
(`get_subcommands`). Added `got_subcommand(App_or_name)` to check for
subcommands.
- Added `.allow_extras()` to disable error on failure. Parse returns a vector of
leftover options. Renamed error to `ExtrasError`, and now triggers on extra
options too.
- Added `require_subcommand` to `App`, to simplify forcing subcommands. Do
**not** do `add_subcommand()->require_subcommand`, since that is the
subcommand, not the main `App`.
- Added printout of ini file text given parsed options, skips flags.
- Support for quotes and spaces in ini files
- Fixes to allow support for Windows (added Appveyor) (Uses `-`, not `/` syntax)
@ -717,14 +936,16 @@ Lots of cleanup and docs additions made it into this release. Parsing is simpler
## Version 0.3: Plumbum compatibility
- Added `->requires`, `->excludes`, and `->envname` from [Plumbum](http://plumbum.readthedocs.io/en/latest/)
- Added `->requires`, `->excludes`, and `->envname` from
[Plumbum](http://plumbum.readthedocs.io/en/latest/)
- Supports `->mandatory` from Plumbum
- More tests for help strings, improvements in formatting
- Support type and set syntax in positionals help strings
- Added help groups, with `->group("name")` syntax
- Added initial support for ini file reading with `add_config` option.
- Supports GCC 4.7 again
- Clang 3.5 now required for tests due to googlemock usage, 3.4 should still work otherwise
- Clang 3.5 now required for tests due to googlemock usage, 3.4 should still
work otherwise
- Changes `setup` for an explicit help bool in constructor/`add_subcommand`
## Version 0.2: Leaner and meaner
@ -739,4 +960,5 @@ Lots of cleanup and docs additions made it into this release. Parsing is simpler
## Version 0.1: First release
First release before major cleanup. Still has make syntax and combiners; very clever syntax but not the best or most commonly expected way to work.
First release before major cleanup. Still has make syntax and combiners; very
clever syntax but not the best or most commonly expected way to work.

1270
README.md

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,11 @@ variables:
jobs:
- job: ClangTidy
variables:
CXX_FLAGS: "-Werror -Wcast-align -Wfloat-equal -Wimplicit-atomic-properties -Wmissing-declarations -Woverlength-strings -Wshadow -Wstrict-selector-match -Wundeclared-selector -Wunreachable-code -std=c++11"
CXX_FLAGS: >
-Werror -Wcast-align -Wfloat-equal -Wimplicit-atomic-properties
-Wmissing-declarations -Woverlength-strings -Wshadow
-Wstrict-selector-match -Wundeclared-selector -Wunreachable-code
-std=c++11
cli11.options: -DCLI11_CLANG_TIDY=ON -DCLI11_CLANG_TIDY_OPTIONS="-fix"
cli11.std: 11
cli11.single: OFF

View File

@ -1,12 +1,25 @@
# CLI11: An introduction
This gitbook is designed to provide an introduction to using the CLI11 library to write your own command line programs. The library is designed to be clean, intuitive, but powerful. There are no requirements beyond C++11 support (and even `<regex>` support not required). It works on Mac, Linux, and Windows, and has 100% test coverage on all three systems. You can simply drop in a single header file (`CLI11.hpp` available in [releases][]) to use CLI11 in your own application. Other ways to integrate it into a build system are listed in the [README][].
This gitbook is designed to provide an introduction to using the CLI11 library
to write your own command line programs. The library is designed to be clean,
intuitive, but powerful. There are no requirements beyond C++11 support (and
even `<regex>` support not required). It works on Mac, Linux, and Windows, and
has 100% test coverage on all three systems. You can simply drop in a single
header file (`CLI11.hpp` available in [releases][]) to use CLI11 in your own
application. Other ways to integrate it into a build system are listed in the
[README][].
The library was inspired the Python libraries [Plumbum][] and [Click][], and incorporates many of their user friendly features. The library is extensively documented, with a [friendly introduction][readme], this tutorial book, and more technical [API docs][].
The library was inspired the Python libraries [Plumbum][] and [Click][], and
incorporates many of their user friendly features. The library is extensively
documented, with a [friendly introduction][readme], this tutorial book, and more
technical [API docs][].
> Feel free to contribute to [this documentation here][cli11tutorial] if something can be improved!
> Feel free to contribute to [this documentation here][cli11tutorial] if
> something can be improved!
The syntax is simple and scales from a basic application to a massive physics analysis with multiple models and many parameters and switches. For example, this is a simple program that has an optional parameter that defaults to 0:
The syntax is simple and scales from a basic application to a massive physics
analysis with multiple models and many parameters and switches. For example,
this is a simple program that has an optional parameter that defaults to 0:
```term
gitbook $ ./a.out
@ -24,13 +37,16 @@ Options:
-p INT Parameter
```
Like any good command line application, help is provided. This program can be implemented in 10 lines:
Like any good command line application, help is provided. This program can be
implemented in 10 lines:
[include](code/intro.cpp)
[Source code](https://github.com/CLIUtils/CLI11/blob/main/book/code/intro.cpp)
Unlike some other libraries, this is enough to exit correctly and cleanly if help is requested or if incorrect arguments are passed. You can try this example out for yourself. To compile with GCC:
Unlike some other libraries, this is enough to exit correctly and cleanly if
help is requested or if incorrect arguments are passed. You can try this example
out for yourself. To compile with GCC:
```term
gitbook:examples $ c++ -std=c++11 intro.cpp
@ -45,13 +61,26 @@ app.add_option("-f,--file", file, "Require an existing file")
->check(CLI::ExistingFile);
```
You can use any valid type; the above example could have used a `boost::file_system` file instead of a `std::string`. The value is a real value and does not require any special lookups to access. You do not have to risk typos by repeating the values after parsing like some libraries require. The library also handles positional arguments, flags, fixed or unlimited repeating options, interdependent options, flags, custom validators, help groups, and more.
You can use any valid type; the above example could have used a
`boost::file_system` file instead of a `std::string`. The value is a real value
and does not require any special lookups to access. You do not have to risk
typos by repeating the values after parsing like some libraries require. The
library also handles positional arguments, flags, fixed or unlimited repeating
options, interdependent options, flags, custom validators, help groups, and
more.
You can use subcommands, as well. Subcommands support callback lambda functions when parsed, or they can be checked later. You can infinitely nest subcommands, and each is a full `App` instance, supporting everything listed above.
You can use subcommands, as well. Subcommands support callback lambda functions
when parsed, or they can be checked later. You can infinitely nest subcommands,
and each is a full `App` instance, supporting everything listed above.
Reading/producing `.ini` files for configuration is also supported, as is using environment variables as input. The base `App` can be subclassed and customized for use in a toolkit (like [GooFit][]). All the standard shell idioms, like `--`, work as well.
Reading/producing `.ini` files for configuration is also supported, as is using
environment variables as input. The base `App` can be subclassed and customized
for use in a toolkit (like [GooFit][]). All the standard shell idioms, like
`--`, work as well.
CLI11 was developed at the [University of Cincinnati][] in support of the [GooFit][] library under [NSF Award 1414736][nsf 1414736]. It was featured in a [DIANA/HEP][] meeting at CERN. Please give it a try! Feedback is always welcome.
CLI11 was developed at the [University of Cincinnati][] in support of the
[GooFit][] library under [NSF Award 1414736][nsf 1414736]. It was featured in a
[DIANA/HEP][] meeting at CERN. Please give it a try! Feedback is always welcome.
[goofit]: https://github.com/GooFit/GooFit
[diana/hep]: https://diana-hep.org

View File

@ -9,12 +9,15 @@ std::string opt;
app.add_option("--my_option", opt)->envname("MY_OPTION");
```
If not given on the command line, the environment variable will be checked and read from if it exists. All the standard tools, like default and required, work as expected.
If passed on the command line, this will ignore the environment variable.
If not given on the command line, the environment variable will be checked and
read from if it exists. All the standard tools, like default and required, work
as expected. If passed on the command line, this will ignore the environment
variable.
## Needs/excludes
You can set a network of requirements. For example, if flag a needs flag b but cannot be given with flag c, that would be:
You can set a network of requirements. For example, if flag a needs flag b but
cannot be given with flag c, that would be:
```cpp
auto a = app.add_flag("-a");
@ -25,11 +28,14 @@ a->needs(b);
a->excludes(c);
```
CLI11 will make sure your network of requirements makes sense, and will throw an error immediately if it does not.
CLI11 will make sure your network of requirements makes sense, and will throw an
error immediately if it does not.
## Custom option callbacks
You can make a completely generic option with a custom callback. For example, if you wanted to add a complex number (already exists, so please don't actually do this):
You can make a completely generic option with a custom callback. For example, if
you wanted to add a complex number (already exists, so please don't actually do
this):
```cpp
CLI::Option *
@ -62,7 +68,13 @@ add_option(app, "-c,--complex", comp);
## Custom converters
You can add your own converters to allow CLI11 to accept more option types in the standard calls. These can only be used for "single" size options (so complex, vector, etc. are a separate topic). If you set up a custom `istringstream& operator <<` overload before include CLI11, you can support different conversions. If you place this in the CLI namespace, you can even keep this from affecting the rest of your code. Here's how you could add `boost::optional` for a compiler that does not have `__has_include`:
You can add your own converters to allow CLI11 to accept more option types in
the standard calls. These can only be used for "single" size options (so
complex, vector, etc. are a separate topic). If you set up a custom
`istringstream& operator <<` overload before include CLI11, you can support
different conversions. If you place this in the CLI namespace, you can even keep
this from affecting the rest of your code. Here's how you could add
`boost::optional` for a compiler that does not have `__has_include`:
```cpp
// CLI11 already does this if __has_include is defined
@ -87,7 +99,10 @@ template <typename T> std::istringstream &operator>>(std::istringstream &in, boo
#include <CLI11.hpp>
```
This is an example of how to use the system only; if you are just looking for a way to activate `boost::optional` support on older compilers, you should define `CLI11_BOOST_OPTIONAL` before including a CLI11 file, you'll get the `boost::optional` support.
This is an example of how to use the system only; if you are just looking for a
way to activate `boost::optional` support on older compilers, you should define
`CLI11_BOOST_OPTIONAL` before including a CLI11 file, you'll get the
`boost::optional` support.
## Custom converters and type names: std::chrono example

View File

@ -1,6 +1,8 @@
# Making a git clone
Let's try our hand at a little `git` clone, called `geet`. It will just print it's intent, rather than running actual code, since it's just a demonstration. Let's start by adding an app and requiring 1 subcommand to run:
Let's try our hand at a little `git` clone, called `geet`. It will just print
it's intent, rather than running actual code, since it's just a demonstration.
Let's start by adding an app and requiring 1 subcommand to run:
[include:"Intro"](../code/geet.cpp)
@ -12,7 +14,8 @@ Now, let's add `commit`:
[include:"Commit"](../code/geet.cpp)
All that's need now is the parse call. We'll print a little message after the code runs, and then return:
All that's need now is the parse call. We'll print a little message after the
code runs, and then return:
[include:"Parse"](../code/geet.cpp)
@ -28,4 +31,9 @@ You'll see it behaves pretty much like `git`.
## Multi-file App parse code
This example could be made much nicer if it was split into files, one per subcommand. If you simply use shared pointers instead of raw values in the lambda capture, you can tie the lifetime to the lambda function lifetime. CLI11 has a [multifile example](https://github.com/CLIUtils/CLI11/tree/main/examples/subcom_in_files) in its example folder.
This example could be made much nicer if it was split into files, one per
subcommand. If you simply use shared pointers instead of raw values in the
lambda capture, you can tie the lifetime to the lambda function lifetime. CLI11
has a
[multifile example](https://github.com/CLIUtils/CLI11/tree/main/examples/subcom_in_files)
in its example folder.

View File

@ -4,17 +4,30 @@ The simplest CLI11 program looks like this:
[include](../code/simplest.cpp)
The first line includes the library; this explicitly uses the single file edition (see [Selecting an edition](/chapters/installation)).
The first line includes the library; this explicitly uses the single file
edition (see [Selecting an edition](/chapters/installation)).
After entering the main function, you'll see that a `CLI::App` object is created. This is the basis for all interactions with the library. You could optionally provide a description for your app here.
After entering the main function, you'll see that a `CLI::App` object is
created. This is the basis for all interactions with the library. You could
optionally provide a description for your app here.
A normal CLI11 application would define some flags and options next. This is a simplest possible example, so we'll go on.
A normal CLI11 application would define some flags and options next. This is a
simplest possible example, so we'll go on.
The macro `CLI11_PARSE` just runs five simple lines. This internally runs `app.parse(argc, argv)`, which takes the command line info from C++ and parses it. If there is an error, it throws a `ParseError`; if you catch it, you can use `app.exit` with the error as an argument to print a nice message and produce the correct return code for your application.
The macro `CLI11_PARSE` just runs five simple lines. This internally runs
`app.parse(argc, argv)`, which takes the command line info from C++ and parses
it. If there is an error, it throws a `ParseError`; if you catch it, you can use
`app.exit` with the error as an argument to print a nice message and produce the
correct return code for your application.
If you just use `app.parse` directly, your application will still work, but the stack will not be correctly unwound since you have an uncaught exception, and the command line output will be cluttered, especially for help.
If you just use `app.parse` directly, your application will still work, but the
stack will not be correctly unwound since you have an uncaught exception, and
the command line output will be cluttered, especially for help.
For this (and most of the examples in this book) we will assume that we have the `CLI11.hpp` file in the current directory and that we are creating an output executable `a.out` on a macOS or Linux system. The commands to compile and test this example would be:
For this (and most of the examples in this book) we will assume that we have the
`CLI11.hpp` file in the current directory and that we are creating an output
executable `a.out` on a macOS or Linux system. The commands to compile and test
this example would be:
```term
gitbook:examples $ g++ -std=c++11 simplest.cpp

View File

@ -2,17 +2,25 @@
## Reading a configure file
You can tell your app to allow configure files with `set_config("--config")`. There are 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.
You can tell your app to allow configure files with `set_config("--config")`.
There are 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.
### Adding a default path
if it is desired that config files be searched for a in a default path the `CLI::FileOnDefaultPath` transform can be used.
if it is desired that config files be searched for a in a default path the
`CLI::FileOnDefaultPath` transform can be used.
```cpp
app.set_config("--config")->transform(CLI::FileOnDefaultPath("/default_path/"));
```
This will allow specified files to either exist as given or on a specified default path.
This will allow specified files to either exist as given or on a specified
default path.
```cpp
app.set_config("--config")
@ -20,7 +28,10 @@ app.set_config("--config")
->transform(CLI::FileOnDefaultPath("/default_path2/",false));
```
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
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
```cpp
app.set_config("--config")
@ -29,32 +40,39 @@ app.set_config("--config")
### Extra fields
Sometimes configuration files are used for multiple purposes so CLI11 allows options on how to deal with extra fields
Sometimes configuration files are used for multiple purposes so CLI11 allows
options on how to deal with extra fields
```cpp
app.allow_config_extras(true);
```
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 allow capture the extras in the extras field of the app. (NOTE: This also
sets the `allow_extras` in the app to true)
```cpp
app.allow_config_extras(false);
```
will generate an error if there are any extra fields
for slightly finer control there is a scoped enumeration of the modes or
will generate an error if there are any extra fields for slightly finer control
there is a scoped enumeration of the modes or
```cpp
app.allow_config_extras(CLI::config_extras_mode::ignore);
```
will completely ignore extra parameters in the config file. This mode is the default.
will completely ignore extra parameters in the config file. This mode is the
default.
```cpp
app.allow_config_extras(CLI::config_extras_mode::capture);
```
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.
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.
```cpp
app.allow_config_extras(CLI::config_extras_mode::error);
@ -66,17 +84,20 @@ is equivalent to `app.allow_config_extras(false);`
app.allow_config_extras(CLI::config_extras_mode::ignore_all);
```
will completely ignore any mismatches, extras, or other issues with the config file
will completely ignore any mismatches, extras, or other issues with the config
file
### Getting the used configuration file name
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.
`app["--config"]->as<std::string>()` assuming `--config` was the configuration
option name.
## Configure file format
Here is an example configuration file, in [TOML](https://github.com/toml-lang/toml) format:
Here is an example configuration file, in
[TOML](https://github.com/toml-lang/toml) format:
```ini
# Comments are supported, using a #
@ -93,7 +114,15 @@ in_subcommand = Wow
subcommand = true # could also be give as sub.subcommand=true
```
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.)
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.
@ -111,7 +140,9 @@ in_subcommand = Wow
sub.subcommand = true
```
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 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.
## Multiple configuration files
@ -121,11 +152,15 @@ If it is desired that multiple configuration be allowed. Use
app.set_config("--config")->expected(1, X);
```
Where X is some positive integer and will allow up to `X` configuration files to be specified by separate `--config` arguments.
Where X is some positive integer and will allow up to `X` configuration files to
be specified by separate `--config` arguments.
## Writing out a configure file
To print a configuration file from the passed arguments, use `.config_to_str(default_also=false, write_description=false)`, where `default_also` will also show any defaulted arguments, and `write_description` will include option descriptions and the App description
To print a configuration file from the passed arguments, use
`.config_to_str(default_also=false, write_description=false)`, where
`default_also` will also show any defaulted arguments, and `write_description`
will include option descriptions and the App description
```cpp
CLI::App app;
@ -136,7 +171,8 @@ To print a configuration file from the passed arguments, use `.config_to_str(def
std::cout<<app.config_to_str(true,true);
```
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.
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.
```cpp
auto fmtr=app.get_config_formatter();
@ -147,7 +183,11 @@ if a prefix is needed to print before the options, for example to print a config
### Customization of configure file output
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
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
```cpp
/// the character used for comments
@ -176,41 +216,62 @@ std::string configSection;
These can be modified via setter functions
- `ConfigBase *comment(char cchar)`: Specify the character to start a comment block
- `ConfigBase *arrayBounds(char aStart, char aEnd)`: Specify the start and end characters for an array
- `ConfigBase *arrayDelimiter(char aSep)`: Specify the delimiter character for an array
- `ConfigBase *valueSeparator(char vSep)`: Specify the delimiter between a name and value
- `ConfigBase *quoteCharacter(char qString, char qChar)` :specify the characters to use around strings and single characters
- `ConfigBase *maxLayers(uint8_t layers)` : specify the maximum number of parent layers to process. This is useful to limit processing for larger config files
- `ConfigBase *parentSeparator(char sep)` : specify the character to separate parent layers from options
- `ConfigBase *section(const std::string &sectionName)` : specify the section name to use to get the option values, only this section will be processed
- `ConfigBase *index(uint16_t sectionIndex)` : specify an index section to use for processing if multiple TOML sections of the same name are present `[[section]]`
- `ConfigBase *comment(char cchar)`: Specify the character to start a comment
block
- `ConfigBase *arrayBounds(char aStart, char aEnd)`: Specify the start and end
characters for an array
- `ConfigBase *arrayDelimiter(char aSep)`: Specify the delimiter character for
an array
- `ConfigBase *valueSeparator(char vSep)`: Specify the delimiter between a name
and value
- `ConfigBase *quoteCharacter(char qString, char qChar)` :specify the characters
to use around strings and single characters
- `ConfigBase *maxLayers(uint8_t layers)` : specify the maximum number of parent
layers to process. This is useful to limit processing for larger config files
- `ConfigBase *parentSeparator(char sep)` : specify the character to separate
parent layers from options
- `ConfigBase *section(const std::string &sectionName)` : specify the section
name to use to get the option values, only this section will be processed
- `ConfigBase *index(uint16_t sectionIndex)` : specify an index section to use
for processing if multiple TOML sections of the same name are present
`[[section]]`
For example, to specify reading a configure file that used `:` to separate name and values:
For example, to specify reading a configure file that used `:` to separate name
and values:
```cpp
auto config_base=app.get_config_formatter_base();
config_base->valueSeparator(':');
```
The default configuration file will read INI files, but will write out files in the TOML format. To specify outputting INI formatted files use
The default configuration file will read INI files, but will write out files in
the TOML format. To specify outputting INI formatted files use
```cpp
app.config_formatter(std::make_shared<CLI::ConfigINI>());
```
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.
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.
## Custom formats
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:
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:
```cpp
std::string to_config(const CLI::App *app, bool default_also, bool, std::string) const;
std::vector<CLI::ConfigItem> from_config(std::istream &input) const;
```
The `CLI::ConfigItem`s 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.
The `CLI::ConfigItem`s 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:
@ -218,7 +279,9 @@ Finally, set your new class as new config formatter:
app.config_formatter(std::make_shared<NewConfig>());
```
See [`examples/json.cpp`](https://github.com/CLIUtils/CLI11/blob/main/examples/json.cpp) for a complete JSON config example.
See
[`examples/json.cpp`](https://github.com/CLIUtils/CLI11/blob/main/examples/json.cpp)
for a complete JSON config example.
### Trivial JSON configuration example
@ -236,21 +299,40 @@ The parser can handle these structures with only a minor tweak
app.get_config_formatter_base()->valueSeparator(':');
```
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.
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.
## Triggering Subcommands
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.
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.
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.
## Stream parsing
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.
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.
## Implementation Notes
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.
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.
1. First long name
2. Positional name

View File

@ -1,6 +1,8 @@
# Adding Flags
The most basic addition to a command line program is a flag. This is simply something that does not take any arguments. Adding a flag in CLI11 is done in one of three ways.
The most basic addition to a command line program is a flag. This is simply
something that does not take any arguments. Adding a flag in CLI11 is done in
one of three ways.
## Boolean flags
@ -11,60 +13,93 @@ bool my_flag{false};
app.add_flag("-f", my_flag, "Optional description");
```
This will bind the flag `-f` to the boolean `my_flag`. After the parsing step, `my_flag` will be `false` if the flag was not found on the command line, or `true` if it was. By default, it will be allowed any number of times, but if you explicitly\[^1\] request `->take_last(false)`, it will only be allowed once; passing something like `./my_app -f -f` or `./my_app -ff` will throw a `ParseError` with a nice help description. A flag name may start with any character except ('-', ' ', '\n', and '!'). For long flags, after the first character all characters are allowed except ('=',':','{',' ', '\n'). Names are given as a comma separated string, with the dash or dashes. An flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed.
This will bind the flag `-f` to the boolean `my_flag`. After the parsing step,
`my_flag` will be `false` if the flag was not found on the command line, or
`true` if it was. By default, it will be allowed any number of times, but if you
explicitly\[^1\] request `->take_last(false)`, it will only be allowed once;
passing something like `./my_app -f -f` or `./my_app -ff` will throw a
`ParseError` with a nice help description. A flag name may start with any
character except ('-', ' ', '\n', and '!'). For long flags, after the first
character all characters are allowed except ('=',':','{',' ', '\n'). Names are
given as a comma separated string, with the dash or dashes. An flag can have as
many names as you want, and afterward, using `count`, you can use any of the
names, with dashes as needed.
## Integer flags
If you want to allow multiple flags and count their value, simply use any integral variables instead of a bool:
If you want to allow multiple flags and count their value, simply use any
integral variables instead of a bool:
```cpp
int my_flag{0};
app.add_flag("-f", my_flag, "Optional description");
```
After the parsing step, `my_flag` will contain the number of times this flag was found on the command line, including 0 if not found.
After the parsing step, `my_flag` will contain the number of times this flag was
found on the command line, including 0 if not found.
This behavior can also be controlled manually via `->multi_option_policy(CLI::MultiOptionPolicy::Sum)` as of version 2.2.
This behavior can also be controlled manually via
`->multi_option_policy(CLI::MultiOptionPolicy::Sum)` as of version 2.2.
## Arbitrary type flags
CLI11 allows the type of the variable to assign to in the `add_flag` function to be any supported type. This is particularly useful in combination with specifying default values for flags. The allowed types include bool, int, float, vector, enum, or string-like.
CLI11 allows the type of the variable to assign to in the `add_flag` function to
be any supported type. This is particularly useful in combination with
specifying default values for flags. The allowed types include bool, int, float,
vector, enum, or string-like.
### Default Flag Values
Flag options specified through the `add_flag*` functions allow a syntax for the option names to default particular options to a false value or any other value if some flags are passed. For example:
Flag options specified through the `add_flag*` functions allow a syntax for the
option names to default particular options to a false value or any other value
if some flags are passed. For example:
```cpp
app.add_flag("--flag,!--no-flag",result,"help for flag");
```
specifies that if `--flag` is passed on the command line result will be true or contain a value of 1. If `--no-flag` is
passed `result` will contain false or -1 if `result` is a signed integer type, or 0 if it is an unsigned type. An
alternative form of the syntax is more explicit: `"--flag,--no-flag{false}"`; this is equivalent to the previous
example. This also works for short form options `"-f,!-n"` or `"-f,-n{false}"`. If `variable_to_bind_to` is anything but an integer value the
default behavior is to take the last value given, while if `variable_to_bind_to` is an integer type the behavior will be to sum
all the given arguments and return the result. This can be modified if needed by changing the `multi_option_policy` on each flag (this is not inherited).
The default value can be any value. For example if you wished to define a numerical flag:
specifies that if `--flag` is passed on the command line result will be true or
contain a value of 1. If `--no-flag` is passed `result` will contain false or -1
if `result` is a signed integer type, or 0 if it is an unsigned type. An
alternative form of the syntax is more explicit: `"--flag,--no-flag{false}"`;
this is equivalent to the previous example. This also works for short form
options `"-f,!-n"` or `"-f,-n{false}"`. If `variable_to_bind_to` is anything but
an integer value the default behavior is to take the last value given, while if
`variable_to_bind_to` is an integer type the behavior will be to sum all the
given arguments and return the result. This can be modified if needed by
changing the `multi_option_policy` on each flag (this is not inherited). The
default value can be any value. For example if you wished to define a numerical
flag:
```cpp
app.add_flag("-1{1},-2{2},-3{3}",result,"numerical flag")
```
using any of those flags on the command line will result in the specified number in the output. Similar things can be done for string values, and enumerations, as long as the default value can be converted to the given type.
using any of those flags on the command line will result in the specified number
in the output. Similar things can be done for string values, and enumerations,
as long as the default value can be converted to the given type.
## Pure flags
Every command that starts with `add_`, such as the flag commands, return a pointer to the internally stored `CLI::Option` that describes your addition. If you prefer, you can capture this pointer and use it, and that allows you to skip adding a variable to bind to entirely:
Every command that starts with `add_`, such as the flag commands, return a
pointer to the internally stored `CLI::Option` that describes your addition. If
you prefer, you can capture this pointer and use it, and that allows you to skip
adding a variable to bind to entirely:
```cpp
CLI::Option* my_flag = app.add_flag("-f", "Optional description");
```
After parsing, you can use `my_flag->count()` to count the number of times this was found. You can also directly use the value (`*my_flag`) as a bool. `CLI::Option` will be discussed in more detail later.
After parsing, you can use `my_flag->count()` to count the number of times this
was found. You can also directly use the value (`*my_flag`) as a bool.
`CLI::Option` will be discussed in more detail later.
## Callback flags
If you want to define a callback that runs when you make a flag, you can use `add_flag_function` (C++11 or newer) or `add_flag` (C++14 or newer only) to add a callback function. The function should have the signature `void(std::size_t)`. This could be useful for a version printout, etc.
If you want to define a callback that runs when you make a flag, you can use
`add_flag_function` (C++11 or newer) or `add_flag` (C++14 or newer only) to add
a callback function. The function should have the signature `void(std::size_t)`.
This could be useful for a version printout, etc.
```cpp
auto callback = [](int count){std::cout << "This was called " << count << " times";};
@ -73,9 +108,15 @@ app.add_flag_function("-c", callback, "Optional description");
## Aliases
The name string, the first item of every `add_` method, can contain as many short and long names as you want, separated by commas. For example, `"-a,--alpha,-b,--beta"` would allow any of those to be recognized on the command line. If you use the same name twice, or if you use the same name in multiple flags, CLI11 will immediately throw a `CLI::ConstructionError` describing your problem (it will not wait until the parsing step).
The name string, the first item of every `add_` method, can contain as many
short and long names as you want, separated by commas. For example,
`"-a,--alpha,-b,--beta"` would allow any of those to be recognized on the
command line. If you use the same name twice, or if you use the same name in
multiple flags, CLI11 will immediately throw a `CLI::ConstructionError`
describing your problem (it will not wait until the parsing step).
If you want to make an option case insensitive, you can use the `->ignore_case()` method on the `CLI::Option` to do that. For example,
If you want to make an option case insensitive, you can use the
`->ignore_case()` method on the `CLI::Option` to do that. For example,
```cpp
bool flag{false};
@ -122,4 +163,5 @@ Flag int: 3
Flag plain: 1
```
\[^1\]: It will not inherit this from the parent defaults, since this is often useful even if you don't want all options to allow multiple passed options.
\[^1\]: It will not inherit this from the parent defaults, since this is often
useful even if you don't want all options to allow multiple passed options.

View File

@ -1,12 +1,13 @@
# Formatting help output
{% hint style='info' %}
New in CLI11 1.6
{% endhint %}
{% hint style='info' %} New in CLI11 1.6 {% endhint %}
## Customizing an existing formatter
In CLI11, you can control the output of the help printout in full or in part. The default formatter was written in such a way as to be customizable. You can use `app.get_formatter()` to get the current formatter. The formatter you set will be inherited by subcommands that are created after you set the formatter.
In CLI11, you can control the output of the help printout in full or in part.
The default formatter was written in such a way as to be customizable. You can
use `app.get_formatter()` to get the current formatter. The formatter you set
will be inherited by subcommands that are created after you set the formatter.
There are several configuration options that you can set:
@ -15,7 +16,9 @@ There are several configuration options that you can set:
| `column_width(width)` | The width of the columns | Both |
| `label(key, value)` | Set a label to a different value | Both |
Labels will map the built in names and type names from key to value if present. For example, if you wanted to change the width of the columns to 40 and the `REQUIRED` label from `(REQUIRED)` to `(MUST HAVE)`:
Labels will map the built in names and type names from key to value if present.
For example, if you wanted to change the width of the columns to 40 and the
`REQUIRED` label from `(REQUIRED)` to `(MUST HAVE)`:
```cpp
app.get_formatter()->column_width(40);
@ -24,7 +27,11 @@ app.get_formatter()->label("REQUIRED", "(MUST HAVE)");
## Subclassing
You can further configure pieces of the code while still keeping most of the formatting intact by subclassing either formatter and replacing any of the methods with your own. The formatters use virtual functions most places, so you are free to add or change anything about them. For example, if you wanted to remove the info that shows up between the option name and the description:
You can further configure pieces of the code while still keeping most of the
formatting intact by subclassing either formatter and replacing any of the
methods with your own. The formatters use virtual functions most places, so you
are free to add or change anything about them. For example, if you wanted to
remove the info that shows up between the option name and the description:
```cpp
class MyFormatter : public CLI::Formatter {
@ -34,11 +41,14 @@ class MyFormatter : public CLI::Formatter {
app.formatter(std::make_shared<MyFormatter>());
```
Look at the class definitions in `FormatterFwd.hpp` or the method definitions in `Formatter.hpp` to see what methods you have access to and how they are put together.
Look at the class definitions in `FormatterFwd.hpp` or the method definitions in
`Formatter.hpp` to see what methods you have access to and how they are put
together.
## Anatomy of a help message
This is a normal printout, with `<>` indicating the methods used to produce each line.
This is a normal printout, with `<>` indicating the methods used to produce each
line.
```text
<make_description(app)>
@ -55,9 +65,11 @@ This is a normal printout, with `<>` indicating the methods used to produce each
<make_footer(app)>
```
`make_usage` calls `make_option_usage(opt)` on all the positionals to build that part of the line. `make_subcommand` passes the subcommand as the app pointer.
`make_usage` calls `make_option_usage(opt)` on all the positionals to build that
part of the line. `make_subcommand` passes the subcommand as the app pointer.
The `make_groups` print the group name then call `make_option(o)` on the options listed in that group. The normal printout for an option looks like this:
The `make_groups` print the group name then call `make_option(o)` on the options
listed in that group. The normal printout for an option looks like this:
```text
make_option_opts(o)
@ -69,5 +81,6 @@ make_option_name(o,p) make_option_desc(o)
Notes:
- `*1`: This signature depends on whether the call is from a positional or optional.
- `*1`: This signature depends on whether the call is from a positional or
optional.
- `o` is opt pointer, `p` is true if positional.

View File

@ -6,7 +6,10 @@
#include <CLI11.hpp>
```
This example uses the single file edition of CLI11. You can download `CLI11.hpp` from the latest release and put it into the same folder as your source code, then compile this with C++ enabled. For a larger project, you can just put this in an include folder and you are set.
This example uses the single file edition of CLI11. You can download `CLI11.hpp`
from the latest release and put it into the same folder as your source code,
then compile this with C++ enabled. For a larger project, you can just put this
in an include folder and you are set.
## Full edition
@ -14,27 +17,42 @@ This example uses the single file edition of CLI11. You can download `CLI11.hpp`
#include <CLI/CLI.hpp>
```
If you want to use CLI11 in its full form, you can also use the original multiple file edition. This has an extra utility (`Timer`), and is does not require that you use a release. The only change to your code would be the include shown above.
If you want to use CLI11 in its full form, you can also use the original
multiple file edition. This has an extra utility (`Timer`), and is does not
require that you use a release. The only change to your code would be the
include shown above.
### CMake support for the full edition
If you use CMake 3.4+ for your project (highly recommended), CLI11 comes with a powerful CMakeLists.txt file that was designed to also be used with `add_subproject`. You can add the repository to your code (preferably as a git submodule), then add the following line to your project (assuming your folder is called CLI11):
If you use CMake 3.4+ for your project (highly recommended), CLI11 comes with a
powerful CMakeLists.txt file that was designed to also be used with
`add_subproject`. You can add the repository to your code (preferably as a git
submodule), then add the following line to your project (assuming your folder is
called CLI11):
```cmake
add_subdirectory(CLI11)
```
Then, you will have a target `CLI11::CLI11` that you can link to with `target_link_libraries`. It will provide the include paths you need for the library. This is the way [GooFit](https://github.com/GooFit/GooFit) uses CLI11, for example.
Then, you will have a target `CLI11::CLI11` that you can link to with
`target_link_libraries`. It will provide the include paths you need for the
library. This is the way [GooFit](https://github.com/GooFit/GooFit) uses CLI11,
for example.
You can also configure and optionally install CLI11, and CMake will create the necessary `lib/cmake/CLI11/CLI11Config.cmake` files, so `find_package(CLI11 CONFIG REQUIRED)` also works.
You can also configure and optionally install CLI11, and CMake will create the
necessary `lib/cmake/CLI11/CLI11Config.cmake` files, so
`find_package(CLI11 CONFIG REQUIRED)` also works.
If you use conan.io, CLI11 supports that too.
### Running tests on the full edition
CLI11 has examples and tests that can be accessed using a CMake build on any platform. Simply build and run ctest to run the 200+ tests to ensure CLI11 works on your system.
CLI11 has examples and tests that can be accessed using a CMake build on any
platform. Simply build and run ctest to run the 200+ tests to ensure CLI11 works
on your system.
As an example of the build system, the following code will download and test CLI11 in a simple Alpine Linux docker container [^1]:
As an example of the build system, the following code will download and test
CLI11 in a simple Alpine Linux docker container [^1]:
```term
gitbook:~ $ docker run -it alpine
@ -78,7 +96,8 @@ Test project /CLI11/build
Total Test time (real) = 0.34 sec
```
For the curious, the CMake options and defaults are listed below. Most options default to off if CLI11 is used as a subdirectory in another project.
For the curious, the CMake options and defaults are listed below. Most options
default to off if CLI11 is used as a subdirectory in another project.
| Option | Description |
| ----------------------------- | ----------------------------------------------------------------------------------------------- |
@ -89,4 +108,7 @@ For the curious, the CMake options and defaults are listed below. Most options d
| `CLI11_CLANG_TIDY=OFF` | Run `clang-tidy` on the examples and headers. Requires CMake 3.6+. |
| `CLI11_CLANG_TIDY_OPTIONS=""` | Options to pass to `clang-tidy`, such as `-fix` (single threaded build only if applying fixes!) |
[^1]: Docker is being used to create a pristine disposable environment; there is nothing special about this container. Alpine is being used because it is small, modern, and fast. Commands are similar on any other platform.
[^1]:
Docker is being used to create a pristine disposable environment; there is
nothing special about this container. Alpine is being used because it is
small, modern, and fast. Commands are similar on any other platform.

View File

@ -2,7 +2,8 @@
## Callbacks
The library was designed to bind to existing variables without requiring typed classes or inheritance. This is accomplished through lambda functions.
The library was designed to bind to existing variables without requiring typed
classes or inheritance. This is accomplished through lambda functions.
This looks like:
@ -14,30 +15,40 @@ Option* add_option(string name, T item) {
}
```
Obviously, you can't access `T` after the `add_` method is over, so it stores the string representation of the default value if it receives the special `true` value as the final argument (not shown above).
Obviously, you can't access `T` after the `add_` method is over, so it stores
the string representation of the default value if it receives the special `true`
value as the final argument (not shown above).
## Parsing
Parsing follows the following procedure:
1. `_validate`: Make sure the defined options and subcommands are self consistent.
1. `_validate`: Make sure the defined options and subcommands are self
consistent.
2. `_parse`: Main parsing routine. See below.
3. `_run_callback`: Run an App callback if present.
The parsing phase is the most interesting:
1. `_parse_single`: Run on each entry on the command line and fill the options/subcommands.
1. `_parse_single`: Run on each entry on the command line and fill the
options/subcommands.
2. `_process`: Run the procedure listed below.
3. `_process_extra`: This throws an error if needed on extra arguments that didn't fit in the parse.
3. `_process_extra`: This throws an error if needed on extra arguments that
didn't fit in the parse.
The `_process` procedure runs the following steps; each step is recursive and completes all subcommands before moving to the next step (new in 1.7). This ensures that interactions between options and subcommand options is consistent.
The `_process` procedure runs the following steps; each step is recursive and
completes all subcommands before moving to the next step (new in 1.7). This
ensures that interactions between options and subcommand options is consistent.
1. `_process_ini`: This reads an INI file and fills/changes options as needed.
2. `_process_env`: Look for environment variables.
3. `_process_callbacks`: Run the callback functions - this fills out the variables.
3. `_process_callbacks`: Run the callback functions - this fills out the
variables.
4. `_process_help_flags`: Run help flags if present (and quit).
5. `_process_requirements`: Make sure needs/excludes, required number of options present.
5. `_process_requirements`: Make sure needs/excludes, required number of options
present.
## Exceptions
The library immediately returns a C++ exception when it detects a problem, such as an incorrect construction or a malformed command line.
The library immediately returns a C++ exception when it detects a problem, such
as an incorrect construction or a malformed command line.

View File

@ -2,21 +2,29 @@
## Simple options
The most versatile addition to a command line program is an option. This is like a flag, but it takes an argument. CLI11 handles all the details for many types of options for you, based on their type. To add an option:
The most versatile addition to a command line program is an option. This is like
a flag, but it takes an argument. CLI11 handles all the details for many types
of options for you, based on their type. To add an option:
```cpp
int int_option{0};
app.add_option("-i", int_option, "Optional description");
```
This will bind the option `-i` to the integer `int_option`. On the command line, a single value that can be converted to an integer will be expected. Non-integer results will fail. If that option is not given, CLI11 will not touch the initial value. This allows you to set up defaults by simply setting your value beforehand. If you want CLI11 to display your default value, you can add `->capture_default_str()` after the option.
This will bind the option `-i` to the integer `int_option`. On the command line,
a single value that can be converted to an integer will be expected. Non-integer
results will fail. If that option is not given, CLI11 will not touch the initial
value. This allows you to set up defaults by simply setting your value
beforehand. If you want CLI11 to display your default value, you can add
`->capture_default_str()` after the option.
```cpp
int int_option{0};
app.add_option("-i", int_option, "Optional description")->capture_default_str();
```
You can use any C++ int-like type, not just `int`. CLI11 understands the following categories of types:
You can use any C++ int-like type, not just `int`. CLI11 understands the
following categories of types:
| Type | CLI11 |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@ -31,35 +39,60 @@ You can use any C++ int-like type, not just `int`. CLI11 understands the followi
| function | A function that takes an array of strings and returns a string that describes the conversion failure or empty for success. May be the empty function. (`{}`) |
| streamable | any other type with a `<<` operator will also work |
By default, CLI11 will assume that an option is optional, and one value is expected if you do not use a vector. You can change this on a specific option using option modifiers. An option name may start with any character except ('-', ' ', '\n', and '!'). For long options, after the first character all characters are allowed except ('=',':','{',' ', '\n'). Names are given as a comma separated string, with the dash or dashes. An option can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on the help line for its positional form.
By default, CLI11 will assume that an option is optional, and one value is
expected if you do not use a vector. You can change this on a specific option
using option modifiers. An option name may start with any character except ('-',
' ', '\n', and '!'). For long options, after the first character all characters
are allowed except ('=',':','{',' ', '\n'). Names are given as a comma separated
string, with the dash or dashes. An option can have as many names as you want,
and afterward, using `count`, you can use any of the names, with dashes as
needed, to count the options. One of the names is allowed to be given without
proceeding dash(es); if present the option is a positional option, and that name
will be used on the help line for its positional form.
## Positional options and aliases
When you give an option on the command line without a name, that is a positional option. Positional options are accepted in the same order they are defined. So, for example:
When you give an option on the command line without a name, that is a positional
option. Positional options are accepted in the same order they are defined. So,
for example:
```term
gitbook:examples $ ./a.out one --two three four
```
The string `one` would have to be the first positional option. If `--two` is a flag, then the remaining two strings are positional. If `--two` is a one-argument option, then `four` is the second positional. If `--two` accepts two or more arguments, then there are no more positionals.
The string `one` would have to be the first positional option. If `--two` is a
flag, then the remaining two strings are positional. If `--two` is a
one-argument option, then `four` is the second positional. If `--two` accepts
two or more arguments, then there are no more positionals.
To make a positional option, you simply give CLI11 one name that does not start with a dash. You can have as many (non-overlapping) names as you want for an option, but only one positional name. So the following name string is valid:
To make a positional option, you simply give CLI11 one name that does not start
with a dash. You can have as many (non-overlapping) names as you want for an
option, but only one positional name. So the following name string is valid:
```cpp
"-a,-b,--alpha,--beta,mypos"
```
This would make two short option aliases, two long option alias, and the option would be also be accepted as a positional.
This would make two short option aliases, two long option alias, and the option
would be also be accepted as a positional.
## Containers of options
If you use a vector or other container instead of a plain option, you can accept more than one value on the command line. By default, a container accepts as many options as possible, until the next value that could be a valid option name. You can specify a set number using an option modifier `->expected(N)`. (The default unlimited behavior on vectors is restored with `N=-1`) CLI11 does not differentiate between these two methods for unlimited acceptance options.
If you use a vector or other container instead of a plain option, you can accept
more than one value on the command line. By default, a container accepts as many
options as possible, until the next value that could be a valid option name. You
can specify a set number using an option modifier `->expected(N)`. (The default
unlimited behavior on vectors is restored with `N=-1`) CLI11 does not
differentiate between these two methods for unlimited acceptance options.
| Separate names | Combined names |
| ----------------- | -------------- |
| `--vec 1 --vec 2` | `--vec 1 2` |
It is also possible to specify a minimum and maximum number through `->expected(Min,Max)`. It is also possible to specify a min and max type size for the elements of the container. It most cases these values will be automatically determined but a user can manually restrict them.
It is also possible to specify a minimum and maximum number through
`->expected(Min,Max)`. It is also possible to specify a min and max type size
for the elements of the container. It most cases these values will be
automatically determined but a user can manually restrict them.
An example of setting up a vector option:
@ -68,13 +101,19 @@ std::vector<int> int_vec;
app.add_option("--vec", int_vec, "My vector option");
```
Vectors will be replaced by the parsed content if the option is given on the command line.
Vectors will be replaced by the parsed content if the option is given on the
command line.
A definition of a container for purposes of CLI11 is a type with a `end()`, `insert(...)`, `clear()` and `value_type` definitions. This includes `vector`, `set`, `deque`, `list`, `forward_iist`, `map`, `unordered_map` and a few others from the standard library, and many other containers from the boost library.
A definition of a container for purposes of CLI11 is a type with a `end()`,
`insert(...)`, `clear()` and `value_type` definitions. This includes `vector`,
`set`, `deque`, `list`, `forward_iist`, `map`, `unordered_map` and a few others
from the standard library, and many other containers from the boost library.
### Empty containers
By default a container will never return an empty container. If it is desired to allow an empty container to be returned, then the option must be modified with a 0 as the minimum expected value
By default a container will never return an empty container. If it is desired to
allow an empty container to be returned, then the option must be modified with a
0 as the minimum expected value
```cpp
std::vector<int> int_vec;
@ -83,7 +122,8 @@ app.add_option("--vec", int_vec, "Empty vector allowed")->expected(0,-1);
An empty vector can than be specified on the command line as `--vec {}`
To allow an empty vector from config file, the default must be set in addition to the above modification.
To allow an empty vector from config file, the default must be set in addition
to the above modification.
```cpp
std::vector<int> int_vec;
@ -113,13 +153,20 @@ std::vector<std::vector<int>> int_vec;
app.add_option("--vec", int_vec, "My vector of vectors option");
```
CLI11 inserts a separator sequence at the start of each argument call to separate the vectors. So unless the separators are injected as part of the command line each call of the option on the command line will result in a separate element of the outer vector. This can be manually controlled via `inject_separator(true|false)` but in nearly all cases this should be left to the defaults. To insert of a separator from the command line add a `%%` where the separation should occur.
CLI11 inserts a separator sequence at the start of each argument call to
separate the vectors. So unless the separators are injected as part of the
command line each call of the option on the command line will result in a
separate element of the outer vector. This can be manually controlled via
`inject_separator(true|false)` but in nearly all cases this should be left to
the defaults. To insert of a separator from the command line add a `%%` where
the separation should occur.
```bash
cmd --vec_of_vec 1 2 3 4 %% 1 2
```
would then result in a container of size 2 with the first element containing 4 values and the second 2.
would then result in a container of size 2 with the first element containing 4
values and the second 2.
This separator is also the only way to get values into something like
@ -130,7 +177,8 @@ app.add_option("--vec", two_vecs, "pair of vectors");
without calling the argument twice.
Further levels of nesting containers should compile but intermediate layers will only have a single element in the container, so is probably not that useful.
Further levels of nesting containers should compile but intermediate layers will
only have a single element in the container, so is probably not that useful.
### Nested types
@ -141,18 +189,21 @@ std::map<int, std::pair<int,std::string>> map;
app.add_option("--dict", map, "map of pairs");
```
will require 3 arguments for each invocation, and multiple sets of 3 arguments can be entered for a single invocation on the command line.
will require 3 arguments for each invocation, and multiple sets of 3 arguments
can be entered for a single invocation on the command line.
```cpp
std::map<int, std::pair<int,std::vector<std::string>>> map;
app.add_option("--dict", map, "map of pairs");
```
will result in a requirement for 2 integers on each invocation and absorb an unlimited number of strings including 0.
will result in a requirement for 2 integers on each invocation and absorb an
unlimited number of strings including 0.
## Option modifiers
When you call `add_option`, you get a pointer to the added option. You can use that to add option modifiers. A full listing of the option modifiers:
When you call `add_option`, you get a pointer to the added option. You can use
that to add option modifiers. A full listing of the option modifiers:
| Modifier | Description |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@ -190,11 +241,19 @@ When you call `add_option`, you get a pointer to the added option. You can use t
| `->trigger_on_parse()` | Have the option callback be triggered when the value is parsed vs. at the end of all parsing, the option callback can potentially be executed multiple times. Generally only useful if you have a user defined callback or validation check. Or potentially if a vector input is given multiple times as it will clear the results when a repeat option is given via command line. It will trigger the callbacks once per option call on the command line |
| `->option_text(string)` | Sets the text between the option name and description. |
The `->check(...)` and `->transform(...)` modifiers can also take a callback function of the form `bool function(std::string)` that runs on every value that the option receives, and returns a value that tells CLI11 whether the check passed or failed.
The `->check(...)` and `->transform(...)` modifiers can also take a callback
function of the form `bool function(std::string)` that runs on every value that
the option receives, and returns a value that tells CLI11 whether the check
passed or failed.
## Using the `CLI::Option` pointer
Each of the option creation mechanisms returns a pointer to the internally stored option. If you save that pointer, you can continue to access the option, and change setting on it later. The Option object can also be converted to a bool to see if it was passed, or `->count()` can be used to see how many times the option was passed. Since flags are also options, the same methods work on them.
Each of the option creation mechanisms returns a pointer to the internally
stored option. If you save that pointer, you can continue to access the option,
and change setting on it later. The Option object can also be converted to a
bool to see if it was passed, or `->count()` can be used to see how many times
the option was passed. Since flags are also options, the same methods work on
them.
```cpp
CLI::Option* opt = app.add_flag("--opt");
@ -207,17 +266,33 @@ if(* opt)
## Inheritance of defaults
One of CLI11's systems to allow customizability without high levels of verbosity is the inheritance system. You can set default values on the parent `App`, and all options and subcommands created from it remember the default values at the point of creation. The default value for Options, specifically, are accessible through the `option_defaults()` method. There are a number of settings that can be set and inherited:
One of CLI11's systems to allow customizability without high levels of verbosity
is the inheritance system. You can set default values on the parent `App`, and
all options and subcommands created from it remember the default values at the
point of creation. The default value for Options, specifically, are accessible
through the `option_defaults()` method. There are a number of settings that can
be set and inherited:
- `group`: The group name starts as "Options"
- `required`: If the option must be given. Defaults to `false`. Is ignored for flags.
- `multi_option_policy`: What to do if several copies of an option are passed and one value is expected. Defaults to `CLI::MultiOptionPolicy::Throw`. This is also used for bool flags, but they always are created with the value `CLI::MultiOptionPolicy::TakeLast` or `CLI::MultiOptionPolicy::Sum` regardless of the default, so that multiple bool flags does not cause an error. But you can override that setting by calling the `multi_option_policy` directly.
- `required`: If the option must be given. Defaults to `false`. Is ignored for
flags.
- `multi_option_policy`: What to do if several copies of an option are passed
and one value is expected. Defaults to `CLI::MultiOptionPolicy::Throw`. This
is also used for bool flags, but they always are created with the value
`CLI::MultiOptionPolicy::TakeLast` or `CLI::MultiOptionPolicy::Sum` regardless
of the default, so that multiple bool flags does not cause an error. But you
can override that setting by calling the `multi_option_policy` directly.
- `ignore_case`: Allow any mixture of cases for the option or flag name
- `ignore_underscore`: Allow any number of underscores in the option or flag name
- `configurable`: Specify whether an option can be configured through a config file
- `disable_flag_override`: do not allow flag values to be overridden on the command line
- `always_capture_default`: specify that the default values should be automatically captured.
- `delimiter`: A delimiter to use for capturing multiple values in a single command line string (e.g. --flag="flag,-flag2,flag3")
- `ignore_underscore`: Allow any number of underscores in the option or flag
name
- `configurable`: Specify whether an option can be configured through a config
file
- `disable_flag_override`: do not allow flag values to be overridden on the
command line
- `always_capture_default`: specify that the default values should be
automatically captured.
- `delimiter`: A delimiter to use for capturing multiple values in a single
command line string (e.g. --flag="flag,-flag2,flag3")
An example of usage:
@ -228,11 +303,13 @@ app.add_flag("--CaSeLeSs");
app.get_group() // is "Required"
```
Groups are mostly for visual organization, but an empty string for a group name will hide the option.
Groups are mostly for visual organization, but an empty string for a group name
will hide the option.
### Windows style options
You can also set the app setting `app->allow_windows_style_options()` to allow windows style options to also be recognized on the command line:
You can also set the app setting `app->allow_windows_style_options()` to allow
windows style options to also be recognized on the command line:
- `/a` (flag)
- `/f filename` (option)
@ -241,11 +318,23 @@ You can also set the app setting `app->allow_windows_style_options()` to allow w
- `/file:filename` (colon)
- `/long_flag:false` (long flag with : to override the default value)
Windows style options do not allow combining short options or values not separated from the short option like with `-` options. You still specify option names in the same manner as on Linux with single and double dashes when you use the `add_*` functions, and the Linux style on the command line will still work. If a long and a short option share the same name, the option will match on the first one defined.
Windows style options do not allow combining short options or values not
separated from the short option like with `-` options. You still specify option
names in the same manner as on Linux with single and double dashes when you use
the `add_*` functions, and the Linux style on the command line will still work.
If a long and a short option share the same name, the option will match on the
first one defined.
## Parse configuration
How an option and its arguments are parsed depends on a set of controls that are part of the option structure. In most circumstances these controls are set automatically based on the type or function used to create the option and the type the arguments are parsed into. The variables define the size of the underlying type (essentially how many strings make up the type), the expected size (how many groups are expected) and a flag indicating if multiple groups are allowed with a single option. And these interact with the `multi_option_policy` when it comes time to parse.
How an option and its arguments are parsed depends on a set of controls that are
part of the option structure. In most circumstances these controls are set
automatically based on the type or function used to create the option and the
type the arguments are parsed into. The variables define the size of the
underlying type (essentially how many strings make up the type), the expected
size (how many groups are expected) and a flag indicating if multiple groups are
allowed with a single option. And these interact with the `multi_option_policy`
when it comes time to parse.
### Examples
@ -256,7 +345,12 @@ std::string val;
app.add_option("--opt",val,"description");
```
creates an option that assigns a value to a `std::string` When this option is constructed it sets a type_size min and max of 1. Meaning that the assignment uses a single string. The Expected size is also set to 1 by default, and `allow_extra_args` is set to false. meaning that each time this option is called 1 argument is expected. This would also be the case if val were a `double`, `int` or any other single argument types.
creates an option that assigns a value to a `std::string` When this option is
constructed it sets a type_size min and max of 1. Meaning that the assignment
uses a single string. The Expected size is also set to 1 by default, and
`allow_extra_args` is set to false. meaning that each time this option is called
1 argument is expected. This would also be the case if val were a `double`,
`int` or any other single argument types.
now for example
@ -265,35 +359,49 @@ std::pair<int, std::string> val;
app.add_option("--opt",val,"description");
```
In this case the typesize is automatically detected to be 2 instead of 1, so the parsing would expect 2 arguments associated with the option.
In this case the typesize is automatically detected to be 2 instead of 1, so the
parsing would expect 2 arguments associated with the option.
```cpp
std::vector<int> val;
app.add_option("--opt",val,"description");
```
detects a type size of 1, since the underlying element type is a single string, so the minimum number of strings is 1. But since it is a vector the expected number can be very big. The default for a vector is (1<<30), and the allow_extra_args is set to true. This means that at least 1 argument is expected to follow the option, but arbitrary numbers of arguments may follow. These are checked if they have the form of an option but if not they are added to the argument.
detects a type size of 1, since the underlying element type is a single string,
so the minimum number of strings is 1. But since it is a vector the expected
number can be very big. The default for a vector is (1<<30), and the
allow_extra_args is set to true. This means that at least 1 argument is expected
to follow the option, but arbitrary numbers of arguments may follow. These are
checked if they have the form of an option but if not they are added to the
argument.
```cpp
std::vector<std::tuple<int, double, std::string>> val;
app.add_option("--opt",val,"description");
```
gets into the complicated cases where the type size is now 3. and the expected max is set to a large number and `allow_extra_args` is set to true. In this case at least 3 arguments are required to follow the option, and subsequent groups must come in groups of three, otherwise an error will result.
gets into the complicated cases where the type size is now 3. and the expected
max is set to a large number and `allow_extra_args` is set to true. In this case
at least 3 arguments are required to follow the option, and subsequent groups
must come in groups of three, otherwise an error will result.
```cpp
bool val{false};
app.add_flag("--opt",val,"description");
```
Using the add_flag methods for creating options creates an option with an expected size of 0, implying no arguments can be passed.
Using the add_flag methods for creating options creates an option with an
expected size of 0, implying no arguments can be passed.
```cpp
std::complex<double> val;
app.add_option("--opt",val,"description");
```
triggers the complex number type which has a min of 1 and max of 2, so 1 or 2 strings can be passed. Complex number conversion supports arguments of the form "1+2j" or "1","2", or "1" "2i". The imaginary number symbols `i` and `j` are interchangeable in this context.
triggers the complex number type which has a min of 1 and max of 2, so 1 or 2
strings can be passed. Complex number conversion supports arguments of the form
"1+2j" or "1","2", or "1" "2i". The imaginary number symbols `i` and `j` are
interchangeable in this context.
```cpp
std::vector<std::vector<int>> val;
@ -304,7 +412,9 @@ has a type size of 1 to (1<<30).
### Customization
The `type_size(N)`, `type_size(Nmin, Nmax)`, `expected(N)`, `expected(Nmin,Nmax)`, and `allow_extra_args()` can be used to customize an option. For example
The `type_size(N)`, `type_size(Nmin, Nmax)`, `expected(N)`,
`expected(Nmin,Nmax)`, and `allow_extra_args()` can be used to customize an
option. For example
```cpp
std::string val;
@ -312,16 +422,38 @@ auto opt=app.add_flag("--opt{vvv}",val,"description");
opt->expected(0,1);
```
will create a hybrid option, that can exist on its own in which case the value "vvv" is used or if a value is given that value will be used.
will create a hybrid option, that can exist on its own in which case the value
"vvv" is used or if a value is given that value will be used.
There are some additional options that can be specified to modify an option for specific cases:
There are some additional options that can be specified to modify an option for
specific cases:
- `->run_callback_for_default()` will specify that the callback should be executed when a default_val is set. This is set automatically when appropriate though it can be turned on or off and any user specified callback for an option will be executed when the default value for an option is set.
- `->run_callback_for_default()` will specify that the callback should be
executed when a default_val is set. This is set automatically when appropriate
though it can be turned on or off and any user specified callback for an
option will be executed when the default value for an option is set.
- `->force_callback()` will for the callback/value assignment to run at the conclusion of parsing regardless of whether the option was supplied or not. This can be used to force the default or execute some code.
- `->force_callback()` will for the callback/value assignment to run at the
conclusion of parsing regardless of whether the option was supplied or not.
This can be used to force the default or execute some code.
- `->trigger_on_parse()` will trigger the callback or value assignment each time the argument is passed. The value is reset if the option is supplied multiple times.
- `->trigger_on_parse()` will trigger the callback or value assignment each time
the argument is passed. The value is reset if the option is supplied multiple
times.
## Unusual circumstances
There are a few cases where some things break down in the type system managing options and definitions. Using the `add_option` method defines a lambda function to extract a default value if required. In most cases this is either straightforward or a failure is detected automatically and handled. But in a few cases a streaming template is available that several layers down may not actually be defined. This results in CLI11 not being able to detect this circumstance automatically and will result in compile error. One specific known case is `boost::optional` if the boost optional_io header is included. This header defines a template for all boost optional values even if they do not actually have a streaming operator. For example `boost::optional<std::vector>` does not have a streaming operator but one is detected since it is part of a template. For these cases a secondary method `app->add_option_no_stream(...)` is provided that bypasses this operation completely and should compile in these cases.
There are a few cases where some things break down in the type system managing
options and definitions. Using the `add_option` method defines a lambda function
to extract a default value if required. In most cases this is either
straightforward or a failure is detected automatically and handled. But in a few
cases a streaming template is available that several layers down may not
actually be defined. This results in CLI11 not being able to detect this
circumstance automatically and will result in compile error. One specific known
case is `boost::optional` if the boost optional_io header is included. This
header defines a template for all boost optional values even if they do not
actually have a streaming operator. For example `boost::optional<std::vector>`
does not have a streaming operator but one is detected since it is part of a
template. For these cases a secondary method `app->add_option_no_stream(...)` is
provided that bypasses this operation completely and should compile in these
cases.

View File

@ -1,21 +1,26 @@
# Subcommands and the App
Subcommands are keyword that invoke a new set of options and features. For example, the `git`
command has a long series of subcommands, like `add` and `commit`. Each can have its own options
and implementations. This chapter will focus on implementations that are contained in the same
C++ application, though the system git uses to extend the main command by calling other commands
in separate executables is supported too; that's called "Prefix commands" and is included at the
end of this chapter.
Subcommands are keyword that invoke a new set of options and features. For
example, the `git` command has a long series of subcommands, like `add` and
`commit`. Each can have its own options and implementations. This chapter will
focus on implementations that are contained in the same C++ application, though
the system git uses to extend the main command by calling other commands in
separate executables is supported too; that's called "Prefix commands" and is
included at the end of this chapter.
## The parent App
We'll start by discussing the parent `App`. You've already used it quite a bit, to create
options and set option defaults. There are several other things you can do with an `App`, however.
We'll start by discussing the parent `App`. You've already used it quite a bit,
to create options and set option defaults. There are several other things you
can do with an `App`, however.
You are given a lot of control the help output. You can set a footer with `app.footer("My Footer")`.
You can replace the default help print when a `ParseError` is thrown with `app.set_failure_message(CLI::FailureMessage::help)`.
The default is `CLI:::FailureMessage::simple`, and you can easily define a new one. Just make a (lambda) function that takes an App pointer
and a reference to an error code (even if you don't use them), and returns a string.
You are given a lot of control the help output. You can set a footer with
`app.footer("My Footer")`. You can replace the default help print when a
`ParseError` is thrown with
`app.set_failure_message(CLI::FailureMessage::help)`. The default is
`CLI:::FailureMessage::simple`, and you can easily define a new one. Just make a
(lambda) function that takes an App pointer and a reference to an error code
(even if you don't use them), and returns a string.
## Adding a subcommand
@ -25,12 +30,14 @@ Subcommands can be added just like an option:
CLI::App* sub = app.add_subcommand("sub", "This is a subcommand");
```
The subcommand should have a name as the first argument, and a little description for the
second argument. A pointer to the internally stored subcommand is provided; you usually will
be capturing that pointer and using it later (though you can use callbacks if you prefer). As
always, feel free to use `auto sub = ...` instead of naming the type.
The subcommand should have a name as the first argument, and a little
description for the second argument. A pointer to the internally stored
subcommand is provided; you usually will be capturing that pointer and using it
later (though you can use callbacks if you prefer). As always, feel free to use
`auto sub = ...` instead of naming the type.
You can check to see if the subcommand was received on the command line several ways:
You can check to see if the subcommand was received on the command line several
ways:
```cpp
if(*sub) ...
@ -39,39 +46,53 @@ if(app.got_subcommand(sub)) ...
if(app.got_subcommand("sub")) ...
```
You can also get a list of subcommands with `get_subcommands()`, and they will be in parsing order.
You can also get a list of subcommands with `get_subcommands()`, and they will
be in parsing order.
There are a lot of options that you can set on a subcommand; in fact,
subcommands have exactly the same options as your main app, since they are actually
the same class of object (as you may have guessed from the type above). This has the
pleasant side affect of making subcommands infinitely nestable.
subcommands have exactly the same options as your main app, since they are
actually the same class of object (as you may have guessed from the type above).
This has the pleasant side affect of making subcommands infinitely nestable.
## Required subcommands
Each App has controls to set the number of subcommands you expect. This is controlled by:
Each App has controls to set the number of subcommands you expect. This is
controlled by:
```cpp
app.require_subcommand(/* min */ 0, /* max */ 1);
```
If you set the max to 0, CLI11 will allow an unlimited number of subcommands. After the (non-unlimited) maximum
is reached, CLI11 will stop trying to match subcommands. So the if you pass "`one two`" to a command, and both `one`
and `two` are subcommands, it will depend on the maximum number as to whether the "`two`" is a subcommand or an argument to the
"`one`" subcommand.
If you set the max to 0, CLI11 will allow an unlimited number of subcommands.
After the (non-unlimited) maximum is reached, CLI11 will stop trying to match
subcommands. So the if you pass "`one two`" to a command, and both `one` and
`two` are subcommands, it will depend on the maximum number as to whether the
"`two`" is a subcommand or an argument to the "`one`" subcommand.
As a shortcut, you can also call the `require_subcommand` method with one argument; that will be the fixed number of subcommands if positive, it
will be the maximum number if negative. Calling it without an argument will set the required subcommands to 1 or more.
As a shortcut, you can also call the `require_subcommand` method with one
argument; that will be the fixed number of subcommands if positive, it will be
the maximum number if negative. Calling it without an argument will set the
required subcommands to 1 or more.
The maximum number of subcommands is inherited by subcommands. This allows you to set the maximum to 1 once at the beginning on the parent app if you only want single subcommands throughout your app. You should keep this in mind, if you are dealing with lots of nested subcommands.
The maximum number of subcommands is inherited by subcommands. This allows you
to set the maximum to 1 once at the beginning on the parent app if you only want
single subcommands throughout your app. You should keep this in mind, if you are
dealing with lots of nested subcommands.
## Using callbacks
You've already seen how to check to see what subcommands were given. It's often much easier, however, to just define the code you want to run when you are making your parser, and not run a bunch of code after `CLI11_PARSE` to analyse the state (Procedural! Yuck!). You can do that with lambda functions. A `std::function<void()>` callback `.callback()` is provided, and CLI11 ensures that all options are prepared and usable by reference capture before entering the callback. An
example is shown below in the `geet` program.
You've already seen how to check to see what subcommands were given. It's often
much easier, however, to just define the code you want to run when you are
making your parser, and not run a bunch of code after `CLI11_PARSE` to analyse
the state (Procedural! Yuck!). You can do that with lambda functions. A
`std::function<void()>` callback `.callback()` is provided, and CLI11 ensures
that all options are prepared and usable by reference capture before entering
the callback. An example is shown below in the `geet` program.
## Inheritance of defaults
The following values are inherited when you add a new subcommand. This happens at the point the subcommand is created:
The following values are inherited when you add a new subcommand. This happens
at the point the subcommand is created:
- The name and description for the help flag
- The footer
@ -94,28 +115,39 @@ There are several special modes for Apps and Subcommands.
### Allow extras
Normally CLI11 throws an error if you don't match all items given on the command line. However, you can enable `allow_extras()`
to instead store the extra values in `.remaining()`. You can get all remaining options including those in contained subcommands recursively in the original order with `.remaining(true)`.
`.remaining_size()` is also provided; this counts the size but ignores the `--` special separator if present.
Normally CLI11 throws an error if you don't match all items given on the command
line. However, you can enable `allow_extras()` to instead store the extra values
in `.remaining()`. You can get all remaining options including those in
contained subcommands recursively in the original order with `.remaining(true)`.
`.remaining_size()` is also provided; this counts the size but ignores the `--`
special separator if present.
### Fallthrough
Fallthrough allows an option that does not match in a subcommand to "fall through" to the parent command; if that parent
allows that option, it matches there instead. This was added to allow CLI11 to represent models:
Fallthrough allows an option that does not match in a subcommand to "fall
through" to the parent command; if that parent allows that option, it matches
there instead. This was added to allow CLI11 to represent models:
```term
gitbook:code $ ./my_program my_model_1 --model_flag --shared_flag
```
Here, `--shared_flag` was set on the main app, and on the command line it "falls through" `my_model_1` to match on the main app.
Here, `--shared_flag` was set on the main app, and on the command line it "falls
through" `my_model_1` to match on the main app.
### Prefix command
This is a special mode that allows "prefix" commands, where the parsing completely stops when it gets to an unknown option. Further unknown options are ignored, even if they could match. Git is the traditional example for prefix commands; if you run git with an unknown subcommand, like "`git thing`", it then calls another command called "`git-thing`" with the remaining options intact.
This is a special mode that allows "prefix" commands, where the parsing
completely stops when it gets to an unknown option. Further unknown options are
ignored, even if they could match. Git is the traditional example for prefix
commands; if you run git with an unknown subcommand, like "`git thing`", it then
calls another command called "`git-thing`" with the remaining options intact.
### Silent subcommands
Subcommands can be modified by using the `silent` option. This will prevent the subcommand from showing up in the get_subcommands list. This can be used to make subcommands into modifiers. For example, a help subcommand might look like
Subcommands can be modified by using the `silent` option. This will prevent the
subcommand from showing up in the get_subcommands list. This can be used to make
subcommands into modifiers. For example, a help subcommand might look like
```c++
auto sub1 = app.add_subcommand("help")->silent();
@ -131,11 +163,19 @@ This would allow calling help such as:
### Positional Validation
Some arguments supplied on the command line may be legitamately applied to more than 1 positional argument. In this context enabling `positional_validation` on the application or subcommand will check any validators before applying the command line argument to the positional option. It is not an error to fail validation in this context, positional arguments not matching any validators will go into the `extra_args` field which may generate an error depending on settings.
Some arguments supplied on the command line may be legitamately applied to more
than 1 positional argument. In this context enabling `positional_validation` on
the application or subcommand will check any validators before applying the
command line argument to the positional option. It is not an error to fail
validation in this context, positional arguments not matching any validators
will go into the `extra_args` field which may generate an error depending on
settings.
### Optional Argument Validation
Similar to positional validation, there are occasional contexts in which case it might be ambiguous whether an argument should be applied to an option or a positional option.
Similar to positional validation, there are occasional contexts in which case it
might be ambiguous whether an argument should be applied to an option or a
positional option.
```c++
std::vector<std::string> vec;
@ -145,4 +185,10 @@ Similar to positional validation, there are occasional contexts in which case it
app.validate_optional_arguments();
```
In this case a sequence of integers is expected for the argument and remaining strings go to the positional string vector. Without the `validate_optional_arguments()` active it would be impossible get any later arguments into the positional if the `--args` option is used. The validator in this context is used to make sure the optional arguments match with what the argument is expecting and if not the `-args` option is closed, and remaining arguments fall into the positional.
In this case a sequence of integers is expected for the argument and remaining
strings go to the positional string vector. Without the
`validate_optional_arguments()` active it would be impossible get any later
arguments into the positional if the `--args` option is used. The validator in
this context is used to make sure the optional arguments match with what the
argument is expecting and if not the `-args` option is closed, and remaining
arguments fall into the positional.

View File

@ -1,12 +1,18 @@
# Using CLI11 in a Toolkit
CLI11 was designed to be integrate into a toolkit, providing a native experience for users. This was used in GooFit to provide `GooFit::Application`, an class designed to make ROOT users feel at home.
CLI11 was designed to be integrate into a toolkit, providing a native experience
for users. This was used in GooFit to provide `GooFit::Application`, an class
designed to make ROOT users feel at home.
## Custom namespace
If you want to provide CLI11 in a custom namespace, you'll want to at least put `using CLI::App` in your namespace. You can also include Option, some errors, and validators. You can also put `using namespace CLI` inside your namespace to import everything.
If you want to provide CLI11 in a custom namespace, you'll want to at least put
`using CLI::App` in your namespace. You can also include Option, some errors,
and validators. You can also put `using namespace CLI` inside your namespace to
import everything.
You may also want to make your own copy of the `CLI11_PARSE` macro. Something like:
You may also want to make your own copy of the `CLI11_PARSE` macro. Something
like:
```cpp
#define MYPACKAGE_PARSE(app, argv, argc) \
@ -19,10 +25,16 @@ You may also want to make your own copy of the `CLI11_PARSE` macro. Something li
## Subclassing App
If you subclass `App`, you'll just need to do a few things. You'll need a constructor; calling the base `App` constructor is a good idea, but not necessary (it just sets a description and adds a help flag.
If you subclass `App`, you'll just need to do a few things. You'll need a
constructor; calling the base `App` constructor is a good idea, but not
necessary (it just sets a description and adds a help flag.
You can call anything you would like to configure in the constructor, like `option_defaults()->take_last()` or `fallthrough()`, and it will be set on all user instances. You can add flags and options, as well.
You can call anything you would like to configure in the constructor, like
`option_defaults()->take_last()` or `fallthrough()`, and it will be set on all
user instances. You can add flags and options, as well.
## Virtual functions provided
You are given a few virtual functions that you can change (only on the main App). `pre_callback` runs right before the callbacks run, letting you print out custom messages at the top of your app.
You are given a few virtual functions that you can change (only on the main
App). `pre_callback` runs right before the callbacks run, letting you print out
custom messages at the top of your app.

View File

@ -3,22 +3,26 @@
There are two forms of validators:
- `transform` validators: mutating
- `check` validators: non-mutating (recommended unless the parsed string must be mutated)
- `check` validators: non-mutating (recommended unless the parsed string must be
mutated)
A transform validator comes in one form, a function with the signature `std::string(std::string)`.
The function will take a string and return the modified version of the string. If there is an error,
the function should throw a `CLI::ValidationError` with the appropriate reason as a message.
A transform validator comes in one form, a function with the signature
`std::string(std::string)`. The function will take a string and return the
modified version of the string. If there is an error, the function should throw
a `CLI::ValidationError` with the appropriate reason as a message.
However, `check` validators come in two forms; either a simple function with the const version of the
above signature, `std::string(const std::string &)`, or a subclass of `struct CLI::Validator`. This
structure has two members that a user should set; one (`func_`) is the function to add to the Option
(exactly matching the above function signature, since it will become that function), and the other is
`name_`, and is the type name to set on the Option (unless empty, in which case the typename will be
left unchanged).
However, `check` validators come in two forms; either a simple function with the
const version of the above signature, `std::string(const std::string &)`, or a
subclass of `struct CLI::Validator`. This structure has two members that a user
should set; one (`func_`) is the function to add to the Option (exactly matching
the above function signature, since it will become that function), and the other
is `name_`, and is the type name to set on the Option (unless empty, in which
case the typename will be left unchanged).
Validators can be combined with `&` and `|`, and they have an `operator()` so that you can call them
as if they were a function. In CLI11, const static versions of the validators are provided so that
the user does not have to call a constructor also.
Validators can be combined with `&` and `|`, and they have an `operator()` so
that you can call them as if they were a function. In CLI11, const static
versions of the validators are provided so that the user does not have to call a
constructor also.
An example of a custom validator:
@ -37,7 +41,8 @@ struct LowerCaseValidator : public Validator {
const static LowerCaseValidator Lowercase;
```
If you were not interested in the extra features of Validator, you could simply pass the lambda function above to the `->check()` method of `Option`.
If you were not interested in the extra features of Validator, you could simply
pass the lambda function above to the `->check()` method of `Option`.
The built-in validators for CLI11 are:

View File

@ -1,6 +1,8 @@
# Introduction {#mainpage}
This is the Doxygen API documentation for CLI11 parser. There is a friendly introduction to CLI11 on the [GitHub page](https://github.com/CLIUtils/CLI11), and [a tutorial series](https://cliutils.github.io/CLI11/book/).
This is the Doxygen API documentation for CLI11 parser. There is a friendly
introduction to CLI11 on the [GitHub page](https://github.com/CLIUtils/CLI11),
and [a tutorial series](https://cliutils.github.io/CLI11/book/).
The main classes are: