Commit 9c55fa2872b730662a3ae530d4d1105916f6c72d

Authored by Henry Fredrick Schreiner
1 parent 200072dc

Added subcommand callback

include/CLI.hpp
... ... @@ -34,11 +34,16 @@ namespace CLI {
34 34  
35 35 struct Error : public std::runtime_error {
36 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 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 49 struct BadNameString : public Error {
... ... @@ -588,8 +593,18 @@ protected:
588 593 bool parsed{false};
589 594 App* subcommand = nullptr;
590 595  
  596 + std::function<void(App*)> app_callback;
  597 +
591 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 609 /// Reset the parsed data
595 610 void reset() {
... ... @@ -978,6 +993,7 @@ public:
978 993 }
979 994  
980 995  
  996 +
981 997 for(Option& opt : options) {
982 998 while (opt.positional() && opt.count() < opt.expected() && positionals.size() > 0) {
983 999 opt.get_new();
... ... @@ -994,6 +1010,8 @@ public:
994 1010 }
995 1011 if(positionals.size()>0)
996 1012 throw PositionalError("[" + detail::join(positionals) + "]");
  1013 +
  1014 + run_callback();
997 1015 }
998 1016  
999 1017 void _parse_subcommand(std::vector<std::string> &args) {
... ... @@ -1124,9 +1142,11 @@ public:
1124 1142 if(e.exit_code != 0) {
1125 1143 std::cerr << "ERROR: ";
1126 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 1147 } else {
1129   - std::cout << help() << std::endl;
  1148 + if(e.print_help)
  1149 + std::cout << help() << std::endl;
1130 1150 }
1131 1151 return e.exit_code;
1132 1152 }
... ...
tests/CLITest.cpp
... ... @@ -330,6 +330,27 @@ TEST_F(TApp, BasicSubcommands) {
330 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 354 // TODO: Add directory test
334 355  
335 356  
... ...