Commit bcbd8c862bdfa9546f144118f9a21e410f1e0b8c

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 65493d64

Using -N for up-to N

CHANGELOG.md
@@ -15,7 +15,8 @@ @@ -15,7 +15,8 @@
15 * The order is now preserved for subcommands (list and callbacks) [#49](https://github.com/CLIUtils/CLI11/pull/49) 15 * The order is now preserved for subcommands (list and callbacks) [#49](https://github.com/CLIUtils/CLI11/pull/49)
16 * Tests now run individually, utilizing CMake 3.10 additions if possible [#50](https://github.com/CLIUtils/CLI11/pull/50) 16 * Tests now run individually, utilizing CMake 3.10 additions if possible [#50](https://github.com/CLIUtils/CLI11/pull/50)
17 * Failure messages are now customizable, with a shorter default [#52](https://github.com/CLIUtils/CLI11/pull/52) 17 * Failure messages are now customizable, with a shorter default [#52](https://github.com/CLIUtils/CLI11/pull/52)
18 - 18 +* `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)
  19 +* Subcommands no longer match after the max required number is obtained [#51](https://github.com/CLIUtils/CLI11/pull/51)
19 20
20 ## Version 1.2 21 ## Version 1.2
21 22
include/CLI/App.hpp
@@ -245,13 +245,20 @@ class App { @@ -245,13 +245,20 @@ class App {
245 /// This allows the subcommand to be directly checked. 245 /// This allows the subcommand to be directly checked.
246 operator bool() const { return parsed_; } 246 operator bool() const { return parsed_; }
247 247
  248 + /// The argumentless form of require subcommand requires 1 or more subcommands
  249 + App *require_subcommand() {
  250 + require_subcommand_min_ = 1;
  251 + require_subcommand_max_ = 0;
  252 + return this;
  253 + }
  254 +
248 /// Require a subcommand to be given (does not affect help call) 255 /// Require a subcommand to be given (does not affect help call)
249 /// The number required can be given. Negative values indicate maximum 256 /// The number required can be given. Negative values indicate maximum
250 /// number allowed (0 for any number). 257 /// number allowed (0 for any number).
251 - App *require_subcommand(int value = -1) { 258 + App *require_subcommand(int value) {
252 if(value < 0) { 259 if(value < 0) {
253 - require_subcommand_min_ = static_cast<size_t>(-value);  
254 - require_subcommand_max_ = 0; 260 + require_subcommand_min_ = 0;
  261 + require_subcommand_max_ = static_cast<size_t>(-value);
255 } else { 262 } else {
256 require_subcommand_min_ = static_cast<size_t>(value); 263 require_subcommand_min_ = static_cast<size_t>(value);
257 require_subcommand_max_ = static_cast<size_t>(value); 264 require_subcommand_max_ = static_cast<size_t>(value);
tests/SubcommandTest.cpp
@@ -653,51 +653,71 @@ struct ManySubcommands : public TApp { @@ -653,51 +653,71 @@ struct ManySubcommands : public TApp {
653 CLI::App *sub4; 653 CLI::App *sub4;
654 654
655 ManySubcommands() { 655 ManySubcommands() {
  656 + app.allow_extras();
656 sub1 = app.add_subcommand("sub1"); 657 sub1 = app.add_subcommand("sub1");
657 sub2 = app.add_subcommand("sub2"); 658 sub2 = app.add_subcommand("sub2");
658 sub3 = app.add_subcommand("sub3"); 659 sub3 = app.add_subcommand("sub3");
659 sub4 = app.add_subcommand("sub4"); 660 sub4 = app.add_subcommand("sub4");
  661 + args = {"sub1", "sub2", "sub3"};
660 } 662 }
661 }; 663 };
662 664
663 -TEST_F(ManySubcommands, RequiredExact) {  
664 - 665 +TEST_F(ManySubcommands, Required1Exact) {
665 app.require_subcommand(1); 666 app.require_subcommand(1);
666 667
667 - sub1->allow_extras();  
668 -  
669 - args = {"sub1", "sub2", "sub3"};  
670 run(); 668 run();
671 -  
672 EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"})); 669 EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"}));
  670 + EXPECT_EQ(app.remaining(true), vs_t({"sub2", "sub3"}));
  671 +}
673 672
674 - app.reset();  
675 - 673 +TEST_F(ManySubcommands, Required2Exact) {
676 app.require_subcommand(2); 674 app.require_subcommand(2);
677 - sub2->allow_extras();  
678 675
679 run(); 676 run();
680 -  
681 EXPECT_EQ(sub2->remaining(), vs_t({"sub3"})); 677 EXPECT_EQ(sub2->remaining(), vs_t({"sub3"}));
682 } 678 }
683 679
684 -TEST_F(ManySubcommands, RequiredFuzzy) { 680 +TEST_F(ManySubcommands, Required1Fuzzy) {
685 681
686 app.require_subcommand(0, 1); 682 app.require_subcommand(0, 1);
687 683
688 - sub1->allow_extras();  
689 -  
690 - args = {"sub1", "sub2", "sub3"};  
691 run(); 684 run();
692 -  
693 EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"})); 685 EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"}));
694 686
695 app.reset(); 687 app.reset();
  688 + app.require_subcommand(-1);
696 689
  690 + run();
  691 + EXPECT_EQ(sub1->remaining(), vs_t({"sub2", "sub3"}));
  692 +}
  693 +
  694 +TEST_F(ManySubcommands, Required2Fuzzy) {
697 app.require_subcommand(0, 2); 695 app.require_subcommand(0, 2);
698 - sub2->allow_extras();  
699 696
700 run(); 697 run();
  698 + EXPECT_EQ(sub2->remaining(), vs_t({"sub3"}));
  699 + EXPECT_EQ(app.remaining(true), vs_t({"sub3"}));
701 700
  701 + app.reset();
  702 + app.require_subcommand(-2);
  703 +
  704 + run();
702 EXPECT_EQ(sub2->remaining(), vs_t({"sub3"})); 705 EXPECT_EQ(sub2->remaining(), vs_t({"sub3"}));
703 } 706 }
  707 +
  708 +TEST_F(ManySubcommands, Unlimited) {
  709 + run();
  710 + EXPECT_EQ(app.remaining(true), vs_t());
  711 +
  712 + app.reset();
  713 + app.require_subcommand();
  714 +
  715 + run();
  716 + EXPECT_EQ(app.remaining(true), vs_t());
  717 +
  718 + app.reset();
  719 + app.require_subcommand(2, 0); // 2 or more
  720 +
  721 + run();
  722 + EXPECT_EQ(app.remaining(true), vs_t());
  723 +}