diff --git a/CHANGELOG.md b/CHANGELOG.md index 598db6b..caaf58a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Version 0.5 (in progress) +* Allow `Hidden` options. * Throw `OptionAlreadyAdded` errors for matching subcommands or options, with ignore-case included, tests * `->ignore_case()` added to subcommands, options, and `add_set_ignore_case`. Subcommands inherit setting from parent App on creation. * Subcommands now can be "chained", that is, left over arguments can now include subcommands that then get parsed. Subcommands are now a list (`get_subcommands`). Added `got_subcommand(App_or_name)` to check for subcommands. diff --git a/README.md b/README.md index cefc90b..7b9ba80 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ The add commands return a pointer to an internally stored `Option`. If you set t * `->requires(opt)`: This option requires another option to also be present, opt is an `Option` pointer. * `->excludes(opt)`: This option cannot be given with `opt` present, opt is an `Option` pointer. * `->envname(name)`: Gets the value from the environment if present and not passed on the command line. -* `->group(name)`: The help group to put the option in. No effect for positional options. Defaults to `"Options"`. +* `->group(name)`: The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `"Hidden"` will not show up in the help print. * `->ignore_case()`: Ignore the case on the command line (also works on subcommands, does not affect arguments). * `->check(CLI::ExistingFile)`: Requires that the file exists if given. * `->check(CLI::ExistingDirectory)`: Requires that the directory exists. diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 68fd811..422e140 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -467,6 +467,9 @@ public: bool pos=false; for(const Option_p &opt : options) if(opt->get_positional()) { + // A hidden positional should still show up in the usage statement + //if(detail::to_lower(opt->get_group()) == "hidden") + // continue; out << " " << opt->help_positional(); if(opt->has_description()) pos=true; @@ -484,9 +487,12 @@ public: // Positional descriptions if(pos) { out << "Positionals:" << std::endl; - for(const Option_p &opt : options) + for(const Option_p &opt : options) { + if(detail::to_lower(opt->get_group()) == "hidden") + continue; if(opt->get_positional() && opt->has_description()) detail::format_help(out, opt->help_pname(), opt->get_description(), wid); + } out << std::endl; } @@ -495,6 +501,8 @@ public: // Options if(npos) { for (const std::string& group : groups) { + if(detail::to_lower(group) == "hidden") + continue; out << group << ":" << std::endl; for(const Option_p &opt : options) { if(opt->nonpositional() && opt->get_group() == group) diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 2f0830b..84f9c9c 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -9,6 +9,7 @@ #include using ::testing::HasSubstr; +using ::testing::Not; TEST(THelp, Basic) { CLI::App app{"My prog"}; @@ -37,8 +38,28 @@ TEST(THelp, OptionalPositional) { EXPECT_THAT(help, HasSubstr("something TEXT")); EXPECT_THAT(help, HasSubstr("My option here")); EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] [something]")); +} + +TEST(THelp, Hidden) { + CLI::App app{"My prog"}; + + std::string x; + app.add_option("something", x, "My option here") + ->group("Hidden"); + std::string y; + app.add_option("--another", y) + ->group("Hidden"); + std::string help = app.help(); + + EXPECT_THAT(help, HasSubstr("My prog")); + EXPECT_THAT(help, HasSubstr("-h,--help")); + EXPECT_THAT(help, HasSubstr("Options:")); + EXPECT_THAT(help, HasSubstr("[something]")); + EXPECT_THAT(help, Not(HasSubstr("something "))); + EXPECT_THAT(help, Not(HasSubstr("another"))); } + TEST(THelp, OptionalPositionalAndOptions) { CLI::App app{"My prog"}; app.add_flag("-q,--quick");