Commit 9c55fa2872b730662a3ae530d4d1105916f6c72d

Authored by Henry Fredrick Schreiner
1 parent 200072dc

Added subcommand callback

include/CLI.hpp
@@ -34,11 +34,16 @@ namespace CLI { @@ -34,11 +34,16 @@ namespace CLI {
34 34
35 struct Error : public std::runtime_error { 35 struct Error : public std::runtime_error {
36 int exit_code; 36 int exit_code;
37 - Error(std::string parent, std::string name, int exit_code=255) : runtime_error(parent + ": " + name), exit_code(exit_code) {} 37 + bool print_help;
  38 + Error(std::string parent, std::string name, int exit_code=255, bool print_help=true) : runtime_error(parent + ": " + name), exit_code(exit_code), print_help(print_help) {}
  39 +};
  40 +
  41 +struct Success : public Error {
  42 + Success() : Error("Success", "Successfully completed, should be caught and quit", 0, false) {}
38 }; 43 };
39 44
40 struct CallForHelp : public Error { 45 struct CallForHelp : public Error {
41 - CallForHelp() : Error("CallForHelp","This should be caught in your main function, see examples", 0) {} 46 + CallForHelp() : Error("CallForHelp", "This should be caught in your main function, see examples", 0) {}
42 }; 47 };
43 48
44 struct BadNameString : public Error { 49 struct BadNameString : public Error {
@@ -588,8 +593,18 @@ protected: @@ -588,8 +593,18 @@ protected:
588 bool parsed{false}; 593 bool parsed{false};
589 App* subcommand = nullptr; 594 App* subcommand = nullptr;
590 595
  596 + std::function<void(App*)> app_callback;
  597 +
591 public: 598 public:
592 599
  600 + void set_callback(std::function<void(App*)> callback) {
  601 + app_callback = callback;
  602 + }
  603 +
  604 + void run_callback() {
  605 + if(app_callback)
  606 + app_callback(this);
  607 + }
593 608
594 /// Reset the parsed data 609 /// Reset the parsed data
595 void reset() { 610 void reset() {
@@ -978,6 +993,7 @@ public: @@ -978,6 +993,7 @@ public:
978 } 993 }
979 994
980 995
  996 +
981 for(Option& opt : options) { 997 for(Option& opt : options) {
982 while (opt.positional() && opt.count() < opt.expected() && positionals.size() > 0) { 998 while (opt.positional() && opt.count() < opt.expected() && positionals.size() > 0) {
983 opt.get_new(); 999 opt.get_new();
@@ -994,6 +1010,8 @@ public: @@ -994,6 +1010,8 @@ public:
994 } 1010 }
995 if(positionals.size()>0) 1011 if(positionals.size()>0)
996 throw PositionalError("[" + detail::join(positionals) + "]"); 1012 throw PositionalError("[" + detail::join(positionals) + "]");
  1013 +
  1014 + run_callback();
997 } 1015 }
998 1016
999 void _parse_subcommand(std::vector<std::string> &args) { 1017 void _parse_subcommand(std::vector<std::string> &args) {
@@ -1124,9 +1142,11 @@ public: @@ -1124,9 +1142,11 @@ public:
1124 if(e.exit_code != 0) { 1142 if(e.exit_code != 0) {
1125 std::cerr << "ERROR: "; 1143 std::cerr << "ERROR: ";
1126 std::cerr << e.what() << std::endl; 1144 std::cerr << e.what() << std::endl;
1127 - std::cerr << help() << std::endl; 1145 + if(e.print_help)
  1146 + std::cerr << help() << std::endl;
1128 } else { 1147 } else {
1129 - std::cout << help() << std::endl; 1148 + if(e.print_help)
  1149 + std::cout << help() << std::endl;
1130 } 1150 }
1131 return e.exit_code; 1151 return e.exit_code;
1132 } 1152 }
tests/CLITest.cpp
@@ -330,6 +330,27 @@ TEST_F(TApp, BasicSubcommands) { @@ -330,6 +330,27 @@ TEST_F(TApp, BasicSubcommands) {
330 EXPECT_EQ(sub2, app.get_subcommand()); 330 EXPECT_EQ(sub2, app.get_subcommand());
331 } 331 }
332 332
  333 +
  334 +TEST_F(TApp, Callbacks) {
  335 + auto sub1 = app.add_subcommand("sub1");
  336 + sub1->set_callback([](CLI::App*){
  337 + throw CLI::Success();
  338 + });
  339 + auto sub2 = app.add_subcommand("sub2");
  340 + bool val = false;
  341 + sub2->set_callback([&val](CLI::App*){
  342 + val = true;
  343 + });
  344 +
  345 +
  346 + app.reset();
  347 + args = {"sub2"};
  348 + EXPECT_FALSE(val);
  349 + EXPECT_NO_THROW(run());
  350 + EXPECT_TRUE(val);
  351 +
  352 +}
  353 +
333 // TODO: Add directory test 354 // TODO: Add directory test
334 355
335 356