diff --git a/include/CLI.hpp b/include/CLI.hpp index c876d712..e6fd5b00 100644 --- a/include/CLI.hpp +++ b/include/CLI.hpp @@ -34,11 +34,16 @@ namespace CLI { struct Error : public std::runtime_error { int exit_code; - Error(std::string parent, std::string name, int exit_code=255) : runtime_error(parent + ": " + name), exit_code(exit_code) {} + bool print_help; + 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) {} +}; + +struct Success : public Error { + Success() : Error("Success", "Successfully completed, should be caught and quit", 0, false) {} }; struct CallForHelp : public Error { - CallForHelp() : Error("CallForHelp","This should be caught in your main function, see examples", 0) {} + CallForHelp() : Error("CallForHelp", "This should be caught in your main function, see examples", 0) {} }; struct BadNameString : public Error { @@ -588,8 +593,18 @@ protected: bool parsed{false}; App* subcommand = nullptr; + std::function app_callback; + public: + void set_callback(std::function callback) { + app_callback = callback; + } + + void run_callback() { + if(app_callback) + app_callback(this); + } /// Reset the parsed data void reset() { @@ -978,6 +993,7 @@ public: } + for(Option& opt : options) { while (opt.positional() && opt.count() < opt.expected() && positionals.size() > 0) { opt.get_new(); @@ -994,6 +1010,8 @@ public: } if(positionals.size()>0) throw PositionalError("[" + detail::join(positionals) + "]"); + + run_callback(); } void _parse_subcommand(std::vector &args) { @@ -1124,9 +1142,11 @@ public: if(e.exit_code != 0) { std::cerr << "ERROR: "; std::cerr << e.what() << std::endl; - std::cerr << help() << std::endl; + if(e.print_help) + std::cerr << help() << std::endl; } else { - std::cout << help() << std::endl; + if(e.print_help) + std::cout << help() << std::endl; } return e.exit_code; } diff --git a/tests/CLITest.cpp b/tests/CLITest.cpp index fd12f1fd..1022a388 100644 --- a/tests/CLITest.cpp +++ b/tests/CLITest.cpp @@ -330,6 +330,27 @@ TEST_F(TApp, BasicSubcommands) { EXPECT_EQ(sub2, app.get_subcommand()); } + +TEST_F(TApp, Callbacks) { + auto sub1 = app.add_subcommand("sub1"); + sub1->set_callback([](CLI::App*){ + throw CLI::Success(); + }); + auto sub2 = app.add_subcommand("sub2"); + bool val = false; + sub2->set_callback([&val](CLI::App*){ + val = true; + }); + + + app.reset(); + args = {"sub2"}; + EXPECT_FALSE(val); + EXPECT_NO_THROW(run()); + EXPECT_TRUE(val); + +} + // TODO: Add directory test