From 37667f523d1fe9b343ca0d6bde8bb780baed3126 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 11 Sep 2017 11:45:00 -0400 Subject: [PATCH] Adding simple flag callback (#33) --- .ci/travis.sh | 12 +++++++++++- .travis.yml | 3 ++- CHANGELOG.md | 1 + CMakeLists.txt | 4 +++- README.md | 6 ++++++ include/CLI/App.hpp | 27 +++++++++++++++++++++++++++ include/CLI/Timer.hpp | 6 ++++++ tests/AppTest.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 106 insertions(+), 3 deletions(-) diff --git a/.ci/travis.sh b/.ci/travis.sh index c2108d3..49cc2f8 100755 --- a/.ci/travis.sh +++ b/.ci/travis.sh @@ -3,8 +3,18 @@ set -evx mkdir build || true cd build -cmake .. -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug +cmake .. -DCLI_CXX_STD=11 -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug cmake --build . -- -j2 ctest --output-on-failure +if [ -n "$CLI_CXX_STD" ] && [ "$CLI_CXX_STD" -ge "14" ] ; then + cmake .. -DCLI_CXX_STD=14 -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug + cmake --build . -- -j2 + ctest --output-on-failure +fi +if [ -n "$CLI_CXX_STD" ] && [ "$CLI_CXX_STD" -ge "17" ] ; then + cmake .. -DCLI_CXX_STD=17 -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug + cmake --build . -- -j2 + ctest --output-on-failure +fi set +evx diff --git a/.travis.yml b/.travis.yml index e95a33b..0154fec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ matrix: env: - COMPILER=3.9 - CHECK_STYLE=yes + - CLI_CXX_STD=14 - compiler: clang addons: apt: @@ -41,6 +42,7 @@ matrix: env: - COMPILER=6 - COVERALLS=yes + - CLI_CXX_STD=14 - compiler: gcc addons: apt: @@ -48,7 +50,6 @@ matrix: - g++-4.7 env: - COMPILER=4.7 - - CXXFLAGS=-D_GLIBCXX_USE_NANOSLEEP - os: osx install: - python -c 'import sys; print(sys.version_info[:])' diff --git a/CHANGELOG.md b/CHANGELOG.md index f464228..e891667 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Version 1.2 (in progress) +* Added functional form of flag [#33](https://github.com/CLIUtils/CLI11/pull/33), automatic on C++14 * Fixed Config file search if passed on command line [#30](https://github.com/CLIUtils/CLI11/issues/30) * Added `CLI11_PARSE(app, argc, argv)` macro for simple parse commands (does not support returning arg) * The name string can now contain spaces around commas [#29](https://github.com/CLIUtils/CLI11/pull/29) diff --git a/CMakeLists.txt b/CMakeLists.txt index f8b8e0b..21b88f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,11 @@ project(CLI11 CXX) SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +set(CLI_CXX_STD "11" CACHE STRING "The CMake standard to require") + if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(CUR_PROJ ON) - set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD ${CLI_CXX_STD}) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/README.md b/README.md index c1a4155..fe3de92 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,10 @@ app.add_flag(option_name, int_or_bool = nothing, help_string="") +app.add_flag_function(option_name, + function , + help_string="") + app.add_set(option_name, variable_to_bind_to, set_of_possible_options, @@ -133,6 +137,8 @@ App* subcom = app.add_subcommand(name, discription); An option name must start with a alphabetic character or underscore. For long options, anything but an equals sign or a comma is valid after that. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on help line for its positional form. If you want the default value to print in the help description, pass in `true` for the final parameter for `add_option` or `add_set`. The set options allow your users to pick from a set of predefined options. +On a C++14 compiler, you can pass a callback function directly to `.add_flag`, while in C++11 mode you'll need to use `.add_flag_function` if you want a callback function. The function will be given the number of times the flag was passed. You can throw a `CLI::ParseError` to signal a failure. + ### Example * `"one,-o,--one"`: Valid as long as not a flag, would create an option that can be specified positionally, or with `-o` or `--one` diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index ff0ed38..ff76382 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -370,6 +370,33 @@ class App { return opt; } + /// Add option for callback + Option *add_flag_function(std::string name, + std::function function, ///< A function to call, void(size_t) + std::string description = "") { + + CLI::callback_t fun = [function](CLI::results_t res) { + auto count = static_cast(res.size()); + function(count); + return true; + }; + + Option *opt = add_option(name, fun, description, false); + if(opt->get_positional()) + throw IncorrectConstruction("Flags cannot be positional"); + opt->set_custom_option("", 0); + return opt; + } + +#if __cplusplus >= 201402L + /// Add option for callback (C++14 or better only) + Option *add_flag(std::string name, + std::function function, ///< A function to call, void(size_t) + std::string description = "") { + return add_flag_function(name, function, description); + } +#endif + /// Add set of options (No default) template Option *add_set(std::string name, diff --git a/include/CLI/Timer.hpp b/include/CLI/Timer.hpp index 4457143..eb6054c 100644 --- a/include/CLI/Timer.hpp +++ b/include/CLI/Timer.hpp @@ -3,6 +3,12 @@ // Distributed under the 3-Clause BSD License. See accompanying // file LICENSE or https://github.com/CLIUtils/CLI11 for details. +// On GCC < 4.8, the following define is often missing. Due to the +// fact that this library only uses sleep_for, this should be safe +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 8 +#define _GLIBCXX_USE_NANOSLEEP +#endif + #include #include #include diff --git a/tests/AppTest.cpp b/tests/AppTest.cpp index 2ddb4be..26b74f9 100644 --- a/tests/AppTest.cpp +++ b/tests/AppTest.cpp @@ -243,6 +243,56 @@ TEST_F(TApp, RequiredFlags) { run(); } +TEST_F(TApp, CallbackFlags) { + + int value = 0; + + auto func = [&value](size_t x) { value = x; }; + + app.add_flag_function("-v", func); + + run(); + EXPECT_EQ(value, 0); + + app.reset(); + args = {"-v"}; + run(); + EXPECT_EQ(value, 1); + + app.reset(); + args = {"-vv"}; + run(); + EXPECT_EQ(value, 2); + + EXPECT_THROW(app.add_flag_function("hi", func), CLI::IncorrectConstruction); +} + +#if __cplusplus >= 201402L +TEST_F(TApp, CallbackFlagsAuto) { + + int value = 0; + + auto func = [&value](size_t x) { value = x; }; + + app.add_flag("-v", func); + + run(); + EXPECT_EQ(value, 0); + + app.reset(); + args = {"-v"}; + run(); + EXPECT_EQ(value, 1); + + app.reset(); + args = {"-vv"}; + run(); + EXPECT_EQ(value, 2); + + EXPECT_THROW(app.add_flag("hi", func), CLI::IncorrectConstruction); +} +#endif + TEST_F(TApp, Positionals) { std::string posit1; -- libgit2 0.21.4