Commit 852929f0f62eb4920302684c2cfa013a711967dd

Authored by Marcus Brinkmann
Committed by Henry Schreiner
1 parent 642a6703

Support runtime errors.

include/CLI/App.hpp
@@ -31,6 +31,8 @@ namespace CLI { @@ -31,6 +31,8 @@ namespace CLI {
31 (app).parse((argc), (argv)); \ 31 (app).parse((argc), (argv)); \
32 } catch(const CLI::ParseError &e) { \ 32 } catch(const CLI::ParseError &e) { \
33 return (app).exit(e); \ 33 return (app).exit(e); \
  34 + } catch(const CLI::RuntimeError &e) { \
  35 + return e.get_exit_code(); \
34 } 36 }
35 #endif 37 #endif
36 38
include/CLI/Error.hpp
@@ -79,6 +79,14 @@ struct OptionAlreadyAdded : public ConstructionError { @@ -79,6 +79,14 @@ struct OptionAlreadyAdded : public ConstructionError {
79 : ConstructionError("OptionAlreadyAdded", name, ExitCodes::OptionAlreadyAdded) {} 79 : ConstructionError("OptionAlreadyAdded", name, ExitCodes::OptionAlreadyAdded) {}
80 }; 80 };
81 81
  82 +// Runtime Errors
  83 +
  84 +/// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code.
  85 +struct RuntimeError : public Error {
  86 + RuntimeError(int exit_code = 1)
  87 + : Error("RuntimeError", "runtime error", exit_code, false) {}
  88 +};
  89 +
82 // Parsing errors 90 // Parsing errors
83 91
84 /// Anything that can error in Parse 92 /// Anything that can error in Parse
tests/SubcommandTest.cpp
@@ -168,6 +168,36 @@ TEST_F(TApp, Callbacks) { @@ -168,6 +168,36 @@ TEST_F(TApp, Callbacks) {
168 EXPECT_TRUE(val); 168 EXPECT_TRUE(val);
169 } 169 }
170 170
  171 +TEST_F(TApp, RuntimeErrorInCallback) {
  172 + auto sub1 = app.add_subcommand("sub1");
  173 + sub1->set_callback([]() { throw CLI::RuntimeError(); });
  174 + auto sub2 = app.add_subcommand("sub2");
  175 + sub2->set_callback([]() { throw CLI::RuntimeError(2); });
  176 +
  177 + args = {"sub1"};
  178 + EXPECT_THROW(run(), CLI::RuntimeError);
  179 +
  180 + app.reset();
  181 + args = {"sub1"};
  182 + try {
  183 + run();
  184 + } catch(const CLI::RuntimeError &e) {
  185 + EXPECT_EQ(1, e.get_exit_code());
  186 + }
  187 +
  188 + app.reset();
  189 + args = {"sub2"};
  190 + EXPECT_THROW(run(), CLI::RuntimeError);
  191 +
  192 + app.reset();
  193 + args = {"sub2"};
  194 + try {
  195 + run();
  196 + } catch(const CLI::RuntimeError &e) {
  197 + EXPECT_EQ(2, e.get_exit_code());
  198 + }
  199 +}
  200 +
171 TEST_F(TApp, NoFallThroughOpts) { 201 TEST_F(TApp, NoFallThroughOpts) {
172 int val = 1; 202 int val = 1;
173 app.add_option("--val", val); 203 app.add_option("--val", val);