diff --git a/README.md b/README.md index 0a993c453..4386b3f56 100644 --- a/README.md +++ b/README.md @@ -132,8 +132,6 @@ app.add_set(option_name, app.add_set_ignore_case(... // String only -app.add_help_flag(name, optional_discription); - App* subcom = app.add_subcommand(name, discription); ``` @@ -163,7 +161,7 @@ The add commands return a pointer to an internally stored `Option`. If you set t * `->check(CLI::NonexistentPath)`: Requires that the path does not exist. * `->check(CLI::Range(min,max))`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0. -These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. Check takes any function that has the signature `bool(std::string)`. If you want to change the default help option, it is available through `get_help_ptr`. If you just want to see the unconverted values, use `.results()` to get the `std::vector` of results. +These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. Check takes any function that has the signature `bool(std::string)`. If you just want to see the unconverted values, use `.results()` to get the `std::vector` of results. On the command line, options can be given as: @@ -247,7 +245,7 @@ arguments, use `.config_to_str(default_also=false)`, where `default_also` will a ## Subclassing -The App class was designed allow toolkits to subclass it, to provide default options and setup/teardown code. Subcommands remain an unsubclassed `App`, since those are not expected to need setup and teardown. The default `App` only adds a help flag, `-h,--help`, but provides an option to disable it in the constructor (and in `add_subcommand`). You can remove options if you have pointers to them using `.remove_option(opt)`. You can add a `pre_callback` override to customize the after parse +The App class was designed allow toolkits to subclass it, to provide default options and setup/teardown code. Subcommands remain an unsubclassed `App`, since those are not expected to need setup and teardown. The default `App` only adds a help flag, `-h,--help`, but provides an option to disable it in the constructor (and in `add_subcommand`), and can removed/replaced using `.set_help_flag(name, help_string)`. You can remove options if you have pointers to them using `.remove_option(opt)`. You can add a `pre_callback` override to customize the after parse but before run behavior, while still giving the user freedom to `set_callback` on the main app. diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 649b49ffe..e55dee794 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -140,7 +140,7 @@ class App { App(std::string description_, bool help, detail::enabler) : description_(std::move(description_)) { if(help) - add_help_flag("-h,--help", "Print this help message and exit"); + set_help_flag("-h,--help", "Print this help message and exit"); } public: @@ -331,11 +331,17 @@ class App { return opt; } - /// Add a help flag, replaced the existing one if present - Option *add_help_flag(std::string name, std::string description = "") { - if(help_ptr_ != nullptr) + /// Set a help flag, replaced the existing one if present + Option *set_help_flag(std::string name = "", std::string description = "") { + if(help_ptr_ != nullptr) { remove_option(help_ptr_); - help_ptr_ = add_flag(name, description); + help_ptr_ = nullptr; + } + + // Empty name will simply remove the help flag + if(!name.empty()) + help_ptr_ = add_flag(name, description); + return help_ptr_; } diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 73e4d37a6..435c151ee 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -287,12 +287,30 @@ TEST(THelp, OnlyOneHelp) { CLI::App app{"My prog"}; // It is not supported to have more than one help flag, last one wins - app.add_help_flag("--help", "No short name allowed"); - app.add_help_flag("--yelp", "Alias for help"); + app.set_help_flag("--help", "No short name allowed"); + app.set_help_flag("--yelp", "Alias for help"); std::vector input{"--help"}; EXPECT_THROW(app.parse(input), CLI::ExtrasError); - +} + +TEST(THelp, RemoveHelp) { + CLI::App app{"My prog"}; + app.set_help_flag(); + + std::string help = app.help(); + + EXPECT_THAT(help, HasSubstr("My prog")); + EXPECT_THAT(help, Not(HasSubstr("-h,--help"))); + EXPECT_THAT(help, Not(HasSubstr("Options:"))); + EXPECT_THAT(help, HasSubstr("Usage:")); + + std::vector input{"--help"}; + try { + app.parse(input); + } catch(const CLI::ParseError &e) { + EXPECT_EQ(static_cast(CLI::ExitCodes::Extras), e.get_exit_code()); + } } TEST(THelp, NoHelp) { @@ -316,7 +334,7 @@ TEST(THelp, NoHelp) { TEST(THelp, CustomHelp) { CLI::App app{"My prog", false}; - CLI::Option *help_option = app.add_help_flag("--yelp", "display help and exit"); + CLI::Option *help_option = app.set_help_flag("--yelp", "display help and exit"); EXPECT_EQ(app.get_help_ptr(), help_option); std::string help = app.help();