From 476a9593d92a2c0eb41a827e6e2d60d240b805e3 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Tue, 21 Jul 2020 00:14:16 +0200 Subject: [PATCH] git subrepo pull packages/CLI11 subrepo: subdir: "packages/CLI11" merged: "2b059cbdb" upstream: origin: "git@github.com:CLIUtils/CLI11.git" branch: "master" commit: "2b059cbdb" git-subrepo: version: "0.4.1" origin: "git@github.com:ingydotnet/git-subrepo.git" commit: "a04d8c2" Also add 'required' option for script filename --- packages/CLI11/.all-contributorsrc | 18 +++ packages/CLI11/.clang-tidy | 14 +-- .../.github/actions/cmake_config/Dockerfile | 2 +- packages/CLI11/.github/workflows/tests.yml | 15 ++- packages/CLI11/.gitrepo | 4 +- packages/CLI11/CHANGELOG.md | 34 ++++++ packages/CLI11/CMakeLists.txt | 33 ++++-- packages/CLI11/README.md | 4 +- packages/CLI11/azure-pipelines.yml | 11 ++ packages/CLI11/book/chapters/config.md | 2 +- packages/CLI11/examples/CMakeLists.txt | 3 + packages/CLI11/examples/simple.cpp | 3 +- packages/CLI11/extern/googletest | 2 +- packages/CLI11/include/CLI/App.hpp | 111 ++++++++++++++++-- packages/CLI11/include/CLI/CLI.hpp | 26 ++-- packages/CLI11/include/CLI/Config.hpp | 6 +- packages/CLI11/include/CLI/ConfigFwd.hpp | 4 +- packages/CLI11/include/CLI/Error.hpp | 17 ++- packages/CLI11/include/CLI/Formatter.hpp | 4 +- packages/CLI11/include/CLI/FormatterFwd.hpp | 2 +- packages/CLI11/include/CLI/Option.hpp | 18 +-- packages/CLI11/include/CLI/Split.hpp | 4 +- packages/CLI11/include/CLI/StringTools.hpp | 2 +- packages/CLI11/include/CLI/TypeTools.hpp | 6 +- packages/CLI11/include/CLI/Validators.hpp | 6 +- packages/CLI11/scripts/MakeSingleHeader.py | 3 +- packages/CLI11/tests/HelpTest.cpp | 50 ++++++++ packages/CLI11/tests/OptionGroupTest.cpp | 12 ++ src/utils/PugsUtils.cpp | 2 +- 29 files changed, 326 insertions(+), 92 deletions(-) diff --git a/packages/CLI11/.all-contributorsrc b/packages/CLI11/.all-contributorsrc index abdeb6b26..b95934e25 100644 --- a/packages/CLI11/.all-contributorsrc +++ b/packages/CLI11/.all-contributorsrc @@ -359,6 +359,24 @@ "contributions": [ "platform" ] + }, + { + "login": "certik", + "name": "Ondřej Čertík", + "avatar_url": "https://avatars3.githubusercontent.com/u/20568?v=4", + "profile": "https://ondrejcertik.com/", + "contributions": [ + "bug" + ] + }, + { + "login": "samhocevar", + "name": "Sam Hocevar", + "avatar_url": "https://avatars2.githubusercontent.com/u/245089?v=4", + "profile": "http://sam.hocevar.net/", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/packages/CLI11/.clang-tidy b/packages/CLI11/.clang-tidy index c9b6458fc..09875c87a 100644 --- a/packages/CLI11/.clang-tidy +++ b/packages/CLI11/.clang-tidy @@ -6,26 +6,16 @@ FormatStyle: file Checks: ' -*, google-*, --google-runtime-int, -google-runtime-references, llvm-include-order, llvm-namespace-comment, misc-throw-by-value-catch-by-reference, modernize*, +-modernize-use-trailing-return-type, readability-container-size-empty, ' -WarningsAsErrors: ' --*, -google-*, --google-runtime-int, --google-runtime-references, -llvm-include-order, -llvm-namespace-comment, -misc-throw-by-value-catch-by-reference, -modernize*, -readability-container-size-empty, -' +WarningsAsErrors: '*' HeaderFilterRegex: '.*hpp' diff --git a/packages/CLI11/.github/actions/cmake_config/Dockerfile b/packages/CLI11/.github/actions/cmake_config/Dockerfile index 81eb9b996..63b28a994 100644 --- a/packages/CLI11/.github/actions/cmake_config/Dockerfile +++ b/packages/CLI11/.github/actions/cmake_config/Dockerfile @@ -7,7 +7,7 @@ RUN apt-get update \ libidn11=1.33-2.1ubuntu1.2 \ ca-certificates=20180409 \ make=4.1-9.1ubuntu1 \ - git=1:2.17.1-1ubuntu0.5 \ + git=1:2.17.1-1ubuntu0.7 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/packages/CLI11/.github/workflows/tests.yml b/packages/CLI11/.github/workflows/tests.yml index c3c832bc6..86cc78ec2 100644 --- a/packages/CLI11/.github/workflows/tests.yml +++ b/packages/CLI11/.github/workflows/tests.yml @@ -13,15 +13,15 @@ jobs: name: Formatting runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-python@v1 + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 - name: set PY - run: echo "::set-env name=PY::$(python --version --version | sha256sum | cut -d' ' -f1)" + run: echo "::set-env name=PY::$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" - uses: actions/cache@v1 with: path: ~/.cache/pre-commit key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} - - uses: pre-commit/action@v1.0.0 + - uses: pre-commit/action@v1.1.0 cuda-build: name: CUDA build only @@ -107,9 +107,14 @@ jobs: with: version: 3.15.6 if: success() || failure() + - name: CMake 3.16 + uses: ./.github/actions/cmake_config + with: + version: 3.16.8 + if: success() || failure() - name: CMake 3.16 (full) uses: ./.github/actions/cmake_config with: - version: 3.16.2 + version: 3.17.3 options: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON if: success() || failure() diff --git a/packages/CLI11/.gitrepo b/packages/CLI11/.gitrepo index 313778e5c..4b4e25a2b 100644 --- a/packages/CLI11/.gitrepo +++ b/packages/CLI11/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@github.com:CLIUtils/CLI11.git branch = master - commit = b9a2f320b912aae623c4acddea06cba399b98654 - parent = 73e054c98d4a424c44972eb708495c40dfa0dbac + commit = 2b059cbdbe844450e1675a5dda3cb8acb1147631 + parent = fb9f84797173b01c7277657b883e954800be1fc9 cmdver = 0.4.1 method = merge diff --git a/packages/CLI11/CHANGELOG.md b/packages/CLI11/CHANGELOG.md index f753569eb..f9cc853b7 100644 --- a/packages/CLI11/CHANGELOG.md +++ b/packages/CLI11/CHANGELOG.md @@ -1,3 +1,37 @@ +## Version 2.0: In progress + +* Built-in config format is TOML compliant now [#435] +* Config updates [#442] +* More powerful containers, `%%` separator [#423] +* Add a version flag easily [#452] + +[#435]: https://github.com/CLIUtils/CLI11/pull/435 +[#443]: https://github.com/CLIUtils/CLI11/pull/443 +[#423]: https://github.com/CLIUtils/CLI11/pull/423 +[#452]: https://github.com/CLIUtils/CLI11/pull/452 + + +### Version 1.9.1: Backporting fixes + +This is a patch version that backports fixes from the development of 2.0. + +* Support relative inclusion [#475][] +* Fix cases where spaces in paths could break CMake support [#471][] +* Fix an issue with string conversion [#421][] +* Cross-compiling improvement for Conan.io [#430][] +* Fix option group default propagation [#450][] +* Fix for C++20 [#459][] +* Support compiling with RTTI off [#461][] + +[#421]: https://github.com/CLIUtils/CLI11/pull/421 +[#430]: https://github.com/CLIUtils/CLI11/pull/430 +[#450]: https://github.com/CLIUtils/CLI11/pull/450 +[#459]: https://github.com/CLIUtils/CLI11/pull/459 +[#461]: https://github.com/CLIUtils/CLI11/pull/461 +[#471]: https://github.com/CLIUtils/CLI11/pull/471 +[#475]: https://github.com/CLIUtils/CLI11/pull/475 + + ## Version 1.9: Config files and cleanup Config file handling was revamped to fix common issues, and now supports reading [TOML](https://github.com/toml-lang/toml). diff --git a/packages/CLI11/CMakeLists.txt b/packages/CLI11/CMakeLists.txt index e7c2695e1..574ca1ee8 100644 --- a/packages/CLI11/CMakeLists.txt +++ b/packages/CLI11/CMakeLists.txt @@ -4,12 +4,12 @@ cmake_minimum_required(VERSION 3.4) # Make sure users don't get warnings on a tested (3.4 to 3.16) version # of CMake. For most of the policies, the new version is better (hence the change). -# We don't use the 3.4...3.16 syntax because of a bug in an older MSVC's +# We don't use the 3.4...3.17 syntax because of a bug in an older MSVC's # built-in and modified CMake 3.11 -if(${CMAKE_VERSION} VERSION_LESS 3.16) +if(${CMAKE_VERSION} VERSION_LESS 3.17) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.16) + cmake_policy(VERSION 3.17) endif() set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"") @@ -46,7 +46,20 @@ list(APPEND force-libcxx "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME") list(APPEND build-docs "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME") list(APPEND build-docs "NOT CMAKE_VERSION VERSION_LESS 3.11") list(APPEND build-docs "Doxygen_FOUND") -list(APPEND build-docs "EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/docs") + +# Necessary to support paths with spaces, see #457 +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/docs") + set(docs_EXIST TRUE) +else() + set(docs_EXIST FALSE) +endif() +list(APPEND build-docs "docs_EXIST") + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples") + set(examples_EXIST TRUE) +else() + set(examples_EXIST FALSE) +endif() option(CLI11_WARNINGS_AS_ERRORS "Turn all warnings into errors (for CI)") option(CLI11_SINGLE_FILE "Generate a single header file") @@ -64,7 +77,7 @@ cmake_dependent_option(CLI11_BUILD_TESTS cmake_dependent_option(CLI11_BUILD_EXAMPLES "Build CLI11 examples" ON - "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/examples" OFF) + "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;${examples_EXIST}" OFF) cmake_dependent_option(CLI11_BUILD_EXAMPLES_JSON "Build CLI11 json example" OFF @@ -181,8 +194,8 @@ endif() # This folder should be installed if(CLI11_INSTALL) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") # Make an export target install(TARGETS CLI11 EXPORT CLI11Targets) @@ -198,13 +211,13 @@ if(CLI11_INSTALL) # Make version available in the install install(FILES "${PROJECT_BINARY_DIR}/CLI11ConfigVersion.cmake" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CLI11) + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CLI11") # Install the export target as a file install(EXPORT CLI11Targets FILE CLI11Config.cmake NAMESPACE CLI11:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CLI11) + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CLI11") # Use find_package on the installed package export(TARGETS CLI11 @@ -239,7 +252,7 @@ if(CLI11_SINGLE_FILE) add_custom_target(CLI11-generate-single-file ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp") set_property(TARGET CLI11-generate-single-file PROPERTY FOLDER "Scripts") - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp" DESTINATION include) add_library(CLI11_SINGLE INTERFACE) target_link_libraries(CLI11_SINGLE INTERFACE CLI11) diff --git a/packages/CLI11/README.md b/packages/CLI11/README.md index e98f2175a..d3552752b 100644 --- a/packages/CLI11/README.md +++ b/packages/CLI11/README.md @@ -926,6 +926,8 @@ This project was created by [Henry Schreiner](https://github.com/henryiii) and m <tr> <td align="center"><a href="https://github.com/jsoref"><img src="https://avatars0.githubusercontent.com/u/2119212?v=4" width="100px;" alt=""/><br /><sub><b>Josh Soref</b></sub></a><br /><a href="#tool-jsoref" title="Tools">🔧</a></td> <td align="center"><a href="https://github.com/geir-t"><img src="https://avatars3.githubusercontent.com/u/35292136?v=4" width="100px;" alt=""/><br /><sub><b>geir-t</b></sub></a><br /><a href="#platform-geir-t" title="Packaging/porting to new platform">📦</a></td> + <td align="center"><a href="https://ondrejcertik.com/"><img src="https://avatars3.githubusercontent.com/u/20568?v=4" width="100px;" alt=""/><br /><sub><b>Ondřej Čertík</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/issues?q=author%3Acertik" title="Bug reports">🐛</a></td> + <td align="center"><a href="http://sam.hocevar.net/"><img src="https://avatars2.githubusercontent.com/u/245089?v=4" width="100px;" alt=""/><br /><sub><b>Sam Hocevar</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=samhocevar" title="Code">💻</a></td> </tr> </table> @@ -945,7 +947,7 @@ CLI11 was developed at the [University of Cincinnati][] to support of the [GooFi [doi-badge]: https://zenodo.org/badge/80064252.svg [doi-link]: https://zenodo.org/badge/latestdoi/80064252 [azure-badge]: https://dev.azure.com/CLIUtils/CLI11/_apis/build/status/CLIUtils.CLI11?branchName=master -[azure]: https://dev.azure.com/CLIUtils/CLI11/_build/latest?definitionId=1&branchName=master +[azure]: https://dev.azure.com/CLIUtils/CLI11 [travis-badge]: https://img.shields.io/travis/CLIUtils/CLI11/master.svg?label=Linux/macOS [travis]: https://travis-ci.org/CLIUtils/CLI11 [appveyor-badge]: https://img.shields.io/appveyor/ci/HenrySchreiner/cli11/master.svg?label=AppVeyor diff --git a/packages/CLI11/azure-pipelines.yml b/packages/CLI11/azure-pipelines.yml index 7d2d7f400..90017c62f 100644 --- a/packages/CLI11/azure-pipelines.yml +++ b/packages/CLI11/azure-pipelines.yml @@ -5,9 +5,11 @@ trigger: - master +- 'v*' pr: - master +- 'v*' variables: cli11.single: ON @@ -62,7 +64,12 @@ jobs: cli11.std: 11 Windowslatest: vmImage: 'windows-2019' + cli11.std: 20 + cli11.options: -DCMAKE_CXX_FLAGS="/std:c++latest /EHsc" + Linux17nortti: + vmImage: 'ubuntu-latest' cli11.std: 17 + cli11.options: -DCMAKE_CXX_FLAGS="-fno-rtti" pool: vmImage: $(vmImage) steps: @@ -113,6 +120,10 @@ jobs: containerImage: silkeh/clang:8 cli11.std: 17 cli11.options: -DCLI11_FORCE_LIBCXX=ON + clang10_20: + containerImage: helics/buildenv:clang10-builder + cli11.std: 20 + cli11.options: -DCLI11_FORCE_LIBCXX=ON -DCMAKE_CXX_FLAGS=-std=c++20 container: $[ variables['containerImage'] ] steps: - template: .ci/azure-cmake.yml diff --git a/packages/CLI11/book/chapters/config.md b/packages/CLI11/book/chapters/config.md index a9edf9aac..fd2dbd7d9 100644 --- a/packages/CLI11/book/chapters/config.md +++ b/packages/CLI11/book/chapters/config.md @@ -135,7 +135,7 @@ The default configuration file will read INI files, but will write out files in ```cpp app.config_formatter(std::make_shared<CLI::ConfigINI>()); ``` -which makes use of a predefined modification of the ConfigBase class which TOML also uses. If a custom formatter is used that is not inheriting from the from ConfigBase class `get_config_formatter_base() will return a nullptr, so some care must be exercised in its us with custom configurations. +which makes use of a predefined modification of the ConfigBase class which TOML also uses. If a custom formatter is used that is not inheriting from the from ConfigBase class `get_config_formatter_base() will return a nullptr if RTTI is on (usually the default), or garbage if RTTI is off, so some care must be exercised in its use with custom configurations. ## Custom formats diff --git a/packages/CLI11/examples/CMakeLists.txt b/packages/CLI11/examples/CMakeLists.txt index 2359d5cd8..8cea1581d 100644 --- a/packages/CLI11/examples/CMakeLists.txt +++ b/packages/CLI11/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 --version) +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/packages/CLI11/examples/simple.cpp b/packages/CLI11/examples/simple.cpp index 2d465cb22..c1354eaf3 100644 --- a/packages/CLI11/examples/simple.cpp +++ b/packages/CLI11/examples/simple.cpp @@ -11,7 +11,8 @@ int main(int argc, char **argv) { CLI::App app("K3Pi goofit fitter"); - + // add version output + 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/packages/CLI11/extern/googletest b/packages/CLI11/extern/googletest index 703bd9caa..859bfe898 160000 --- a/packages/CLI11/extern/googletest +++ b/packages/CLI11/extern/googletest @@ -1 +1 @@ -Subproject commit 703bd9caab50b139428cea1aaff9974ebee5742e +Subproject commit 859bfe8981d6724c4ea06e73d29accd8588f3230 diff --git a/packages/CLI11/include/CLI/App.hpp b/packages/CLI11/include/CLI/App.hpp index 2a2414d13..8d47976e5 100644 --- a/packages/CLI11/include/CLI/App.hpp +++ b/packages/CLI11/include/CLI/App.hpp @@ -20,14 +20,14 @@ #include <vector> // CLI Library includes -#include "CLI/ConfigFwd.hpp" -#include "CLI/Error.hpp" -#include "CLI/FormatterFwd.hpp" -#include "CLI/Macros.hpp" -#include "CLI/Option.hpp" -#include "CLI/Split.hpp" -#include "CLI/StringTools.hpp" -#include "CLI/TypeTools.hpp" +#include "ConfigFwd.hpp" +#include "Error.hpp" +#include "FormatterFwd.hpp" +#include "Macros.hpp" +#include "Option.hpp" +#include "Split.hpp" +#include "StringTools.hpp" +#include "TypeTools.hpp" namespace CLI { @@ -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<FormatterBase> formatter_{new Formatter()}; @@ -703,6 +706,45 @@ 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 &versionString = "") { + // 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 version flag + if(!flag_name.empty()) { + version_ptr_ = add_flag_callback( + flag_name, + [versionString]() { throw(CLI::CallForVersion(versionString, 0)); }, + "Display program version information and exit"); + version_ptr_->configurable(false); + } + + return version_ptr_; + } + /// Generate the version string through a callback function + Option *set_version_flag(std::string flag_name, std::function<std::string()> vfunc) { + // 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 version 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) { @@ -993,7 +1035,7 @@ class App { /// creates an option group as part of the given app template <typename T = Option_group> T *add_option_group(std::string group_name, std::string group_description = "") { - auto option_group = std::make_shared<T>(std::move(group_description), group_name, nullptr); + auto option_group = std::make_shared<T>(std::move(group_description), group_name, this); auto ptr = option_group.get(); // move to App_p for overload resolution on older gcc versions App_p app_ptr = std::dynamic_pointer_cast<App>(option_group); @@ -1332,19 +1374,24 @@ class App { int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const { /// Avoid printing anything if this is a CLI::RuntimeError - if(dynamic_cast<const CLI::RuntimeError *>(&e) != nullptr) + if(e.get_name() == "RuntimeError") return e.get_exit_code(); - if(dynamic_cast<const CLI::CallForHelp *>(&e) != nullptr) { + if(e.get_name() == "CallForHelp") { out << help(); return e.get_exit_code(); } - if(dynamic_cast<const CLI::CallForAllHelp *>(&e) != nullptr) { + if(e.get_name() == "CallForAllHelp") { out << help("", AppFormatMode::All); return e.get_exit_code(); } + if(e.get_name() == "CallForVersion") { + out << e.what() << std::endl; + return e.get_exit_code(); + } + if(e.get_exit_code() != static_cast<int>(ExitCodes::Success)) { if(failure_message_) err << failure_message_(this, e) << std::flush; @@ -1530,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 ///@{ @@ -1542,7 +1606,12 @@ class App { /// Access the config formatter as a configBase pointer std::shared_ptr<ConfigBase> get_config_formatter_base() const { + // This is safer as a dynamic_cast if we have RTTI, as Config -> ConfigBase +#if defined(__cpp_rtti) || (defined(__GXX_RTTI) && __GXX_RTTI) || (defined(_HAS_STATIC_RTTI) && (_HAS_STATIC_RTTI == 0)) return std::dynamic_pointer_cast<ConfigBase>(config_formatter_); +#else + return std::static_pointer_cast<ConfigBase>(config_formatter_); +#endif } /// Get the app or subcommand description @@ -1726,6 +1795,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_; } @@ -3086,7 +3161,18 @@ inline std::string help(const App *app, const Error &e) { namespace detail { /// This class is simply to allow tests access to App's protected functions struct AppFriend { +#ifdef CLI11_CPP14 + /// Wrap _parse_short, perfectly forward arguments and return + template <typename... Args> static decltype(auto) parse_arg(App *app, Args &&... args) { + return app->_parse_arg(std::forward<Args>(args)...); + } + + /// Wrap _parse_subcommand, perfectly forward arguments and return + template <typename... Args> static decltype(auto) parse_subcommand(App *app, Args &&... args) { + return app->_parse_subcommand(std::forward<Args>(args)...); + } +#else /// Wrap _parse_short, perfectly forward arguments and return template <typename... Args> static auto parse_arg(App *app, Args &&... args) -> @@ -3100,6 +3186,7 @@ struct AppFriend { typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type { return app->_parse_subcommand(std::forward<Args>(args)...); } +#endif /// Wrap the fallthrough parent function to make sure that is working correctly static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); } }; diff --git a/packages/CLI11/include/CLI/CLI.hpp b/packages/CLI11/include/CLI/CLI.hpp index 22e85aed1..98fca5488 100644 --- a/packages/CLI11/include/CLI/CLI.hpp +++ b/packages/CLI11/include/CLI/CLI.hpp @@ -9,28 +9,28 @@ // CLI Library includes // Order is important for combiner script -#include "CLI/Version.hpp" +#include "Version.hpp" -#include "CLI/Macros.hpp" +#include "Macros.hpp" -#include "CLI/StringTools.hpp" +#include "StringTools.hpp" -#include "CLI/Error.hpp" +#include "Error.hpp" -#include "CLI/TypeTools.hpp" +#include "TypeTools.hpp" -#include "CLI/Split.hpp" +#include "Split.hpp" -#include "CLI/ConfigFwd.hpp" +#include "ConfigFwd.hpp" -#include "CLI/Validators.hpp" +#include "Validators.hpp" -#include "CLI/FormatterFwd.hpp" +#include "FormatterFwd.hpp" -#include "CLI/Option.hpp" +#include "Option.hpp" -#include "CLI/App.hpp" +#include "App.hpp" -#include "CLI/Config.hpp" +#include "Config.hpp" -#include "CLI/Formatter.hpp" +#include "Formatter.hpp" diff --git a/packages/CLI11/include/CLI/Config.hpp b/packages/CLI11/include/CLI/Config.hpp index 8ef40552e..5a982236c 100644 --- a/packages/CLI11/include/CLI/Config.hpp +++ b/packages/CLI11/include/CLI/Config.hpp @@ -13,9 +13,9 @@ #include <utility> #include <vector> -#include "CLI/App.hpp" -#include "CLI/ConfigFwd.hpp" -#include "CLI/StringTools.hpp" +#include "App.hpp" +#include "ConfigFwd.hpp" +#include "StringTools.hpp" namespace CLI { diff --git a/packages/CLI11/include/CLI/ConfigFwd.hpp b/packages/CLI11/include/CLI/ConfigFwd.hpp index 49ca1b288..2546d1352 100644 --- a/packages/CLI11/include/CLI/ConfigFwd.hpp +++ b/packages/CLI11/include/CLI/ConfigFwd.hpp @@ -12,8 +12,8 @@ #include <string> #include <vector> -#include "CLI/Error.hpp" -#include "CLI/StringTools.hpp" +#include "Error.hpp" +#include "StringTools.hpp" namespace CLI { diff --git a/packages/CLI11/include/CLI/Error.hpp b/packages/CLI11/include/CLI/Error.hpp index 0adf15c50..11feaedbc 100644 --- a/packages/CLI11/include/CLI/Error.hpp +++ b/packages/CLI11/include/CLI/Error.hpp @@ -13,7 +13,7 @@ #include <vector> // CLI library includes -#include "CLI/StringTools.hpp" +#include "StringTools.hpp" namespace CLI { @@ -157,18 +157,25 @@ 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 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. class RuntimeError : public ParseError { CLI11_ERROR_DEF(ParseError, RuntimeError) diff --git a/packages/CLI11/include/CLI/Formatter.hpp b/packages/CLI11/include/CLI/Formatter.hpp index 6ac4e4d1a..8a8ba3526 100644 --- a/packages/CLI11/include/CLI/Formatter.hpp +++ b/packages/CLI11/include/CLI/Formatter.hpp @@ -10,8 +10,8 @@ #include <string> #include <vector> -#include "CLI/App.hpp" -#include "CLI/FormatterFwd.hpp" +#include "App.hpp" +#include "FormatterFwd.hpp" namespace CLI { diff --git a/packages/CLI11/include/CLI/FormatterFwd.hpp b/packages/CLI11/include/CLI/FormatterFwd.hpp index 4c4a5de05..362219e24 100644 --- a/packages/CLI11/include/CLI/FormatterFwd.hpp +++ b/packages/CLI11/include/CLI/FormatterFwd.hpp @@ -11,7 +11,7 @@ #include <utility> #include <vector> -#include "CLI/StringTools.hpp" +#include "StringTools.hpp" namespace CLI { diff --git a/packages/CLI11/include/CLI/Option.hpp b/packages/CLI11/include/CLI/Option.hpp index 911dd64b2..e98000284 100644 --- a/packages/CLI11/include/CLI/Option.hpp +++ b/packages/CLI11/include/CLI/Option.hpp @@ -15,11 +15,11 @@ #include <utility> #include <vector> -#include "CLI/Error.hpp" -#include "CLI/Macros.hpp" -#include "CLI/Split.hpp" -#include "CLI/StringTools.hpp" -#include "CLI/Validators.hpp" +#include "Error.hpp" +#include "Macros.hpp" +#include "Split.hpp" +#include "StringTools.hpp" +#include "Validators.hpp" namespace CLI { @@ -508,7 +508,7 @@ class Option : public OptionBase<Option> { /// Can find a string if needed template <typename T = App> Option *needs(std::string opt_name) { - auto opt = dynamic_cast<T *>(parent_)->get_option_no_throw(opt_name); + auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name); if(opt == nullptr) { throw IncorrectConstruction::MissingOption(opt_name); } @@ -550,7 +550,7 @@ class Option : public OptionBase<Option> { /// Can find a string if needed template <typename T = App> Option *excludes(std::string opt_name) { - auto opt = dynamic_cast<T *>(parent_)->get_option_no_throw(opt_name); + auto opt = static_cast<T *>(parent_)->get_option_no_throw(opt_name); if(opt == nullptr) { throw IncorrectConstruction::MissingOption(opt_name); } @@ -587,7 +587,7 @@ class Option : public OptionBase<Option> { template <typename T = App> Option *ignore_case(bool value = true) { if(!ignore_case_ && value) { ignore_case_ = value; - auto *parent = dynamic_cast<T *>(parent_); + auto *parent = static_cast<T *>(parent_); for(const Option_p &opt : parent->options_) { if(opt.get() == this) { continue; @@ -612,7 +612,7 @@ class Option : public OptionBase<Option> { if(!ignore_underscore_ && value) { ignore_underscore_ = value; - auto *parent = dynamic_cast<T *>(parent_); + auto *parent = static_cast<T *>(parent_); for(const Option_p &opt : parent->options_) { if(opt.get() == this) { continue; diff --git a/packages/CLI11/include/CLI/Split.hpp b/packages/CLI11/include/CLI/Split.hpp index 7e534732d..6306404bc 100644 --- a/packages/CLI11/include/CLI/Split.hpp +++ b/packages/CLI11/include/CLI/Split.hpp @@ -11,8 +11,8 @@ #include <utility> #include <vector> -#include "CLI/Error.hpp" -#include "CLI/StringTools.hpp" +#include "Error.hpp" +#include "StringTools.hpp" namespace CLI { namespace detail { diff --git a/packages/CLI11/include/CLI/StringTools.hpp b/packages/CLI11/include/CLI/StringTools.hpp index cd861ba2d..70f202aa7 100644 --- a/packages/CLI11/include/CLI/StringTools.hpp +++ b/packages/CLI11/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/packages/CLI11/include/CLI/TypeTools.hpp b/packages/CLI11/include/CLI/TypeTools.hpp index a4297b2ff..4b85f05c5 100644 --- a/packages/CLI11/include/CLI/TypeTools.hpp +++ b/packages/CLI11/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 <typename T, typename _ = void> 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 <typename T> @@ -244,7 +244,7 @@ struct is_readable_container< // check to see if an object is a wrapper (fail by default) template <typename T, typename _ = void> 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 <typename T> struct is_wrapper<T, conditional_t<false, void_t<typename T::value_type>, 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 <typename T, typename def, typename Enable = void> struct wrapped_type { using type = def; }; /// Type size for regular object types that do not look like a tuple diff --git a/packages/CLI11/include/CLI/Validators.hpp b/packages/CLI11/include/CLI/Validators.hpp index 9f47477db..bc916f861 100644 --- a/packages/CLI11/include/CLI/Validators.hpp +++ b/packages/CLI11/include/CLI/Validators.hpp @@ -6,9 +6,9 @@ #pragma once -#include "CLI/Macros.hpp" -#include "CLI/StringTools.hpp" -#include "CLI/TypeTools.hpp" +#include "Macros.hpp" +#include "StringTools.hpp" +#include "TypeTools.hpp" #include <cmath> #include <cstdint> diff --git a/packages/CLI11/scripts/MakeSingleHeader.py b/packages/CLI11/scripts/MakeSingleHeader.py index 1163485a3..1c4385826 100755 --- a/packages/CLI11/scripts/MakeSingleHeader.py +++ b/packages/CLI11/scripts/MakeSingleHeader.py @@ -128,6 +128,7 @@ def MakeHeader( base_dir = os.path.abspath(os.path.join(DIR, include_dir)) main_header = os.path.join(base_dir, main_header) + header_dir = os.path.dirname(main_header) licence_file = os.path.abspath(os.path.join(DIR, "../LICENSE")) with open(licence_file) as f: @@ -138,7 +139,7 @@ def MakeHeader( include_files = includes_local.findall(header) - headers = [HeaderFile(base_dir, inc) for inc in include_files] + headers = [HeaderFile(header_dir, inc) for inc in include_files] single_header = reduce(add, headers) if macro is not None: diff --git a/packages/CLI11/tests/HelpTest.cpp b/packages/CLI11/tests/HelpTest.cpp index 68d96d13b..161b0b9ee 100644 --- a/packages/CLI11/tests/HelpTest.cpp +++ b/packages/CLI11/tests/HelpTest.cpp @@ -1165,3 +1165,53 @@ 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")); + + app.set_version_flag(); + EXPECT_TRUE(app.version().empty()); +} + +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")); + + app.set_version_flag("-v", []() { return std::string("VERSION2 " CLI11_VERSION); }); + vers = app.version(); + EXPECT_THAT(vers, HasSubstr("VERSION")); +} + +TEST(TVersion, parse_throw) { + + CLI::App app; + + app.set_version_flag("--version", CLI11_VERSION); + + EXPECT_THROW(app.parse("--version"), CLI::CallForVersion); + EXPECT_THROW(app.parse("--version --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); + } +} diff --git a/packages/CLI11/tests/OptionGroupTest.cpp b/packages/CLI11/tests/OptionGroupTest.cpp index 51bb9fd26..e510c1a39 100644 --- a/packages/CLI11/tests/OptionGroupTest.cpp +++ b/packages/CLI11/tests/OptionGroupTest.cpp @@ -374,6 +374,18 @@ TEST_F(TApp, InvalidOptions) { EXPECT_THROW(ogroup->add_option(opt), CLI::OptionNotFound); } +TEST_F(TApp, OptionGroupInheritedOptionDefaults) { + app.option_defaults()->ignore_case(); + auto ogroup = app.add_option_group("clusters"); + int res{0}; + ogroup->add_option("--test1", res); + + args = {"--Test1", "5"}; + run(); + EXPECT_EQ(res, 5); + EXPECT_EQ(app.count_all(), 1u); +} + struct ManyGroups : public TApp { CLI::Option_group *main{nullptr}; diff --git a/src/utils/PugsUtils.cpp b/src/utils/PugsUtils.cpp index de9e8830f..7ea50b0ed 100644 --- a/src/utils/PugsUtils.cpp +++ b/src/utils/PugsUtils.cpp @@ -48,7 +48,7 @@ initialize(int& argc, char* argv[]) { CLI::App app{"Pugs help"}; - app.add_option("filename,-f,--filename", filename, "pugs script file")->check(CLI::ExistingFile); + app.add_option("filename", filename, "pugs script file")->required()->check(CLI::ExistingFile); int threads = -1; app.add_option("--threads", threads, "Number of Kokkos threads") -- GitLab