diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ef17d2c2..56a58e87 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -128,3 +128,7 @@ set_property(TEST subcom_in_files PROPERTY PASS_REGULAR_EXPRESSION add_cli_exe(formatter formatter.cpp) add_cli_exe(nested nested.cpp) + +add_cli_exe(subcom_help subcom_help.cpp) +add_test(NAME subcom_help_normal COMMAND subcom_help sub --help) +add_test(NAME subcom_help_reversed COMMAND subcom_help --help sub) diff --git a/examples/subcom_help.cpp b/examples/subcom_help.cpp new file mode 100644 index 00000000..0d8997d9 --- /dev/null +++ b/examples/subcom_help.cpp @@ -0,0 +1,14 @@ +#include +#include + +int main(int argc, char *argv[]) { + CLI::App cli_global{"Demo app"}; + auto &cli_sub = *cli_global.add_subcommand("sub", "Some subcommand"); + std::string sub_arg; + cli_sub.add_option("sub_arg", sub_arg, "Argument for subcommand")->required(); + CLI11_PARSE(cli_global, argc, argv); + if(cli_sub) { + std::cout << "Got: " << sub_arg << std::endl; + } + return 0; +} diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index eebab3bf..2bd8b8f6 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -1341,6 +1341,10 @@ class App { // Verify required options for(const Option_p &opt : options_) { + // Exit if a help flag was passed (requirements not required in that case) + if(_any_help_flag()) + break; + // Required or partially filled if(opt->get_required() || opt->count() != 0) { // Make sure enough -N arguments parsed (+N is already handled in parsing function) @@ -1379,6 +1383,21 @@ class App { } } + /// Return True if a help flag detected (checks all parents) + bool _any_help_flag() const { + bool result = false; + const Option *help_ptr = get_help_ptr(); + const Option *help_all_ptr = get_help_all_ptr(); + if(help_ptr != nullptr && help_ptr->count() > 0) + result = true; + if(help_all_ptr != nullptr && help_all_ptr->count() > 0) + result = true; + if(parent_ != nullptr) + return result || parent_->_any_help_flag(); + else + return result; + } + /// Parse one config param, return false if not found in any subcommand, remove if it is /// /// If this has more than one dot.separated.name, go into the subcommand matching it