Commit 9c55fa2872b730662a3ae530d4d1105916f6c72d
1 parent
200072dc
Added subcommand callback
Showing
2 changed files
with
45 additions
and
4 deletions
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 | ... | ... |