diff --git a/CHANGELOG.md b/CHANGELOG.md index a663bc72..4c0e29b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ * The order is now preserved for subcommands (list and callbacks) [#49](https://github.com/CLIUtils/CLI11/pull/49) * Tests now run individually, utilizing CMake 3.10 additions if possible [#50](https://github.com/CLIUtils/CLI11/pull/50) * Failure messages are now customizable, with a shorter default [#52](https://github.com/CLIUtils/CLI11/pull/52) - +* `require_subcommand` now offers a two-argument form and negative values on the one-argument form are more useful [#51](https://github.com/CLIUtils/CLI11/pull/51) +* Subcommands no longer match after the max required number is obtained [#51](https://github.com/CLIUtils/CLI11/pull/51) ## Version 1.2 diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 71e39683..d2941a35 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -245,13 +245,20 @@ class App { /// This allows the subcommand to be directly checked. operator bool() const { return parsed_; } + /// The argumentless form of require subcommand requires 1 or more subcommands + App *require_subcommand() { + require_subcommand_min_ = 1; + require_subcommand_max_ = 0; + return this; + } + /// Require a subcommand to be given (does not affect help call) /// The number required can be given. Negative values indicate maximum /// number allowed (0 for any number). - App *require_subcommand(int value = -1) { + App *require_subcommand(int value) { if(value < 0) { - require_subcommand_min_ = static_cast(-value); - require_subcommand_max_ = 0; + require_subcommand_min_ = 0; + require_subcommand_max_ = static_cast(-value); } else { require_subcommand_min_ = static_cast(value); require_subcommand_max_ = static_cast(value); diff --git a/tests/SubcommandTest.cpp b/tests/SubcommandTest.cpp index 992d4ed0..9b83eb95 100644 --- a/tests/SubcommandTest.cpp +++ b/tests/SubcommandTest.cpp @@ -653,51 +653,71 @@ struct ManySubcommands : public TApp { CLI::App *sub4; ManySubcommands() { + app.allow_extras(); sub1 = app.add_subcommand("sub1"); sub2 = app.add_subcommand("sub2"); sub3 = app.add_subcommand("sub3"); sub4 = app.add_subcommand("sub4"); + args = {"sub1", "sub2", "sub3"}; } }; -TEST_F(ManySubcommands, RequiredExact) { - +TEST_F(ManySubcommands, Required1Exact) { app.require_subcommand(1); - sub1->allow_extras(); - - args = {"sub1", "sub2", "sub3"}; run(); - EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"})); + EXPECT_EQ(app.remaining(true), vs_t({"sub2", "sub3"})); +} - app.reset(); - +TEST_F(ManySubcommands, Required2Exact) { app.require_subcommand(2); - sub2->allow_extras(); run(); - EXPECT_EQ(sub2->remaining(), vs_t({"sub3"})); } -TEST_F(ManySubcommands, RequiredFuzzy) { +TEST_F(ManySubcommands, Required1Fuzzy) { app.require_subcommand(0, 1); - sub1->allow_extras(); - - args = {"sub1", "sub2", "sub3"}; run(); - EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"})); app.reset(); - - app.require_subcommand(0, 2); - sub2->allow_extras(); + app.require_subcommand(-1); run(); + EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"})); +} +TEST_F(ManySubcommands, Required2Fuzzy) { + app.require_subcommand(0, 2); + + run(); + EXPECT_EQ(sub2->remaining(), vs_t({"sub3"})); + EXPECT_EQ(app.remaining(true), vs_t({"sub3"})); + + app.reset(); + app.require_subcommand(-2); + + run(); EXPECT_EQ(sub2->remaining(), vs_t({"sub3"})); } + +TEST_F(ManySubcommands, Unlimited) { + run(); + EXPECT_EQ(app.remaining(true), vs_t()); + + app.reset(); + app.require_subcommand(); + + run(); + EXPECT_EQ(app.remaining(true), vs_t()); + + app.reset(); + app.require_subcommand(2, 0); // 2 or more + + run(); + EXPECT_EQ(app.remaining(true), vs_t()); +}