From 90af06afe6b50661ce78cc7edfe20f604c50afda Mon Sep 17 00:00:00 2001 From: Philip Top Date: Tue, 7 Apr 2020 06:00:18 -0700 Subject: [PATCH 1/9] Add a dedicated version option to CLI11 to facilitate use of version flags, similar to help flags --- include/CLI/App.hpp | 62 +++++++++++++++++++++++++++++++++++++++++++ include/CLI/Error.hpp | 6 +++++ 2 files changed, 68 insertions(+) diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index d7c9f3f1d..d273f3621 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -139,6 +139,9 @@ class App { /// A pointer to the help all flag if there is one INHERITABLE Option *help_all_ptr_{nullptr}; + /// A pointer to a version flag if there is one + Option *version_ptr_{nullptr}; + /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer) std::shared_ptr formatter_{new Formatter()}; @@ -703,6 +706,43 @@ class App { return help_all_ptr_; } + /// Set a version flag and version display string, replace the existing one if present + Option *set_version_flag(std::string flag_name = "", const std::string &version = "") { + // take flag_description by const reference otherwise add_flag tries to assign to help_description + if(version_ptr_ != nullptr) { + remove_option(version_ptr_); + version_ptr_ = nullptr; + } + + // Empty name will simply remove the help flag + if(!flag_name.empty()) { + version_ptr_ = add_flag_callback(flag_name, + [version]() { throw(CLI::CallForVersion(version, 0)); }, + "display program version information and exit"); + version_ptr_->configurable(false); + } + + return version_ptr_; + } + /// Set a version flag, using a callback + Option *set_version_flag(std::string flag_name, std::function vfunc) { + // take flag_description by const reference otherwise add_flag tries to assign to help_description + if(version_ptr_ != nullptr) { + remove_option(version_ptr_); + version_ptr_ = nullptr; + } + + // Empty name will simply remove the help flag + if(!flag_name.empty()) { + version_ptr_ = add_flag_callback(flag_name, + [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, + "display program version information and exit"); + version_ptr_->configurable(false); + } + + return version_ptr_; + } + private: /// Internal function for adding a flag Option *_add_flag_internal(std::string flag_name, CLI::callback_t fun, std::string flag_description) { @@ -1345,6 +1385,11 @@ class App { return e.get_exit_code(); } + if(dynamic_cast(&e) != nullptr) { + out << e.what() << std::endl; + return e.get_exit_code(); + } + if(e.get_exit_code() != static_cast(ExitCodes::Success)) { if(failure_message_) err << failure_message_(this, e) << std::flush; @@ -1530,6 +1575,23 @@ class App { return formatter_->make_help(this, prev, mode); } + /// Displays a version string + std::string version() const { + std::string val; + if(version_ptr_ != nullptr) { + auto rv = version_ptr_->results(); + version_ptr_->clear(); + version_ptr_->add_result("true"); + try { + version_ptr_->run_callback(); + } catch(const CLI::CallForVersion &cfv) { + val = cfv.what(); + } + version_ptr_->clear(); + version_ptr_->add_result(rv); + } + return val; + } ///@} /// @name Getters ///@{ diff --git a/include/CLI/Error.hpp b/include/CLI/Error.hpp index 0adf15c50..11b2c07a7 100644 --- a/include/CLI/Error.hpp +++ b/include/CLI/Error.hpp @@ -169,6 +169,12 @@ class CallForAllHelp : public ParseError { : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} }; +/// -v or --version on command line +class CallForVersion : public ParseError { + CLI11_ERROR_DEF(ParseError, CallForVersion) + CallForVersion() : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + /// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code. class RuntimeError : public ParseError { CLI11_ERROR_DEF(ParseError, RuntimeError) From 9df1b5e1cd9ee22814095d14daa1dbe090ae0bf7 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Tue, 7 Apr 2020 14:14:28 -0700 Subject: [PATCH 2/9] add some test for the version flag --- examples/CMakeLists.txt | 3 ++ examples/simple.cpp | 2 ++ include/CLI/App.hpp | 17 +++++++++++ tests/HelpTest.cpp | 63 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 2359d5cd8..bd9baddb6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -54,6 +54,9 @@ set_property(TEST simple_all PROPERTY PASS_REGULAR_EXPRESSION "Received flag: 2 (2) times" "Some value: 1.2") +add_test(NAME simple_version COMMAND simple -v) +set_property(TEST simple_version PROPERTY PASS_REGULAR_EXPRESSION + "${CLI11_VERSION}") add_cli_exe(subcommands subcommands.cpp) add_test(NAME subcommands_none COMMAND subcommands) diff --git a/examples/simple.cpp b/examples/simple.cpp index 2d465cb22..fbe2e6857 100644 --- a/examples/simple.cpp +++ b/examples/simple.cpp @@ -11,6 +11,8 @@ int main(int argc, char **argv) { CLI::App app("K3Pi goofit fitter"); + // add version output + app.version(std::string(CLI11_VERSION)); std::string file; CLI::Option *opt = app.add_option("-f,--file,file", file, "File name"); diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index d273f3621..8f6259234 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -742,6 +742,17 @@ class App { return version_ptr_; } + /// Set the version as a string + App *version(const std::string &version) { + set_version_flag("-v,--version", version); + return this; + } + + /// Set the version as a function + App *version(std::function vfunc) { + set_version_flag("-v,--version", vfunc); + return this; + } private: /// Internal function for adding a flag @@ -1788,6 +1799,12 @@ class App { /// Get a pointer to the config option. (const) const Option *get_config_ptr() const { return config_ptr_; } + /// Get a pointer to the version option. + Option *get_version_ptr() { return version_ptr_; } + + /// Get a pointer to the version option. (const) + const Option *get_version_ptr() const { return version_ptr_; } + /// Get the parent of this subcommand (or nullptr if master app) App *get_parent() { return parent_; } diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 68d96d13b..7089ec423 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -1165,3 +1165,66 @@ TEST(THelp, FunctionDefaultString) { EXPECT_THAT(help, HasSubstr("INT=Powerful")); } + +TEST(TVersion, simple_flag) { + + CLI::App app; + + app.set_version_flag("-v,--version", "VERSION " CLI11_VERSION); + + auto vers = app.version(); + EXPECT_THAT(vers, HasSubstr("VERSION")); +} + +TEST(TVersion, callback_flag) { + + CLI::App app; + + app.set_version_flag("-v,--version", []() { return std::string("VERSION " CLI11_VERSION); }); + + auto vers = app.version(); + EXPECT_THAT(vers, HasSubstr("VERSION")); +} + +TEST(TVersion, simple_direct) { + + CLI::App app; + + app.version(std::string("VERSION " CLI11_VERSION)); + + auto vers = app.version(); + EXPECT_THAT(vers, HasSubstr("VERSION")); +} + +TEST(TVersion, callback_direct) { + + CLI::App app; + + app.version([]() { return std::string("VERSION " CLI11_VERSION); }); + + auto vers = app.version(); + EXPECT_THAT(vers, HasSubstr("VERSION")); +} + +TEST(TVersion, parse_throw) { + + CLI::App app; + + app.version(CLI11_VERSION); + + EXPECT_THROW(app.parse("--version"), CLI::CallForVersion); + EXPECT_THROW(app.parse("-v --arg2 5"), CLI::CallForVersion); + + auto ptr = app.get_version_ptr(); + + ptr->ignore_case(); + try { + app.parse("--Version"); + } catch(const CLI::CallForVersion &v) { + EXPECT_STREQ(v.what(), CLI11_VERSION); + EXPECT_EQ(v.get_exit_code(), 0); + const auto &appc = app; + auto cptr = appc.get_version_ptr(); + EXPECT_EQ(cptr->count(), 1U); + } +} From 40ddfe1c55966188d5f94f49bb6863665d014dc5 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 9 Apr 2020 06:01:49 -0700 Subject: [PATCH 3/9] update errors and formatting --- include/CLI/App.hpp | 16 +++++++++------- include/CLI/Error.hpp | 15 ++++++++------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 8f6259234..fefc5286e 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -707,7 +707,7 @@ class App { } /// Set a version flag and version display string, replace the existing one if present - Option *set_version_flag(std::string flag_name = "", const std::string &version = "") { + Option *set_version_flag(std::string flag_name = "", const std::string &versionString = "") { // take flag_description by const reference otherwise add_flag tries to assign to help_description if(version_ptr_ != nullptr) { remove_option(version_ptr_); @@ -716,9 +716,10 @@ class App { // Empty name will simply remove the help flag if(!flag_name.empty()) { - version_ptr_ = add_flag_callback(flag_name, - [version]() { throw(CLI::CallForVersion(version, 0)); }, - "display program version information and exit"); + version_ptr_ = add_flag_callback( + flag_name, + [versionString]() { throw(CLI::CallForVersion(versionString, 0)); }, + "display program version information and exit"); version_ptr_->configurable(false); } @@ -734,9 +735,10 @@ class App { // Empty name will simply remove the help flag if(!flag_name.empty()) { - version_ptr_ = add_flag_callback(flag_name, - [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, - "display program version information and exit"); + version_ptr_ = add_flag_callback( + flag_name, + [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, + "display program version information and exit"); version_ptr_->configurable(false); } diff --git a/include/CLI/Error.hpp b/include/CLI/Error.hpp index 11b2c07a7..7841c92b7 100644 --- a/include/CLI/Error.hpp +++ b/include/CLI/Error.hpp @@ -157,22 +157,23 @@ class Success : public ParseError { }; /// -h or --help on command line -class CallForHelp : public ParseError { - CLI11_ERROR_DEF(ParseError, CallForHelp) +class CallForHelp : public Success { + CLI11_ERROR_DEF(Success, CallForHelp) CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} }; /// Usually something like --help-all on command line -class CallForAllHelp : public ParseError { - CLI11_ERROR_DEF(ParseError, CallForAllHelp) +class CallForAllHelp : public Success { + CLI11_ERROR_DEF(Success, CallForAllHelp) CallForAllHelp() : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} }; /// -v or --version on command line -class CallForVersion : public ParseError { - CLI11_ERROR_DEF(ParseError, CallForVersion) - CallForVersion() : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {} +class CallForVersion : public Success { + CLI11_ERROR_DEF(Success, CallForVersion) + CallForVersion() + : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {} }; /// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code. From de2af347c6cfabfffecb4de343c3a59835f3bc30 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 9 Apr 2020 06:23:12 -0700 Subject: [PATCH 4/9] clear up gcc 4.8 warnings --- include/CLI/App.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index fefc5286e..6ea704b98 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -708,13 +708,13 @@ class App { /// Set a version flag and version display string, replace the existing one if present Option *set_version_flag(std::string flag_name = "", const std::string &versionString = "") { - // take flag_description by const reference otherwise add_flag tries to assign to help_description + // take flag_description by const reference otherwise add_flag tries to assign to version_description if(version_ptr_ != nullptr) { remove_option(version_ptr_); version_ptr_ = nullptr; } - // Empty name will simply remove the help flag + // Empty name will simply remove the version flag if(!flag_name.empty()) { version_ptr_ = add_flag_callback( flag_name, @@ -725,15 +725,15 @@ class App { return version_ptr_; } - /// Set a version flag, using a callback + /// Generate the version string through a callback function Option *set_version_flag(std::string flag_name, std::function vfunc) { - // take flag_description by const reference otherwise add_flag tries to assign to help_description + // take flag_description by const reference otherwise add_flag tries to assign to version_description if(version_ptr_ != nullptr) { remove_option(version_ptr_); version_ptr_ = nullptr; } - // Empty name will simply remove the help flag + // Empty name will simply remove the version flag if(!flag_name.empty()) { version_ptr_ = add_flag_callback( flag_name, @@ -745,12 +745,12 @@ class App { return version_ptr_; } /// Set the version as a string - App *version(const std::string &version) { - set_version_flag("-v,--version", version); + App *version(const std::string &versionString) { + set_version_flag("-v,--version", versionString); return this; } - /// Set the version as a function + /// Generate the version string through a callback function App *version(std::function vfunc) { set_version_flag("-v,--version", vfunc); return this; From 6316c56a69e9f7c9d5cce6284b106ea367278773 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 9 Apr 2020 06:54:53 -0700 Subject: [PATCH 5/9] add a few more tests --- tests/HelpTest.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 7089ec423..07f7513af 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -1174,6 +1174,9 @@ TEST(TVersion, simple_flag) { auto vers = app.version(); EXPECT_THAT(vers, HasSubstr("VERSION")); + + app.set_version_flag(); + EXPECT_TRUE(app.version().empty()); } TEST(TVersion, callback_flag) { @@ -1184,6 +1187,10 @@ TEST(TVersion, callback_flag) { auto vers = app.version(); EXPECT_THAT(vers, HasSubstr("VERSION")); + + app.set_version_flag("-v", []() { return std::string("VERSION2 " CLI11_VERSION); }); + auto vers = app.version(); + EXPECT_THAT(vers, HasSubstr("VERSION")); } TEST(TVersion, simple_direct) { From f80431759f2d20f3bb2d80bdb012bda21c139a1a Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 9 Apr 2020 08:07:38 -0700 Subject: [PATCH 6/9] fix compiler error --- tests/HelpTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 07f7513af..4b6ce0a80 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -1189,7 +1189,7 @@ TEST(TVersion, callback_flag) { EXPECT_THAT(vers, HasSubstr("VERSION")); app.set_version_flag("-v", []() { return std::string("VERSION2 " CLI11_VERSION); }); - auto vers = app.version(); + vers = app.version(); EXPECT_THAT(vers, HasSubstr("VERSION")); } From 318e0f76976f58e4dd7f0d33a87cb40e328dce06 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 9 Apr 2020 10:14:07 -0700 Subject: [PATCH 7/9] fix a few comments, and change default version flag to only use "--version" --- examples/CMakeLists.txt | 2 +- include/CLI/App.hpp | 4 ++-- include/CLI/StringTools.hpp | 2 +- include/CLI/TypeTools.hpp | 6 +++--- tests/HelpTest.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index bd9baddb6..8cea1581d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -54,7 +54,7 @@ set_property(TEST simple_all PROPERTY PASS_REGULAR_EXPRESSION "Received flag: 2 (2) times" "Some value: 1.2") -add_test(NAME simple_version COMMAND simple -v) +add_test(NAME simple_version COMMAND simple --version) set_property(TEST simple_version PROPERTY PASS_REGULAR_EXPRESSION "${CLI11_VERSION}") diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 6ea704b98..be149de71 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -746,13 +746,13 @@ class App { } /// Set the version as a string App *version(const std::string &versionString) { - set_version_flag("-v,--version", versionString); + set_version_flag("--version", versionString); return this; } /// Generate the version string through a callback function App *version(std::function vfunc) { - set_version_flag("-v,--version", vfunc); + set_version_flag("--version", vfunc); return this; } diff --git a/include/CLI/StringTools.hpp b/include/CLI/StringTools.hpp index cd861ba2d..70f202aa7 100644 --- a/include/CLI/StringTools.hpp +++ b/include/CLI/StringTools.hpp @@ -190,7 +190,7 @@ inline bool valid_name_string(const std::string &str) { return true; } -/// check if a string is a container segment separator (empty or "%%" +/// check if a string is a container segment separator (empty or "%%") inline bool is_separator(const std::string &str) { static const std::string sep("%%"); return (str.empty() || str == sep); diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp index a4297b2ff..4b85f05c5 100644 --- a/include/CLI/TypeTools.hpp +++ b/include/CLI/TypeTools.hpp @@ -232,7 +232,7 @@ struct is_mutable_container< // check to see if an object is a mutable container (fail by default) template struct is_readable_container : std::false_type {}; -/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, a clear, and an en end +/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, a clear, and an end /// methods and an insert function. And for our purposes we exclude std::string and types that can be constructed from /// a std::string template @@ -244,7 +244,7 @@ struct is_readable_container< // check to see if an object is a wrapper (fail by default) template struct is_wrapper : std::false_type {}; -// check if an object is a is a wrapper (it has a value_type defined) +// check if an object is a wrapper (it has a value_type defined) template struct is_wrapper, void>> : public std::true_type {}; @@ -344,7 +344,7 @@ auto value_string(const T &value) -> decltype(to_string(value)) { return to_string(value); } -/// temple to get the underlying value type if it exists or use a default +/// template to get the underlying value type if it exists or use a default template struct wrapped_type { using type = def; }; /// Type size for regular object types that do not look like a tuple diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 4b6ce0a80..0a273c344 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -1220,7 +1220,7 @@ TEST(TVersion, parse_throw) { app.version(CLI11_VERSION); EXPECT_THROW(app.parse("--version"), CLI::CallForVersion); - EXPECT_THROW(app.parse("-v --arg2 5"), CLI::CallForVersion); + EXPECT_THROW(app.parse("--version --arg2 5"), CLI::CallForVersion); auto ptr = app.get_version_ptr(); From adf201e3886ebb0b8508c47d3fbf07bfefccc493 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 21 May 2020 10:25:42 -0700 Subject: [PATCH 8/9] remove `version` calls and tests --- examples/simple.cpp | 3 +-- include/CLI/App.hpp | 28 ---------------------------- tests/HelpTest.cpp | 43 +++++++++++++++++-------------------------- 3 files changed, 18 insertions(+), 56 deletions(-) diff --git a/examples/simple.cpp b/examples/simple.cpp index fbe2e6857..e969d6f58 100644 --- a/examples/simple.cpp +++ b/examples/simple.cpp @@ -12,8 +12,7 @@ int main(int argc, char **argv) { CLI::App app("K3Pi goofit fitter"); // add version output - app.version(std::string(CLI11_VERSION)); - + app.set_version_flag("--version",std::string(CLI11_VERSION)); std::string file; CLI::Option *opt = app.add_option("-f,--file,file", file, "File name"); diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index be149de71..96952774d 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -744,17 +744,6 @@ class App { return version_ptr_; } - /// Set the version as a string - App *version(const std::string &versionString) { - set_version_flag("--version", versionString); - return this; - } - - /// Generate the version string through a callback function - App *version(std::function vfunc) { - set_version_flag("--version", vfunc); - return this; - } private: /// Internal function for adding a flag @@ -1588,23 +1577,6 @@ class App { return formatter_->make_help(this, prev, mode); } - /// Displays a version string - std::string version() const { - std::string val; - if(version_ptr_ != nullptr) { - auto rv = version_ptr_->results(); - version_ptr_->clear(); - version_ptr_->add_result("true"); - try { - version_ptr_->run_callback(); - } catch(const CLI::CallForVersion &cfv) { - val = cfv.what(); - } - version_ptr_->clear(); - version_ptr_->add_result(rv); - } - return val; - } ///@} /// @name Getters ///@{ diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 0a273c344..15311b48a 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -1166,17 +1166,28 @@ TEST(THelp, FunctionDefaultString) { EXPECT_THAT(help, HasSubstr("INT=Powerful")); } +static std::string getVersion(CLI::App& app, const std::string &args="--version") +{ + try { + app.parse(args); + } + catch (const CLI::CallForVersion& v) + { + return v.what(); + } + return std::string{}; +} TEST(TVersion, simple_flag) { CLI::App app; app.set_version_flag("-v,--version", "VERSION " CLI11_VERSION); - auto vers = app.version(); + auto vers = getVersion(app); EXPECT_THAT(vers, HasSubstr("VERSION")); - + app.allow_extras(); app.set_version_flag(); - EXPECT_TRUE(app.version().empty()); + EXPECT_TRUE(getVersion(app).empty()); } TEST(TVersion, callback_flag) { @@ -1185,31 +1196,11 @@ TEST(TVersion, callback_flag) { app.set_version_flag("-v,--version", []() { return std::string("VERSION " CLI11_VERSION); }); - auto vers = app.version(); + auto vers = getVersion(app); EXPECT_THAT(vers, HasSubstr("VERSION")); app.set_version_flag("-v", []() { return std::string("VERSION2 " CLI11_VERSION); }); - vers = app.version(); - EXPECT_THAT(vers, HasSubstr("VERSION")); -} - -TEST(TVersion, simple_direct) { - - CLI::App app; - - app.version(std::string("VERSION " CLI11_VERSION)); - - auto vers = app.version(); - EXPECT_THAT(vers, HasSubstr("VERSION")); -} - -TEST(TVersion, callback_direct) { - - CLI::App app; - - app.version([]() { return std::string("VERSION " CLI11_VERSION); }); - - auto vers = app.version(); + vers = getVersion(app,"-v"); EXPECT_THAT(vers, HasSubstr("VERSION")); } @@ -1217,7 +1208,7 @@ TEST(TVersion, parse_throw) { CLI::App app; - app.version(CLI11_VERSION); + app.set_version_flag("--version", CLI11_VERSION); EXPECT_THROW(app.parse("--version"), CLI::CallForVersion); EXPECT_THROW(app.parse("--version --arg2 5"), CLI::CallForVersion); From 486fcbf303a08aaf9dd627329ccd5e89de58122e Mon Sep 17 00:00:00 2001 From: Philip Top Date: Thu, 21 May 2020 11:18:53 -0700 Subject: [PATCH 9/9] formatting and add `std::string version()` back in. --- examples/simple.cpp | 2 +- include/CLI/App.hpp | 17 +++++++++++++++++ tests/HelpTest.cpp | 21 +++++---------------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/examples/simple.cpp b/examples/simple.cpp index e969d6f58..c1354eaf3 100644 --- a/examples/simple.cpp +++ b/examples/simple.cpp @@ -12,7 +12,7 @@ int main(int argc, char **argv) { CLI::App app("K3Pi goofit fitter"); // add version output - app.set_version_flag("--version",std::string(CLI11_VERSION)); + app.set_version_flag("--version", std::string(CLI11_VERSION)); std::string file; CLI::Option *opt = app.add_option("-f,--file,file", file, "File name"); diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 96952774d..ad4d950ca 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -1577,6 +1577,23 @@ class App { return formatter_->make_help(this, prev, mode); } + /// Displays a version string + std::string version() const { + std::string val; + if(version_ptr_ != nullptr) { + auto rv = version_ptr_->results(); + version_ptr_->clear(); + version_ptr_->add_result("true"); + try { + version_ptr_->run_callback(); + } catch(const CLI::CallForVersion &cfv) { + val = cfv.what(); + } + version_ptr_->clear(); + version_ptr_->add_result(rv); + } + return val; + } ///@} /// @name Getters ///@{ diff --git a/tests/HelpTest.cpp b/tests/HelpTest.cpp index 15311b48a..161b0b9ee 100644 --- a/tests/HelpTest.cpp +++ b/tests/HelpTest.cpp @@ -1166,28 +1166,17 @@ TEST(THelp, FunctionDefaultString) { EXPECT_THAT(help, HasSubstr("INT=Powerful")); } -static std::string getVersion(CLI::App& app, const std::string &args="--version") -{ - try { - app.parse(args); - } - catch (const CLI::CallForVersion& v) - { - return v.what(); - } - return std::string{}; -} TEST(TVersion, simple_flag) { CLI::App app; app.set_version_flag("-v,--version", "VERSION " CLI11_VERSION); - auto vers = getVersion(app); + auto vers = app.version(); EXPECT_THAT(vers, HasSubstr("VERSION")); - app.allow_extras(); + app.set_version_flag(); - EXPECT_TRUE(getVersion(app).empty()); + EXPECT_TRUE(app.version().empty()); } TEST(TVersion, callback_flag) { @@ -1196,11 +1185,11 @@ TEST(TVersion, callback_flag) { app.set_version_flag("-v,--version", []() { return std::string("VERSION " CLI11_VERSION); }); - auto vers = getVersion(app); + auto vers = app.version(); EXPECT_THAT(vers, HasSubstr("VERSION")); app.set_version_flag("-v", []() { return std::string("VERSION2 " CLI11_VERSION); }); - vers = getVersion(app,"-v"); + vers = app.version(); EXPECT_THAT(vers, HasSubstr("VERSION")); }