Update changelog (#383)

* Update changelog

[skip ci]

* Use code for maintainers instead

* Generate file with GitHub Actions

* Apply suggestions from code review

Co-Authored-By: Philip Top <phlptp@gmail.com>

* Adding default val and combine one line

Co-authored-by: Philip Top <top1@llnl.gov>
This commit is contained in:
Henry Schreiner 2020-01-02 17:38:44 -05:00 committed by GitHub
parent 5b17abf22f
commit 59052a6b27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 129 additions and 49 deletions

View File

@ -16,7 +16,9 @@
"avatar_url": "https://avatars1.githubusercontent.com/u/4616906?v=4",
"profile": "http://iscinumpy.gitlab.io",
"contributions": [
"maintenance"
"bug",
"doc",
"code"
]
},
{
@ -25,7 +27,9 @@
"avatar_url": "https://avatars0.githubusercontent.com/u/20667153?v=4",
"profile": "https://github.com/phlptp",
"contributions": [
"maintenance"
"bug",
"doc",
"code"
]
},
{

View File

@ -66,3 +66,6 @@ yarn add --dev all-contributors-cli
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.

36
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: Build
on:
push:
branches:
- master
- v*
tags:
- "*"
pull_request:
branches:
- master
jobs:
single-header:
name: Single header
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
- name: Make header
run: python ./scripts/MakeSingleHeader.py CLI11.hpp
- uses: actions/upload-artifact@v1
with:
name: CLI11.hpp
path: CLI11.hpp
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: CLI11.hpp
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -106,15 +106,6 @@ deploy:
on:
branch: master
condition: "$DEPLOY_MAT = yes"
- provider: releases
api_key:
secure: L1svZ5J+RiR67dj1fNk/XiZRvYfGJC4c5/dKSvDH+yuKSzZ6ODaTiVmYF8NtMJ7/3AQenEa0OuRBVQ0YpngFz3ugIcRsGCDUHtCMK/Bti0+6ZFdICbqcv6W3BlRIM8s7EOBPhjfbCV+ae7xep9B24HmwBPKukMFjDIj4nwBsmwCHZK9iNFtfaW2J2cr2TJo7QPY01J0W1k/boaj91KzHf9UuhEH8KYqp7szv+6kV00W8bRBtugw419dIm25eXFXgXDT9s/OA7qXV7o5FXWWpkyJ5AINVbY9DerkYag5TStrdOyKk+S1FexRG6TMG4L4Jyu/QxQGhMdu0m1yRCLvIekGtWLDnjNrI2SZrd5HbKprQ0O8j1770Is4q5blVPqAZ6O9jVMJRtVEaYbsJwItz1BJWkPT4S9GFbDL1dq2Z5jR2f5gd/cz2yYH56b47iYHWtzSqEfVhsXiN+atD+tWyQFA4Q/av0bGHwJ6LX0A1q0OCHruUMoxcw1QKfYtV1bkf/folL4Z4Hx3CL+NB0Lkqs8LFsQHxODP4a26I5DS/kaDHofotho8wsWlKFDtonZa+CExORGFFMPnGRz2qX5tMgGoo84wcqrprfoQv2llqeUr3gISPl2qxrljAhj3/Dcl7iI7k0Er7Ji8ENpgjSec4aqnBx8Ke2yaDEmBvwbouFCM=
skip_cleanup: true
file: build/include/CLI11.hpp
on:
repo: CLIUtils/CLI11
tags: true
condition: "$DEPLOY_MAT = yes"
notifications:
webhooks:

View File

@ -1,13 +1,45 @@
## Version 1.9: IN PROGRESS
## Version 1.9: Config files and cleanup
* The meson build system supported [#299][]
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.
* 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][]
* `app.immediate_callback()` allows the main app to run before subcommand callbacks. [#292][]
* GCC 4.7 is no longer supported, due mostly to GoogleTest. GCC 4.8+ is now required. [#160][]
* `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][]
* Transform now supports arrays [#349][]
* Option groups can be hidden [#356][]
* Add `CLI::deprecate_option` and `CLI::retire_option` functions [#358][]
* More flexible and safer Option `default_val` [#387][]
* Backend: Cleaner type traits [#286][]
* Backend: File checking updates [#341][]
* Backend: Using pre-commit to format, checked in GitHub Actions [#336][]
* Backend: Warning cleanup, more checks from klocwork [#350][], Effective C++ [#354][], clang-tidy [#360][], CUDA NVCC [#365][], cross compile [#373][], and sign conversion [#382][]
* 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][]
> ### Converting from CLI11 1.8:
>
> * Some deprecated methods dropped
> - `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
[#160]: https://github.com/CLIUtils/CLI11/pull/160
[#285]: https://github.com/CLIUtils/CLI11/pull/285
@ -16,6 +48,34 @@
[#292]: https://github.com/CLIUtils/CLI11/pull/292
[#299]: https://github.com/CLIUtils/CLI11/pull/299
[#300]: https://github.com/CLIUtils/CLI11/pull/300
[#301]: https://github.com/CLIUtils/CLI11/pull/301
[#304]: https://github.com/CLIUtils/CLI11/pull/304
[#306]: https://github.com/CLIUtils/CLI11/pull/306
[#307]: https://github.com/CLIUtils/CLI11/pull/307
[#309]: https://github.com/CLIUtils/CLI11/pull/309
[#310]: https://github.com/CLIUtils/CLI11/pull/310
[#312]: https://github.com/CLIUtils/CLI11/pull/312
[#313]: https://github.com/CLIUtils/CLI11/pull/313
[#317]: https://github.com/CLIUtils/CLI11/pull/317
[#318]: https://github.com/CLIUtils/CLI11/pull/318
[#320]: https://github.com/CLIUtils/CLI11/pull/320
[#325]: https://github.com/CLIUtils/CLI11/pull/325
[#333]: https://github.com/CLIUtils/CLI11/pull/333
[#336]: https://github.com/CLIUtils/CLI11/pull/336
[#342]: https://github.com/CLIUtils/CLI11/pull/342
[#348]: https://github.com/CLIUtils/CLI11/pull/348
[#349]: https://github.com/CLIUtils/CLI11/pull/349
[#350]: https://github.com/CLIUtils/CLI11/pull/350
[#354]: https://github.com/CLIUtils/CLI11/pull/354
[#356]: https://github.com/CLIUtils/CLI11/pull/356
[#358]: https://github.com/CLIUtils/CLI11/pull/358
[#360]: https://github.com/CLIUtils/CLI11/pull/360
[#362]: https://github.com/CLIUtils/CLI11/pull/362
[#365]: https://github.com/CLIUtils/CLI11/pull/365
[#373]: https://github.com/CLIUtils/CLI11/pull/373
[#374]: https://github.com/CLIUtils/CLI11/pull/374
[#382]: https://github.com/CLIUtils/CLI11/pull/382
## Version 1.8: Transformers, default strings, and flags
@ -508,4 +568,3 @@ 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.

View File

@ -63,10 +63,10 @@ Features that were added in the last released major version are marked with "
### Introduction
CLI11 provides all the features you expect in a powerful command line parser, with a beautiful, minimal syntax and no dependencies beyond C++11. It is header only, and comes in a single file form for easy inclusion in projects. It is easy to use for small projects, but powerful enough for complex command line projects, and can be customized for frameworks.
It is tested on [Travis][], [AppVeyor][], and [Azure][], and is being included in the [GooFit GPU fitting framework][goofit]. It was inspired by [`plumbum.cli`][plumbum] for Python. CLI11 has a user friendly introduction in this README, a more in-depth tutorial [GitBook][], as well as [API documentation][api-docs] generated by Travis.
It is tested on [Travis][], [AppVeyor][], [Azure][], and [GitHub Actions][actions-link], and is used by the [GooFit GPU fitting framework][goofit]. It was inspired by [`plumbum.cli`][plumbum] for Python. CLI11 has a user friendly introduction in this README, a more in-depth tutorial [GitBook][], as well as [API documentation][api-docs] generated by Travis.
See the [changelog](./CHANGELOG.md) or [GitHub Releases][] for details for current and past releases. Also see the [Version 1.0 post][], [Version 1.3 post][], or [Version 1.6 post][] for more information.
You can be notified when new releases are made by subscribing to <https://github.com/CLIUtils/CLI11/releases.atom> on an RSS reader, like Feedly, or use the releases mode of the github watching tool.
You can be notified when new releases are made by subscribing to <https://github.com/CLIUtils/CLI11/releases.atom> on an RSS reader, like Feedly, or use the releases mode of the GitHub watching tool.
### Why write another CLI parser?
@ -106,13 +106,13 @@ After I wrote this, I also found the following libraries:
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [GFlags][] | The Google Commandline Flags library. Uses macros heavily, and is limited in scope, missing things like subcommands. It provides a simple syntax and supports config files/env vars. |
| [GetOpt][] | Very limited C solution with long, convoluted syntax. Does not support much of anything, like help generation. Always available on UNIX, though (but in different flavors). |
| [ProgramOptions.hxx][] | Interesting library, less powerful and no subcommands. Nice callback system. |
| [ProgramOptions.hxx][] | Interesting library, less powerful and no subcommands. Nice callback system. |
| [Args][] | Also interesting, and supports subcommands. I like the optional-like design, but CLI11 is cleaner and provides direct value access, and is less verbose. |
| [Argument Aggregator][] | I'm a big fan of the [fmt][] library, and the try-catch statement looks familiar. :thumbsup: Doesn't seem to support subcommands. |
| [Clara][] | Simple library built for the excellent [Catch][] testing framework. Unique syntax, limited scope. |
| [Argh!][] | Very minimalistic C++11 parser, single header. Don't have many features. No help generation?!?! At least it's exception-free. |
| [CLI][] | Custom language and parser. Huge build-system overkill for very little benefit. Last release in 2009, but still occasionally active. |
| [argparse][] | C++17 single file argument parser. Design seems similar to CLI11 in some ways. |
| [CLI][] | Custom language and parser. Huge build-system overkill for very little benefit. Last release in 2009, but still occasionally active. |
| [argparse][] | C++17 single file argument parser. Design seems similar to CLI11 in some ways. The author has several other interesting projects. |
See [Awesome C++][] for a less-biased list of parsers. You can also find other single file libraries at [Single file libs][].
@ -195,7 +195,7 @@ While all options internally are the same type, there are several ways to add an
app.add_option(option_name, help_str="") // 🆕
app.add_option(option_name,
variable_to_bind_to, // bool, int, float, vector, 🆕 enum, or string-like, or anything with a defined conversion from a string or that takes an int🚧, double🚧, or string in a constructor. Also allowed are tuples🚧,std::array🚧 or std::pair🚧.
variable_to_bind_to, // bool, int, float, vector, 🆕 enum, or string-like, or anything with a defined conversion from a string or that takes an int 🚧, double 🚧, or string in a constructor. Also allowed are tuples 🚧, std::array 🚧 or std::pair 🚧.
help_string="")
app.add_option_function<type>(option_name,
@ -203,7 +203,7 @@ app.add_option_function<type>(option_name,
help_string="")
app.add_complex(... // Special case: support for complex numbers
//🚧There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type. The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version. If XC is a std::pair and T is some non pair type. Then a two argument constructor for T is called to assign the value. For tuples or other multi element types, XC must be a single type or a tuple like object of the same size as the assignment type
// 🚧 There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type. The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version. If XC is a std::pair and T is some non pair type. Then a two argument constructor for T is called to assign the value. For tuples or other multi element types, XC must be a single type or a tuple like object of the same size as the assignment type
app.add_option<typename T, typename XC>(option_name,
T &output, // output must be assignable or constructible from a value of type XC
help_string="")
@ -226,19 +226,6 @@ app.add_flag_callback(option_name,function<void(void)>,help_string="") // 🆕
App* subcom = app.add_subcommand(name, description);
Option_group *app.add_option_group(name,description); // 🆕
// ⚠️ All add_*set* methods deprecated in CLI11 1.8 - use ->transform(CLI::IsMember) instead
-app.add_set(option_name,
- variable_to_bind_to, // Same type as stored by set
- set_of_possible_options, // Set will be copied, ignores changes
- help_string="")
-app.add_mutable_set(... // Set can change later, keeps reference
-app.add_set_ignore_case(... // String only
-app.add_mutable_set_ignore_case(... // String only
-app.add_set_ignore_underscore(... // String only
-app.add_mutable_set_ignore_underscore(... // String only
-app.add_set_ignore_case_underscore(... // String only
-app.add_mutable_set_ignore_case_underscore(... // String only
```
An option name must start with a alphabetic character, underscore, a number 🆕, '?' 🆕, or '@' 🆕. For long options, after the first character '.', and '-' are also valid characters. For the `add_flag*` functions '{' has special meaning. Names are given as a comma separated string, with the dash or dashes. An option or flag 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.
@ -258,7 +245,7 @@ app.add_option<vtype,std:string>("--vs",v1);
app.add_option<vtype,int>("--vi",v1);
app.add_option<vtype,double>("--vf",v1);
```
otherwise the output would default to a string. The add_option can be used with any integral or floating point types, enumerations, or strings. Or any type that takes an int, double, or std::string in an assignment operator or constructor. If an object can take multiple varieties of those, std::string takes precedence, then double then int. To better control which one is used or to use another type for the underlying conversions use the two parameter template to directly specify the conversion type.
otherwise the output would default to a string. The `add_option` can be used with any integral or floating point types, enumerations, or strings. Or any type that takes an int, double, or std::string in an assignment operator or constructor. If an object can take multiple varieties of those, std::string takes precedence, then double then int. To better control which one is used or to use another type for the underlying conversions use the two parameter template to directly specify the conversion type.
Types such as (std or boost) `optional<int>`, `optional<double>`, and `optional<string>` are supported directly, other optional types can be added using the two parameter template. See [CLI11 Advanced Topics/Custom Converters][] for information on how this could be done and how you can add your own converters for additional types.
@ -323,7 +310,7 @@ Before parsing, you can set the following options:
- `->description(str)`: Set/change the description.
- `->multi_option_policy(CLI::MultiOptionPolicy::Throw)`: Set the multi-option policy. Shortcuts available: `->take_last()`, `->take_first()`, and `->join()`. This will only affect options expecting 1 argument or bool flags (which do not inherit their default but always start with a specific policy).
- `->check(std::string(const std::string &), validator_name="",validator_description="")`: 🆕 Define a check function. The function should return a non empty string with the error message if the check fails
- `->check(Validator)`:🆕 Use a Validator object to do the check see [Validators](#validators) for a description of available Validators and how to create new ones.
- `->check(Validator)`: 🆕 Use a Validator object to do the check see [Validators](#validators) for a description of available Validators and how to create new ones.
- `->transform(std::string(std::string &), validator_name="",validator_description=")`: Converts the input string into the output string, in-place in the parsed options.
- `->transform(Validator)`: uses a Validator object to do the transformation see [Validators](#validators) for a description of available Validators and how to create new ones.
- `->each(void(const std::string &)>`: Run this function on each value received, as it is received. It should throw a `ValidationError` if an error is encountered.
@ -376,7 +363,7 @@ CLI11 has several Validators built-in that perform some common checks
- `CLI::IsMember(...)`: 🆕 Require an option be a member of a given set. See [Transforming Validators](#transforming-validators) for more details.
- `CLI::Transformer(...)`: 🆕 Modify the input using a map. See [Transforming Validators](#transforming-validators) for more details.
- `CLI::CheckedTransformer(...)`: 🆕 Modify the input using a map, and require that the input is either in the set or already one of the outputs of the set. See [Transforming Validators](#transforming-validators) for more details.
- `CLI::AsNumberWithUnit(...)`:🆕 Modify the `<NUMBER> <UNIT>` pair by matching the unit and multiplying the number by the corresponding factor. It can be used as a base for transformers, that accept things like size values (`1 KB`) or durations (`0.33 ms`).
- `CLI::AsNumberWithUnit(...)`: 🆕 Modify the `<NUMBER> <UNIT>` pair by matching the unit and multiplying the number by the corresponding factor. It can be used as a base for transformers, that accept things like size values (`1 KB`) or durations (`0.33 ms`).
- `CLI::AsSizeValue(...)`: 🆕 Convert inputs like `100b`, `42 KB`, `101 Mb`, `11 Mib` to absolute values. `KB` can be configured to be interpreted as 10^3 or 2^10.
- `CLI::ExistingFile`: Requires that the file exists if given.
- `CLI::ExistingDirectory`: Requires that the directory exists.
@ -440,7 +427,7 @@ NOTES: If the container used in `IsMember`, `Transformer`, or `CheckedTransform
Validators are copyable and have a few operations that can be performed on them to alter settings. Most of the built in Validators have a default description that is displayed in the help. This can be altered via `.description(validator_description)`.
The name of a Validator, which is useful for later reference from the `get_validator(name)` method of an `Option` can be set via `.name(validator_name)`
The operation function of a Validator can be set via
`.operation(std::function<std::string(std::string &>)`. The `.active()` function can activate or deactivate a Validator from the operation. A validator can be set to apply only to a specific element of the output. For example in a pair option `std::pair<int, std::string>` the first element may need to be a positive integer while the second may need to be a valid file. The `.application_index(int)` 🚧function can specify this. It is zero based and negative indices apply to all values.
`.operation(std::function<std::string(std::string &>)`. The `.active()` function can activate or deactivate a Validator from the operation. A validator can be set to apply only to a specific element of the output. For example in a pair option `std::pair<int, std::string>` the first element may need to be a positive integer while the second may need to be a valid file. The `.application_index(int)` 🚧 function can specify this. It is zero based and negative indices apply to all values.
```cpp
opt->check(CLI::Validator(CLI::PositiveNumber).application_index(0));
opt->check(CLI::Validator(CLI::ExistingFile).application_index(1));
@ -561,7 +548,7 @@ There are several options that are supported on the main app and subcommands and
- `.formatter(fmt)`: Set a formatter, with signature `std::string(const App*, std::string, AppFormatMode)`. See Formatting for more details.
- `.description(str)`: Set/change the description.
- `.get_description()`: Access the description.
- `.alias(str)`:🚧 set an alias for the subcommand, this allows subcommands to be called by more than one name.
- `.alias(str)`: 🚧 set an alias for the subcommand, this allows subcommands to be called by more than one name.
- `.parsed()`: True if this subcommand was given on the command line.
- `.count()`: Returns the number of times the subcommand was called.
- `.count(option_name)`: Returns the number of times a particular option was called.
@ -588,7 +575,7 @@ There are several options that are supported on the main app and subcommands and
#### Callbacks
A subcommand has three optional callbacks that are executed at different stages of processing. The `preparse_callback` 🆕 is executed once after the first argument of a subcommand or application is processed and gives an argument for the number of remaining arguments to process. For the main app the first argument is considered the program name, for subcommands the first argument is the subcommand name. For Option groups and nameless subcommands the first argument is after the first argument or subcommand is processed from that group.
The second callback is executed after parsing. This is known as the `parse_complete_callback`. For subcommands this is executed immediately after parsing and can be executed multiple times if a subcommand is called multiple times. On the main app this callback is executed after all the `parse_complete_callback`s for the subcommands are executed but prior to any `final_callback` calls in the subcommand or option groups. If the main app or subcommand has a config file, no data from the config file will be reflected in `parse_complete_callback` on named subcommands 🚧. For option_groups the `parse_complete_callback` is executed prior to the `parse_complete_callback` on the main app but after the config_file is loaded(if specified). The 🚧 `final_callback` is executed after all processing is complete. After the `parse_complete_callback` is executed on the main app, the used subcommand `final_callback` are executed followed by the 'final callback' for option groups. The last thing to execute is the `final_callback` for the main_app.
The second callback is executed after parsing. This is known as the `parse_complete_callback`. For subcommands this is executed immediately after parsing and can be executed multiple times if a subcommand is called multiple times. On the main app this callback is executed after all the `parse_complete_callback`s for the subcommands are executed but prior to any `final_callback` calls in the subcommand or option groups. If the main app or subcommand has a config file, no data from the config file will be reflected in `parse_complete_callback` on named subcommands 🚧. For `option_group`s the `parse_complete_callback` is executed prior to the `parse_complete_callback` on the main app but after the `config_file` is loaded (if specified). The 🚧 `final_callback` is executed after all processing is complete. After the `parse_complete_callback` is executed on the main app, the used subcommand `final_callback` are executed followed by the "final callback" for option groups. The last thing to execute is the `final_callback` for the `main_app`.
For example say an application was set up like
```cpp
@ -620,8 +607,8 @@ program --opt1 opt1_val sub1 --sub1opt --sub1optb val sub2 --sub2opt sub1 --sub
A subcommand is considered terminated when one of the following conditions are met.
1. There are no more arguments to process
2. Another subcommand is encountered that would not fit in an optional slot of the subcommand
3. The positional_mark(`--`) is encountered and there are no available positional slots in the subcommand.
4. The subcommand_terminator mark(`++`) is encountered
3. The `positional_mark` (`--`) is encountered and there are no available positional slots in the subcommand.
4. The `subcommand_terminator` mark (`++`) is encountered
Prior to executed a `parse_complete_callback` all contained options are processed before the callback is triggered. If a subcommand with a `parse_complete_callback` is called again, then the contained options are reset, and can be triggered again.
@ -661,9 +648,9 @@ CLI::TriggerOn(group1_pointer, triggered_group);
CLI::TriggerOff(group2_pointer, disabled_group);
```
These functions make use of `preparse_callback`, `enabled_by_default()` and `disabled_by_default`. The triggered group may be a vector of group pointers. These methods should only be used once per group and will override any previous use of the underlying functions. More complex arrangements can be accomplished using similar methodology with a custom preparse_callback function that does more.
These functions make use of `preparse_callback`, `enabled_by_default()` and `disabled_by_default`. The triggered group may be a vector of group pointers. These methods should only be used once per group and will override any previous use of the underlying functions. More complex arrangements can be accomplished using similar methodology with a custom `preparse_callback` function that does more.
Additional helper functions `deprecate_option`🚧 and `retire_option`🚧 are available to deprecate or retire options
Additional helper functions `deprecate_option` 🚧 and `retire_option` 🚧 are available to deprecate or retire options
```cpp
CLI::deprecate_option(option *, replacement_name="");
CLI::deprecate_option(App,option_name,replacement_name="");
@ -876,8 +863,8 @@ This project was created by [Henry Schreiner](https://github.com/henryiii) and m
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="http://iscinumpy.gitlab.io"><img src="https://avatars1.githubusercontent.com/u/4616906?v=4" width="100px;" alt=""/><br /><sub><b>Henry Schreiner</b></sub></a><br /><a href="#maintenance-henryiii" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/phlptp"><img src="https://avatars0.githubusercontent.com/u/20667153?v=4" width="100px;" alt=""/><br /><sub><b>Philip Top</b></sub></a><br /><a href="#maintenance-phlptp" title="Maintenance">🚧</a></td>
<td align="center"><a href="http://iscinumpy.gitlab.io"><img src="https://avatars1.githubusercontent.com/u/4616906?v=4" width="100px;" alt=""/><br /><sub><b>Henry Schreiner</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Ahenryiii" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=henryiii" title="Documentation">📖</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=henryiii" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/phlptp"><img src="https://avatars0.githubusercontent.com/u/20667153?v=4" width="100px;" alt=""/><br /><sub><b>Philip Top</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Aphlptp" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=phlptp" title="Documentation">📖</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=phlptp" title="Code">💻</a></td>
<td align="center"><a href="https://www.linkedin.com/in/cbachhuber/"><img src="https://avatars0.githubusercontent.com/u/27212661?v=4" width="100px;" alt=""/><br /><sub><b>Christoph Bachhuber</b></sub></a><br /><a href="#example-cbachhuber" title="Examples">💡</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=cbachhuber" title="Code">💻</a></td>
<td align="center"><a href="https://lambdafu.net/"><img src="https://avatars1.githubusercontent.com/u/1138455?v=4" width="100px;" alt=""/><br /><sub><b>Marcus Brinkmann</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Alambdafu" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=lambdafu" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/SkyToGround"><img src="https://avatars1.githubusercontent.com/u/58835?v=4" width="100px;" alt=""/><br /><sub><b>Jonas Nilsson</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3ASkyToGround" title="Bug reports">🐛</a> <a href="https://github.com/CLIUtils/CLI11/commits?author=SkyToGround" title="Code">💻</a></td>
@ -938,7 +925,7 @@ CLI11 was developed at the [University of Cincinnati][] to support of the [GooFi
[azure]: https://dev.azure.com/CLIUtils/CLI11/_build/latest?definitionId=1&branchName=master
[travis-badge]: https://img.shields.io/travis/CLIUtils/CLI11/master.svg?label=Linux/macOS
[travis]: https://travis-ci.org/CLIUtils/CLI11
[appveyor-badge]: https://img.shields.io/appveyor/ci/HenrySchreiner/cli11/master.svg?label=Windows
[appveyor-badge]: https://img.shields.io/appveyor/ci/HenrySchreiner/cli11/master.svg?label=AppVeyor
[appveyor]: https://ci.appveyor.com/project/HenrySchreiner/cli11
[actions-badge]: https://github.com/CLIUtils/CLI11/workflows/Tests/badge.svg
[actions-link]: https://github.com/CLIUtils/CLI11/actions