@@ -285,7 +285,7 @@ CLI11_INLINE Option *App::set_help_flag(std::string flag_name, const std::string
285285 // Empty name will simply remove the help flag
286286 if (!flag_name.empty ()) {
287287 help_ptr_ = add_flag (flag_name, help_description);
288- help_ptr_->configurable (false );
288+ help_ptr_->configurable (false )-> callback_priority (CallbackPriority::First) ;
289289 }
290290
291291 return help_ptr_;
@@ -301,7 +301,7 @@ CLI11_INLINE Option *App::set_help_all_flag(std::string help_name, const std::st
301301 // Empty name will simply remove the help all flag
302302 if (!help_name.empty ()) {
303303 help_all_ptr_ = add_flag (help_name, help_description);
304- help_all_ptr_->configurable (false );
304+ help_all_ptr_->configurable (false )-> callback_priority (CallbackPriority::First) ;
305305 }
306306
307307 return help_all_ptr_;
@@ -319,7 +319,7 @@ App::set_version_flag(std::string flag_name, const std::string &versionString, c
319319 if (!flag_name.empty ()) {
320320 version_ptr_ = add_flag_callback (
321321 flag_name, [versionString]() { throw (CLI::CallForVersion (versionString, 0 )); }, version_help);
322- version_ptr_->configurable (false );
322+ version_ptr_->configurable (false )-> callback_priority (CallbackPriority::First) ;
323323 }
324324
325325 return version_ptr_;
@@ -336,7 +336,7 @@ App::set_version_flag(std::string flag_name, std::function<std::string()> vfunc,
336336 if (!flag_name.empty ()) {
337337 version_ptr_ =
338338 add_flag_callback (flag_name, [vfunc]() { throw (CLI::CallForVersion (vfunc (), 0 )); }, version_help);
339- version_ptr_->configurable (false );
339+ version_ptr_->configurable (false )-> callback_priority (CallbackPriority::First) ;
340340 }
341341
342342 return version_ptr_;
@@ -1239,43 +1239,48 @@ CLI11_INLINE void App::_process_env() {
12391239 }
12401240}
12411241
1242- CLI11_INLINE void App::_process_callbacks () {
1242+ CLI11_INLINE void App::_process_callbacks (CallbackPriority priority ) {
12431243
12441244 for (App_p &sub : subcommands_) {
12451245 // process the priority option_groups first
12461246 if (sub->get_name ().empty () && sub->parse_complete_callback_ ) {
12471247 if (sub->count_all () > 0 ) {
1248- sub->_process_callbacks ();
1249- sub->run_callback ();
1248+ sub->_process_callbacks (priority);
1249+ if (priority == CallbackPriority::Normal) {
1250+ // only run the subcommand callback at normal priority
1251+ sub->run_callback ();
1252+ }
12501253 }
12511254 }
12521255 }
12531256
12541257 for (const Option_p &opt : options_) {
1255- if ((*opt) && !opt->get_callback_run ()) {
1256- opt->run_callback ();
1258+ if (opt->get_callback_priority () == priority) {
1259+ if ((*opt) && !opt->get_callback_run ()) {
1260+ opt->run_callback ();
1261+ }
12571262 }
12581263 }
12591264 for (App_p &sub : subcommands_) {
12601265 if (!sub->parse_complete_callback_ ) {
1261- sub->_process_callbacks ();
1266+ sub->_process_callbacks (priority );
12621267 }
12631268 }
12641269}
12651270
1266- CLI11_INLINE void App::_process_help_flags (bool trigger_help, bool trigger_all_help) const {
1271+ CLI11_INLINE void App::_process_help_flags (CallbackPriority priority, bool trigger_help, bool trigger_all_help) const {
12671272 const Option *help_ptr = get_help_ptr ();
12681273 const Option *help_all_ptr = get_help_all_ptr ();
12691274
1270- if (help_ptr != nullptr && help_ptr->count () > 0 )
1275+ if (help_ptr != nullptr && help_ptr->count () > 0 && help_ptr-> get_callback_priority () == priority )
12711276 trigger_help = true ;
1272- if (help_all_ptr != nullptr && help_all_ptr->count () > 0 )
1277+ if (help_all_ptr != nullptr && help_all_ptr->count () > 0 && help_all_ptr-> get_callback_priority () == priority )
12731278 trigger_all_help = true ;
12741279
12751280 // If there were parsed subcommands, call those. First subcommand wins if there are multiple ones.
12761281 if (!parsed_subcommands_.empty ()) {
12771282 for (const App *sub : parsed_subcommands_)
1278- sub->_process_help_flags (trigger_help, trigger_all_help);
1283+ sub->_process_help_flags (priority, trigger_help, trigger_all_help);
12791284
12801285 // Only the final subcommand should call for help. All help wins over help.
12811286 } else if (trigger_all_help) {
@@ -1416,7 +1421,10 @@ CLI11_INLINE void App::_process_requirements() {
14161421CLI11_INLINE void App::_process () {
14171422 // help takes precedence over other potential errors and config and environment shouldn't be processed if help
14181423 // throws
1419- _process_help_flags ();
1424+ _process_callbacks (CallbackPriority::FirstPreHelp);
1425+ _process_help_flags (CallbackPriority::First);
1426+ _process_callbacks (CallbackPriority::First);
1427+
14201428 std::exception_ptr config_exception;
14211429 try {
14221430 // the config file might generate a FileError but that should not be processed until later in the process
@@ -1430,13 +1438,23 @@ CLI11_INLINE void App::_process() {
14301438 }
14311439 // callbacks and requirements processing can generate exceptions which should take priority
14321440 // over the config file error if one exists.
1441+ _process_callbacks (CallbackPriority::PreRequirementsCheckPreHelp);
1442+ _process_help_flags (CallbackPriority::PreRequirementsCheck);
1443+ _process_callbacks (CallbackPriority::PreRequirementsCheck);
1444+
14331445 _process_requirements ();
14341446
1435- _process_callbacks ();
1447+ _process_callbacks (CallbackPriority::NormalPreHelp);
1448+ _process_help_flags (CallbackPriority::Normal);
1449+ _process_callbacks (CallbackPriority::Normal);
14361450
14371451 if (config_exception) {
14381452 std::rethrow_exception (config_exception);
14391453 }
1454+
1455+ _process_callbacks (CallbackPriority::LastPreHelp);
1456+ _process_help_flags (CallbackPriority::Last);
1457+ _process_callbacks (CallbackPriority::Last);
14401458}
14411459
14421460CLI11_INLINE void App::_process_extras () {
@@ -1496,10 +1514,20 @@ CLI11_INLINE void App::_parse(std::vector<std::string> &args) {
14961514 // Convert missing (pairs) to extras (string only) ready for processing in another app
14971515 args = remaining_for_passthrough (false );
14981516 } else if (parse_complete_callback_) {
1517+ _process_callbacks (CallbackPriority::FirstPreHelp);
1518+ _process_help_flags (CallbackPriority::First);
1519+ _process_callbacks (CallbackPriority::First);
14991520 _process_env ();
1500- _process_callbacks ();
1501- _process_help_flags ();
1521+ _process_callbacks (CallbackPriority::PreRequirementsCheckPreHelp);
1522+ _process_help_flags (CallbackPriority::PreRequirementsCheck);
1523+ _process_callbacks (CallbackPriority::PreRequirementsCheck);
15021524 _process_requirements ();
1525+ _process_callbacks (CallbackPriority::NormalPreHelp);
1526+ _process_help_flags (CallbackPriority::Normal);
1527+ _process_callbacks (CallbackPriority::Normal);
1528+ _process_callbacks (CallbackPriority::LastPreHelp);
1529+ _process_help_flags (CallbackPriority::Last);
1530+ _process_callbacks (CallbackPriority::Last);
15031531 run_callback (false , true );
15041532 }
15051533}
@@ -1620,8 +1648,15 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
16201648 // check for section close
16211649 if (item.name == " --" ) {
16221650 if (configurable_ && parse_complete_callback_) {
1623- _process_callbacks ();
1651+ _process_callbacks (CallbackPriority::FirstPreHelp);
1652+ _process_callbacks (CallbackPriority::First);
1653+ _process_callbacks (CallbackPriority::PreRequirementsCheckPreHelp);
1654+ _process_callbacks (CallbackPriority::PreRequirementsCheck);
16241655 _process_requirements ();
1656+ _process_callbacks (CallbackPriority::NormalPreHelp);
1657+ _process_callbacks (CallbackPriority::Normal);
1658+ _process_callbacks (CallbackPriority::LastPreHelp);
1659+ _process_callbacks (CallbackPriority::Last);
16251660 run_callback ();
16261661 }
16271662 return true ;
@@ -2081,10 +2116,20 @@ App::_parse_arg(std::vector<std::string> &args, detail::Classifier current_type,
20812116 _trigger_pre_parse (args.size ());
20822117 // run the parse complete callback since the subcommand processing is now complete
20832118 if (sub->parse_complete_callback_ ) {
2119+ sub->_process_callbacks (CallbackPriority::FirstPreHelp);
2120+ sub->_process_help_flags (CallbackPriority::First);
2121+ sub->_process_callbacks (CallbackPriority::First);
20842122 sub->_process_env ();
2085- sub->_process_callbacks ();
2086- sub->_process_help_flags ();
2123+ sub->_process_callbacks (CallbackPriority::PreRequirementsCheckPreHelp);
2124+ sub->_process_help_flags (CallbackPriority::PreRequirementsCheck);
2125+ sub->_process_callbacks (CallbackPriority::PreRequirementsCheck);
20872126 sub->_process_requirements ();
2127+ sub->_process_callbacks (CallbackPriority::NormalPreHelp);
2128+ sub->_process_help_flags (CallbackPriority::Normal);
2129+ sub->_process_callbacks (CallbackPriority::Normal);
2130+ sub->_process_callbacks (CallbackPriority::LastPreHelp);
2131+ sub->_process_help_flags (CallbackPriority::Last);
2132+ sub->_process_callbacks (CallbackPriority::Last);
20882133 sub->run_callback (false , true );
20892134 }
20902135 return true ;
0 commit comments