diff --git a/README.md b/README.md index d00e06f5..4666fc29 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,10 @@ int main(int argc, char** argv) { } ``` -For more information about `ensure_utf8` the section on +When adding options the names should not conflict with each other, if an option +is added, or a modifier changed that would cause naming conflicts a run time +error will be thrown in the add_option method. This includes default options for +help `-h, --help`. For more information about `ensure_utf8` the section on [Unicode support](#unicode-support) below.
Note: If you don't like macros, this is what that macro expands to: (click to expand)

@@ -500,6 +503,34 @@ Before parsing, you can set the following options: validation checks for the option to be executed when the option value is parsed vs. at the end of all parsing. This could cause the callback to be executed multiple times. Also works with positional options. +- `->callback_priority(CallbackPriority priority)`: 🚧 changes the order in + which the option callback is executed. Four principal callback call-points + are available. `CallbackPriority::First` executes at the very beginning of + processing, before configuration files are read and environment variables are + interpreted. `CallbackPriority::PreRequirementsCheck` executes after + configuration and environment processing but before requirements checking. + `CallbackPriority::Normal` executes after the requirements check but before + any previously potentially raised exceptions are re-thrown. + `CallbackPriority::Last` executes after exception handling is completed. + For each position, both ordinary option callbacks and help callbacks are + invoked. The relative order between them can be controlled using the + corresponding `PreHelp` variants. `CallbackPriority::FirstPreHelp` executes + ordinary option callbacks before help callbacks at the very beginning of + processing. `CallbackPriority::PreRequirementsCheckPreHelp` executes ordinary + option callbacks before help callbacks after configuration and environment + processing but before requirements checking. `CallbackPriority::NormalPreHelp` + executes ordinary option callbacks before help callbacks after the + requirements check but before exception re-throwing. + `CallbackPriority::LastPreHelp` executes ordinary option callbacks before help + callbacks after exception handling has completed. When using the standard + priorities (`CallbackPriority::First`, + `CallbackPriority::PreRequirementsCheck`, `CallbackPriority::Normal`, + `CallbackPriority::Last`), help callbacks are executed before ordinary option + callbacks. By default, help callbacks use `CallbackPriority::First`, and + ordinary option callbacks use `CallbackPriority::Normal`. This mechanism + provides fine-grained control over when option values are set and when help or + requirement checks occur, enabling precise customization of the processing + sequence. These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. The `each` function takes any function @@ -639,7 +670,7 @@ setting `CLI11_ENABLE_EXTRA_VALIDATORS` to 1 write permission. Requires C++17. - `CLI::ExecPermission`: Requires that the file given exist and have execution permission. Requires C++17. -- + - #### Validator Usage diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index d35e9b9d..b369a3f8 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -1303,12 +1303,12 @@ class App { void _process_env(); /// Process callbacks. Runs on *all* subcommands. - void _process_callbacks(); + void _process_callbacks(CallbackPriority priority); /// Run help flag processing if any are found. /// /// The flags allow recursive calls to remember if there was a help flag on a parent. - void _process_help_flags(bool trigger_help = false, bool trigger_all_help = false) const; + void _process_help_flags(CallbackPriority priority, bool trigger_help = false, bool trigger_all_help = false) const; /// Verify required options and cross requirements. Subcommands too (only if selected). void _process_requirements(); diff --git a/include/CLI/Option.hpp b/include/CLI/Option.hpp index da6ee41e..3522df20 100644 --- a/include/CLI/Option.hpp +++ b/include/CLI/Option.hpp @@ -50,6 +50,18 @@ enum class MultiOptionPolicy : char { Reverse, //!< take only the last Expected number of arguments in reverse order }; +/// @brief enumeration for the callback priority +enum class CallbackPriority : std::uint8_t { + FirstPreHelp = 0, + First = 1, + PreRequirementsCheckPreHelp = 2, + PreRequirementsCheck = 3, + NormalPreHelp = 4, + Normal = 5, + LastPreHelp = 6, + Last = 7 +}; // namespace CLI + /// This is the CRTP base class for Option and OptionDefaults. It was designed this way /// to share parts of the class; an OptionDefaults can copy to an Option. template class OptionBase { @@ -84,6 +96,9 @@ template class OptionBase { /// Policy for handling multiple arguments beyond the expected Max MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw}; + /// Priority of callback + CallbackPriority callback_priority_{CallbackPriority::Normal}; + /// Copy the contents to another similar class (one based on OptionBase) template void copy_to(T *other) const; @@ -142,6 +157,9 @@ template class OptionBase { /// The status of the multi option policy CLI11_NODISCARD MultiOptionPolicy get_multi_option_policy() const { return multi_option_policy_; } + /// The priority of callback + CLI11_NODISCARD CallbackPriority get_callback_priority() const { return callback_priority_; } + // Shortcuts for multi option policy /// Set the multi option policy to take last @@ -201,6 +219,12 @@ class OptionDefaults : public OptionBase { // Methods here need a different implementation if they are Option vs. OptionDefault + /// Set the callback priority + OptionDefaults *callback_priority(CallbackPriority value = CallbackPriority::Normal) { + callback_priority_ = value; + return this; + } + /// Take the last argument if given multiple times OptionDefaults *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) { multi_option_policy_ = value; @@ -343,7 +367,6 @@ class Option : public OptionBase