From 4067f55cb87824360655f4d0e55967fdb32610ad Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Mon, 30 Jan 2017 13:02:55 -0500 Subject: [PATCH] Changing the exit method to a more reasonable system --- examples/try.cpp | 4 +++- examples/try1.cpp | 4 +++- include/CLI.hpp | 44 ++++++++++++++++++++++++++++++++------------ tests/CLITest.cpp | 11 +++++++---- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/examples/try.cpp b/examples/try.cpp index 88fa125..08beb05 100644 --- a/examples/try.cpp +++ b/examples/try.cpp @@ -11,7 +11,9 @@ int main (int argc, char** argv) { int count; app.add_flag("c,count", count, "File name"); - app.start(argc, argv); + CLI::Return ret = app.start(argc, argv); + if(ret != CLI::Return::Continue) + return (int) ret; std::cout << "Working on file: " << file << ", direct count: " << app.count("file") << std::endl; std::cout << "Working on count: " << count << ", direct count: " << app.count("count") << std::endl; diff --git a/examples/try1.cpp b/examples/try1.cpp index 4345bfc..6077513 100644 --- a/examples/try1.cpp +++ b/examples/try1.cpp @@ -14,7 +14,9 @@ int main (int argc, char** argv) { int count; stop->add_flag("c,count", count, "File name"); - app.start(argc, argv); + CLI::Return ret = app.start(argc, argv); + if(ret != CLI::Return::Continue) + return (int) ret; std::cout << "Working on file: " << file << ", direct count: " << start->count("file") << std::endl; std::cout << "Working on count: " << count << ", direct count: " << stop->count("count") << std::endl; diff --git a/include/CLI.hpp b/include/CLI.hpp index 0998e3f..3d12da2 100644 --- a/include/CLI.hpp +++ b/include/CLI.hpp @@ -62,6 +62,15 @@ using std::enable_if_t; #endif // If your compiler supports C++14, you can use that definition instead +enum class Return { + Continue = -1, + Success = 0, + ParseError = 1, + PositionalError = 2, + RequiredError = 3, + GeneralError = 4 +}; + struct Combiner { int num; bool positional; @@ -147,8 +156,8 @@ struct RequiredError : public Error { RequiredError(std::string name) : Error("RequiredError", name) {} }; -struct ExtraPositionalsError : public Error { - ExtraPositionalsError(std::string name) : Error("ExtraPositionalsError", name) {} +struct PositionalError : public Error { + PositionalError(std::string name) : Error("PositionalError", name) {} }; struct HorribleError : public Error { @@ -617,7 +626,7 @@ public: } if(positionals.size()>0) - throw ExtraPositionalsError("[" + join(positionals) + "]"); + throw PositionalError("[" + join(positionals) + "]"); } void _parse_subcommand(std::vector &args) { @@ -762,21 +771,32 @@ public: } /// This must be called after the options are in but before the rest of the program. - /** Instead of throwing erros, causes the program to exit - * if -h or an invalid option is passed. */ - void start(int argc, char** argv) { + /** Instead of throwing erros, this gives an error code + * if -h or an invalid option is passed. Continue with your program if returns -1 */ + Return start(int argc, char** argv) { + + std::function msg_fun{[this](const Error &e){ + std::cerr << "ERROR: "; + std::cerr << e.what() << std::endl; + std::cerr << help() << std::endl; + }}; + try { parse(argc, argv); + return Return::Continue; } catch(const CallForHelp &e) { std::cout << help() << std::endl; - exit(0); + return Return::Success; + } catch(const ParseError &e) { + msg_fun(e); + return Return::ParseError; + } catch(const PositionalError &e) { + msg_fun(e); + return Return::RequiredError; } catch(const Error &e) { - std::cerr << "ERROR: "; - std::cerr << e.what() << std::endl; - std::cerr << help() << std::endl; - exit(1); + msg_fun(e); + return Return::GeneralError; } - } /// Counts the number of times the given option was passed. diff --git a/tests/CLITest.cpp b/tests/CLITest.cpp index 42dbab9..1aa070b 100644 --- a/tests/CLITest.cpp +++ b/tests/CLITest.cpp @@ -15,7 +15,7 @@ TEST(Basic, Empty) { { CLI::App app; input_t spare = {"spare"}; - EXPECT_THROW(app.parse(spare), CLI::ExtraPositionalsError); + EXPECT_THROW(app.parse(spare), CLI::PositionalError); } { CLI::App app; @@ -248,6 +248,10 @@ TEST_F(TApp, FileExists) { std::remove(myfile.c_str()); EXPECT_FALSE(CLI::_ExistingFile(myfile)); } + + +// TODO: Add directory test + TEST_F(TApp, Basic) { auto sub1 = app.add_subcommand("sub1"); auto sub2 = app.add_subcommand("sub2"); @@ -302,16 +306,15 @@ TEST_F(SubcommandProgram, Working) { TEST_F(SubcommandProgram, Spare) { args = {"extra", "-d", "start", "-ffilename"}; - EXPECT_THROW(run(), CLI::ExtraPositionalsError); + EXPECT_THROW(run(), CLI::PositionalError); } TEST_F(SubcommandProgram, SpareSub) { args = {"-d", "start", "spare", "-ffilename"}; - EXPECT_THROW(run(), CLI::ExtraPositionalsError); + EXPECT_THROW(run(), CLI::PositionalError); } -// TODO: Add positionals // TODO: Add vector arguments // TODO: Maybe add function to call on subcommand parse? // TODO: Check help output -- libgit2 0.21.4