Commit 37667f523d1fe9b343ca0d6bde8bb780baed3126
Committed by
GitHub
1 parent
adbd2aa7
Adding simple flag callback (#33)
* Addind simple flag callback * Give flag function a new name, old name only on C++14 * Fixing reference to destroyed function * Better GCC 4.7 support, travis prepared for C++17 (not used yet) * Updating documentation
Showing
8 changed files
with
106 additions
and
3 deletions
.ci/travis.sh
| ... | ... | @@ -3,8 +3,18 @@ set -evx |
| 3 | 3 | |
| 4 | 4 | mkdir build || true |
| 5 | 5 | cd build |
| 6 | -cmake .. -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug | |
| 6 | +cmake .. -DCLI_CXX_STD=11 -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug | |
| 7 | 7 | cmake --build . -- -j2 |
| 8 | 8 | ctest --output-on-failure |
| 9 | +if [ -n "$CLI_CXX_STD" ] && [ "$CLI_CXX_STD" -ge "14" ] ; then | |
| 10 | + cmake .. -DCLI_CXX_STD=14 -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug | |
| 11 | + cmake --build . -- -j2 | |
| 12 | + ctest --output-on-failure | |
| 13 | +fi | |
| 14 | +if [ -n "$CLI_CXX_STD" ] && [ "$CLI_CXX_STD" -ge "17" ] ; then | |
| 15 | + cmake .. -DCLI_CXX_STD=17 -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug | |
| 16 | + cmake --build . -- -j2 | |
| 17 | + ctest --output-on-failure | |
| 18 | +fi | |
| 9 | 19 | |
| 10 | 20 | set +evx | ... | ... |
.travis.yml
| ... | ... | @@ -20,6 +20,7 @@ matrix: |
| 20 | 20 | env: |
| 21 | 21 | - COMPILER=3.9 |
| 22 | 22 | - CHECK_STYLE=yes |
| 23 | + - CLI_CXX_STD=14 | |
| 23 | 24 | - compiler: clang |
| 24 | 25 | addons: |
| 25 | 26 | apt: |
| ... | ... | @@ -41,6 +42,7 @@ matrix: |
| 41 | 42 | env: |
| 42 | 43 | - COMPILER=6 |
| 43 | 44 | - COVERALLS=yes |
| 45 | + - CLI_CXX_STD=14 | |
| 44 | 46 | - compiler: gcc |
| 45 | 47 | addons: |
| 46 | 48 | apt: |
| ... | ... | @@ -48,7 +50,6 @@ matrix: |
| 48 | 50 | - g++-4.7 |
| 49 | 51 | env: |
| 50 | 52 | - COMPILER=4.7 |
| 51 | - - CXXFLAGS=-D_GLIBCXX_USE_NANOSLEEP | |
| 52 | 53 | - os: osx |
| 53 | 54 | install: |
| 54 | 55 | - python -c 'import sys; print(sys.version_info[:])' | ... | ... |
CHANGELOG.md
| 1 | 1 | ## Version 1.2 (in progress) |
| 2 | 2 | |
| 3 | +* Added functional form of flag [#33](https://github.com/CLIUtils/CLI11/pull/33), automatic on C++14 | |
| 3 | 4 | * Fixed Config file search if passed on command line [#30](https://github.com/CLIUtils/CLI11/issues/30) |
| 4 | 5 | * Added `CLI11_PARSE(app, argc, argv)` macro for simple parse commands (does not support returning arg) |
| 5 | 6 | * The name string can now contain spaces around commas [#29](https://github.com/CLIUtils/CLI11/pull/29) | ... | ... |
CMakeLists.txt
| ... | ... | @@ -4,9 +4,11 @@ project(CLI11 CXX) |
| 4 | 4 | |
| 5 | 5 | SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) |
| 6 | 6 | |
| 7 | +set(CLI_CXX_STD "11" CACHE STRING "The CMake standard to require") | |
| 8 | + | |
| 7 | 9 | if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) |
| 8 | 10 | set(CUR_PROJ ON) |
| 9 | - set(CMAKE_CXX_STANDARD 11) | |
| 11 | + set(CMAKE_CXX_STANDARD ${CLI_CXX_STD}) | |
| 10 | 12 | set(CMAKE_CXX_EXTENSIONS OFF) |
| 11 | 13 | set(CMAKE_CXX_STANDARD_REQUIRED ON) |
| 12 | 14 | ... | ... |
README.md
| ... | ... | @@ -120,6 +120,10 @@ app.add_flag(option_name, |
| 120 | 120 | int_or_bool = nothing, |
| 121 | 121 | help_string="") |
| 122 | 122 | |
| 123 | +app.add_flag_function(option_name, | |
| 124 | + function <void(size_t count)>, | |
| 125 | + help_string="") | |
| 126 | + | |
| 123 | 127 | app.add_set(option_name, |
| 124 | 128 | variable_to_bind_to, |
| 125 | 129 | set_of_possible_options, |
| ... | ... | @@ -133,6 +137,8 @@ App* subcom = app.add_subcommand(name, discription); |
| 133 | 137 | |
| 134 | 138 | 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. |
| 135 | 139 | |
| 140 | +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. | |
| 141 | + | |
| 136 | 142 | ### Example |
| 137 | 143 | |
| 138 | 144 | * `"one,-o,--one"`: Valid as long as not a flag, would create an option that can be specified positionally, or with `-o` or `--one` | ... | ... |
include/CLI/App.hpp
| ... | ... | @@ -370,6 +370,33 @@ class App { |
| 370 | 370 | return opt; |
| 371 | 371 | } |
| 372 | 372 | |
| 373 | + /// Add option for callback | |
| 374 | + Option *add_flag_function(std::string name, | |
| 375 | + std::function<void(size_t)> function, ///< A function to call, void(size_t) | |
| 376 | + std::string description = "") { | |
| 377 | + | |
| 378 | + CLI::callback_t fun = [function](CLI::results_t res) { | |
| 379 | + auto count = static_cast<size_t>(res.size()); | |
| 380 | + function(count); | |
| 381 | + return true; | |
| 382 | + }; | |
| 383 | + | |
| 384 | + Option *opt = add_option(name, fun, description, false); | |
| 385 | + if(opt->get_positional()) | |
| 386 | + throw IncorrectConstruction("Flags cannot be positional"); | |
| 387 | + opt->set_custom_option("", 0); | |
| 388 | + return opt; | |
| 389 | + } | |
| 390 | + | |
| 391 | +#if __cplusplus >= 201402L | |
| 392 | + /// Add option for callback (C++14 or better only) | |
| 393 | + Option *add_flag(std::string name, | |
| 394 | + std::function<void(size_t)> function, ///< A function to call, void(size_t) | |
| 395 | + std::string description = "") { | |
| 396 | + return add_flag_function(name, function, description); | |
| 397 | + } | |
| 398 | +#endif | |
| 399 | + | |
| 373 | 400 | /// Add set of options (No default) |
| 374 | 401 | template <typename T> |
| 375 | 402 | Option *add_set(std::string name, | ... | ... |
include/CLI/Timer.hpp
| ... | ... | @@ -3,6 +3,12 @@ |
| 3 | 3 | // Distributed under the 3-Clause BSD License. See accompanying |
| 4 | 4 | // file LICENSE or https://github.com/CLIUtils/CLI11 for details. |
| 5 | 5 | |
| 6 | +// On GCC < 4.8, the following define is often missing. Due to the | |
| 7 | +// fact that this library only uses sleep_for, this should be safe | |
| 8 | +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 && __GNUC_MINOR__ < 8 | |
| 9 | +#define _GLIBCXX_USE_NANOSLEEP | |
| 10 | +#endif | |
| 11 | + | |
| 6 | 12 | #include <chrono> |
| 7 | 13 | #include <functional> |
| 8 | 14 | #include <iostream> | ... | ... |
tests/AppTest.cpp
| ... | ... | @@ -243,6 +243,56 @@ TEST_F(TApp, RequiredFlags) { |
| 243 | 243 | run(); |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | +TEST_F(TApp, CallbackFlags) { | |
| 247 | + | |
| 248 | + int value = 0; | |
| 249 | + | |
| 250 | + auto func = [&value](size_t x) { value = x; }; | |
| 251 | + | |
| 252 | + app.add_flag_function("-v", func); | |
| 253 | + | |
| 254 | + run(); | |
| 255 | + EXPECT_EQ(value, 0); | |
| 256 | + | |
| 257 | + app.reset(); | |
| 258 | + args = {"-v"}; | |
| 259 | + run(); | |
| 260 | + EXPECT_EQ(value, 1); | |
| 261 | + | |
| 262 | + app.reset(); | |
| 263 | + args = {"-vv"}; | |
| 264 | + run(); | |
| 265 | + EXPECT_EQ(value, 2); | |
| 266 | + | |
| 267 | + EXPECT_THROW(app.add_flag_function("hi", func), CLI::IncorrectConstruction); | |
| 268 | +} | |
| 269 | + | |
| 270 | +#if __cplusplus >= 201402L | |
| 271 | +TEST_F(TApp, CallbackFlagsAuto) { | |
| 272 | + | |
| 273 | + int value = 0; | |
| 274 | + | |
| 275 | + auto func = [&value](size_t x) { value = x; }; | |
| 276 | + | |
| 277 | + app.add_flag("-v", func); | |
| 278 | + | |
| 279 | + run(); | |
| 280 | + EXPECT_EQ(value, 0); | |
| 281 | + | |
| 282 | + app.reset(); | |
| 283 | + args = {"-v"}; | |
| 284 | + run(); | |
| 285 | + EXPECT_EQ(value, 1); | |
| 286 | + | |
| 287 | + app.reset(); | |
| 288 | + args = {"-vv"}; | |
| 289 | + run(); | |
| 290 | + EXPECT_EQ(value, 2); | |
| 291 | + | |
| 292 | + EXPECT_THROW(app.add_flag("hi", func), CLI::IncorrectConstruction); | |
| 293 | +} | |
| 294 | +#endif | |
| 295 | + | |
| 246 | 296 | TEST_F(TApp, Positionals) { |
| 247 | 297 | |
| 248 | 298 | std::string posit1; | ... | ... |