Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group merge #1039

Merged
merged 4 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Unreleased

- add mechanism to allow option groups to be hidden and all options be
considered part of the parent for help display

## Version 2.4: Unicode and TOML support

This version adds Unicode support, support for TOML standard including multiline
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,17 @@ auto hidden_group=app.add_option_group("");
```

will create a group such that no options in that group are displayed in the help
string.
string. For the purposes of help display, if the option group name starts with a
'+' it is treated as if it were not in a group for help and get_options. For
example:

```cpp
auto added_group=app.add_option_group("+sub");
```

In this case the help output will not reference the option group and options
inside of it will be treated for most purposes as if they were part of the
parent.

### Configuration file

Expand Down
5 changes: 5 additions & 0 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,6 +1340,11 @@ class Option_group : public App {
: App(std::move(group_description), "", parent) {
group(group_name);
// option groups should have automatic fallthrough
if(group_name.empty() || group_name.front() == '+') {
// help will not be used by default in these contexts
set_help_flag("");
set_help_all_flag("");
}
}
using App::add_option;
/// Add an existing option to the Option_group
Expand Down
17 changes: 15 additions & 2 deletions include/CLI/impl/App_inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,14 @@ CLI11_INLINE std::vector<const Option *> App::get_options(const std::function<bo
[&filter](const Option *opt) { return !filter(opt); }),
std::end(options));
}

for(const auto &subcp : subcommands_) {
// also check down into nameless subcommands
const App *subc = subcp.get();
if(subc->get_name().empty() && !subc->get_group().empty() && subc->get_group().front() == '+') {
std::vector<const Option *> subcopts = subc->get_options(filter);
options.insert(options.end(), subcopts.begin(), subcopts.end());
}
}
return options;
}

Expand All @@ -798,7 +805,13 @@ CLI11_INLINE std::vector<Option *> App::get_options(const std::function<bool(Opt
std::remove_if(std::begin(options), std::end(options), [&filter](Option *opt) { return !filter(opt); }),
std::end(options));
}

for(auto &subc : subcommands_) {
// also check down into nameless subcommands
if(subc->get_name().empty() && !subc->get_group().empty() && subc->get_group().front() == '+') {
auto subcopts = subc->get_options(filter);
options.insert(options.end(), subcopts.begin(), subcopts.end());
}
}
return options;
}

Expand Down
6 changes: 3 additions & 3 deletions include/CLI/impl/Formatter_inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ CLI11_INLINE std::string Formatter::make_subcommands(const App *app, AppFormatMo
std::vector<std::string> subcmd_groups_seen;
for(const App *com : subcommands) {
if(com->get_name().empty()) {
if(!com->get_group().empty()) {
out << make_expanded(com);
if(com->get_group().empty() || com->get_group().front() == '+') {
continue;
}
continue;
out << make_expanded(com);
}
std::string group_key = com->get_group();
if(!group_key.empty() &&
Expand Down
26 changes: 26 additions & 0 deletions tests/OptionGroupTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,32 @@ TEST_CASE_METHOD(TApp, "BasicOptionGroupMin", "[optiongroup]") {
CHECK(std::string::npos != exactloc);
}

TEST_CASE_METHOD(TApp, "integratedOptionGroup", "[optiongroup]") {
auto *ogroup = app.add_option_group("+clusters");
int res{0};
ogroup->add_option("--test1", res);
ogroup->add_option("--test2", res);
ogroup->add_option("--test3", res);
int val2{0};
app.add_option("--option", val2);
ogroup->require_option();

args = {"--option", "9"};
CHECK_THROWS_AS(run(), CLI::RequiredError);

args = {"--test1", "5", "--test2", "4", "--test3=5"};
CHECK_NOTHROW(run());

auto options = app.get_options();
CHECK(options.size() == 5);
const CLI::App *capp = &app;
auto coptions = capp->get_options();
CHECK(coptions.size() == 5);
std::string help = app.help();
auto exactloc = help.find("clusters");
CHECK(std::string::npos == exactloc);
}

TEST_CASE_METHOD(TApp, "BasicOptionGroupExact2", "[optiongroup]") {
auto *ogroup = app.add_option_group("clusters");
int res{0};
Expand Down
Loading