Commit 518615844270bba877087501677e0534a559272d

Authored by Henry Schreiner
Committed by GitHub
1 parent d4654144

Rename requires to needs (#82)

* Adding fix for #75, rename requires to needs

* Removing check for install commands (should still be run in subproject)
CHANGELOG.md
1 1 ## Version 1.4 (in progress)
2 2 * Added `get_parent()` to access the parent from a subcommand
  3 +* `app.allow_ini_extras()` added to allow extras in INI files [#70]
  4 +* Adding install support for CMake [#79]
  5 +* MakeSingleHeader now works if outside of git [#78]
  6 +* Double printing of error message fixed [#77]
  7 +* Descriptions can now be written with `config_to_str` [#66]
  8 +* Multiline INI comments now supported
  9 +* Added `ExistingPath` validator [#73]
  10 +* Renamed `requires` to `needs` to avoid C++20 keyword [#75], [#82]
  11 +
  12 +[#70]: https://github.com/CLIUtils/CLI11/issues/70
  13 +[#75]: https://github.com/CLIUtils/CLI11/issues/75
  14 +
  15 +[#82]: https://github.com/CLIUtils/CLI11/pull/82
  16 +[#79]: https://github.com/CLIUtils/CLI11/pull/79
  17 +[#78]: https://github.com/CLIUtils/CLI11/pull/78
  18 +[#77]: https://github.com/CLIUtils/CLI11/pull/77
  19 +[#73]: https://github.com/CLIUtils/CLI11/pull/73
  20 +[#66]: https://github.com/CLIUtils/CLI11/pull/66
3 21  
4 22 ## Version 1.3: Refactor
5 23  
... ...
CMakeLists.txt
... ... @@ -53,9 +53,7 @@ file(GLOB CLI_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/*")
53 53 # To see in IDE, must be listed for target
54 54 add_library(CLI11 INTERFACE)
55 55 target_include_directories(CLI11 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
56   -if (CUR_PROJ)
57   - install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/CLI DESTINATION include)
58   -endif()
  56 +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/CLI DESTINATION include)
59 57  
60 58 # Single file test
61 59 find_package(PythonInterp)
... ... @@ -64,6 +62,7 @@ if(CUR_PROJ AND PYTHONINTERP_FOUND)
64 62 else()
65 63 set(CLI_SINGLE_FILE_DEFAULT OFF)
66 64 endif()
  65 +
67 66 option(CLI_SINGLE_FILE "Generate a single header file (and test)" ${CLI_SINGLE_FILE_DEFAULT})
68 67 if(CLI_SINGLE_FILE)
69 68 find_package(PythonInterp REQUIRED)
... ... @@ -76,9 +75,7 @@ if(CLI_SINGLE_FILE)
76 75 DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp")
77 76 set_target_properties(generate_cli_single_file
78 77 PROPERTIES FOLDER "Scripts")
79   - if (CUR_PROJ)
80   - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp DESTINATION include)
81   - endif()
  78 + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp DESTINATION include)
82 79 add_library(CLI11_SINGLE INTERFACE)
83 80 target_link_libraries(CLI11_SINGLE INTERFACE CLI11)
84 81 add_dependencies(CLI11_SINGLE generate_cli_single_file)
... ... @@ -98,3 +95,4 @@ option(CLI_EXAMPLES "Build the examples" ${CUR_PROJ})
98 95 if(CLI_EXAMPLES)
99 96 add_subdirectory(examples)
100 97 endif()
  98 +
... ...
README.md
... ... @@ -171,7 +171,7 @@ The add commands return a pointer to an internally stored `Option`. If you set t
171 171  
172 172 * `->required()`: The program will quit if this option is not present. This is `mandatory` in Plumbum, but required options seems to be a more standard term. For compatibility, `->mandatory()` also works.
173 173 * `->expected(N)`: Take `N` values instead of as many as possible, only for vector args. If negative, require at least `-N`.
174   -* `->requires(opt)`: This option requires another option to also be present, opt is an `Option` pointer.
  174 +* `->needs(opt)`: This option requires another option to also be present, opt is an `Option` pointer.
175 175 * `->excludes(opt)`: This option cannot be given with `opt` present, opt is an `Option` pointer.
176 176 * `->envname(name)`: Gets the value from the environment if present and not passed on the command line.
177 177 * `->group(name)`: The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `""` will not show up in the help print (hidden).
... ... @@ -272,7 +272,7 @@ sub.subcommand = true
272 272 ```
273 273  
274 274 Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `yes`; or `false`, `off`, `0`, `no` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not mean that subcommand was passed, it just sets the "defaults". To print a configuration file from the passed
275   -arguments, use `.config_to_str(default_also=false)`, where `default_also` will also show any defaulted arguments.
  275 +arguments, use `.config_to_str(default_also=false, prefix="", write_description=false)`, where `default_also` will also show any defaulted arguments, `prefix` will add a prefix, and `write_description` will include option descriptions.
276 276  
277 277 ## Inheriting defaults
278 278  
... ...
include/CLI/Option.hpp
... ... @@ -278,7 +278,7 @@ class Option : public OptionBase<Option> {
278 278 }
279 279  
280 280 /// Sets required options
281   - Option *requires(Option *opt) {
  281 + Option *needs(Option *opt) {
282 282 auto tup = requires_.insert(opt);
283 283 if(!tup.second)
284 284 throw OptionAlreadyAdded::Requires(get_name(), opt->get_name());
... ... @@ -286,18 +286,32 @@ class Option : public OptionBase<Option> {
286 286 }
287 287  
288 288 /// Can find a string if needed
289   - template <typename T = App> Option *requires(std::string opt_name) {
  289 + template <typename T = App> Option *needs(std::string opt_name) {
290 290 for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
291 291 if(opt.get() != this && opt->check_name(opt_name))
292   - return requires(opt.get());
  292 + return needs(opt.get());
293 293 throw IncorrectConstruction::MissingOption(opt_name);
294 294 }
295 295  
296 296 /// Any number supported, any mix of string and Opt
  297 + template <typename A, typename B, typename... ARG> Option *needs(A opt, B opt1, ARG... args) {
  298 + needs(opt);
  299 + return needs(opt1, args...);
  300 + }
  301 +
  302 +#if __cplusplus <= 201703L
  303 + /// Sets required options \deprecated
  304 + Option *requires(Option *opt) { return needs(opt); }
  305 +
  306 + /// Can find a string if needed \deprecated
  307 + template <typename T = App> Option *requires(std::string opt_name) { return needs<T>(opt_name); }
  308 +
  309 + /// Any number supported, any mix of string and Opt \deprecated
297 310 template <typename A, typename B, typename... ARG> Option *requires(A opt, B opt1, ARG... args) {
298   - requires(opt);
299   - return requires(opt1, args...);
  311 + needs(opt);
  312 + return needs(opt1, args...);
300 313 }
  314 +#endif
301 315  
302 316 /// Sets excluded options
303 317 Option *excludes(Option *opt) {
... ... @@ -314,6 +328,7 @@ class Option : public OptionBase&lt;Option&gt; {
314 328 return excludes(opt.get());
315 329 throw IncorrectConstruction::MissingOption(opt_name);
316 330 }
  331 +
317 332 /// Any number supported, any mix of string and Opt
318 333 template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
319 334 excludes(opt);
... ...
tests/AppTest.cpp
... ... @@ -982,9 +982,9 @@ TEST_F(TApp, OriginalOrder) {
982 982 EXPECT_EQ(app.parse_order(), std::vector<CLI::Option *>({op1, op2, op1, op1}));
983 983 }
984 984  
985   -TEST_F(TApp, RequiresFlags) {
  985 +TEST_F(TApp, NeedsFlags) {
986 986 CLI::Option *opt = app.add_flag("-s,--string");
987   - app.add_flag("--both")->requires(opt);
  987 + app.add_flag("--both")->needs(opt);
988 988  
989 989 run();
990 990  
... ... @@ -1049,11 +1049,11 @@ TEST_F(TApp, ExcludesMixedFlags) {
1049 1049 EXPECT_THROW(run(), CLI::ExcludesError);
1050 1050 }
1051 1051  
1052   -TEST_F(TApp, RequiresMultiFlags) {
  1052 +TEST_F(TApp, NeedsMultiFlags) {
1053 1053 CLI::Option *opt1 = app.add_flag("--opt1");
1054 1054 CLI::Option *opt2 = app.add_flag("--opt2");
1055 1055 CLI::Option *opt3 = app.add_flag("--opt3");
1056   - app.add_flag("--optall")->requires(opt1, opt2, opt3);
  1056 + app.add_flag("--optall")->needs(opt1, opt2, opt3);
1057 1057  
1058 1058 run();
1059 1059  
... ... @@ -1082,6 +1082,41 @@ TEST_F(TApp, RequiresMultiFlags) {
1082 1082 run();
1083 1083 }
1084 1084  
  1085 +TEST_F(TApp, NeedsMixedFlags) {
  1086 + CLI::Option *opt1 = app.add_flag("--opt1");
  1087 + app.add_flag("--opt2");
  1088 + app.add_flag("--opt3");
  1089 + app.add_flag("--optall")->needs(opt1, "--opt2", "--opt3");
  1090 +
  1091 + run();
  1092 +
  1093 + app.reset();
  1094 + args = {"--opt1"};
  1095 + run();
  1096 +
  1097 + app.reset();
  1098 + args = {"--opt2"};
  1099 + run();
  1100 +
  1101 + app.reset();
  1102 + args = {"--optall"};
  1103 + EXPECT_THROW(run(), CLI::RequiresError);
  1104 +
  1105 + app.reset();
  1106 + args = {"--optall", "--opt1"};
  1107 + EXPECT_THROW(run(), CLI::RequiresError);
  1108 +
  1109 + app.reset();
  1110 + args = {"--optall", "--opt2", "--opt1"};
  1111 + EXPECT_THROW(run(), CLI::RequiresError);
  1112 +
  1113 + app.reset();
  1114 + args = {"--optall", "--opt1", "--opt2", "--opt3"};
  1115 + run();
  1116 +}
  1117 +
  1118 +#if __cplusplus <= 201703L
  1119 +
1085 1120 TEST_F(TApp, RequiresMixedFlags) {
1086 1121 CLI::Option *opt1 = app.add_flag("--opt1");
1087 1122 app.add_flag("--opt2");
... ... @@ -1115,10 +1150,12 @@ TEST_F(TApp, RequiresMixedFlags) {
1115 1150 run();
1116 1151 }
1117 1152  
1118   -TEST_F(TApp, RequiresChainedFlags) {
  1153 +#endif
  1154 +
  1155 +TEST_F(TApp, NeedsChainedFlags) {
1119 1156 CLI::Option *opt1 = app.add_flag("--opt1");
1120   - CLI::Option *opt2 = app.add_flag("--opt2")->requires(opt1);
1121   - app.add_flag("--opt3")->requires(opt2);
  1157 + CLI::Option *opt2 = app.add_flag("--opt2")->needs(opt1);
  1158 + app.add_flag("--opt3")->needs(opt2);
1122 1159  
1123 1160 run();
1124 1161  
... ...
tests/CreationTest.cpp
... ... @@ -163,9 +163,9 @@ TEST_F(TApp, IncorrectConstructionTakeLastExpected) {
163 163 EXPECT_THROW(cat->expected(2), CLI::IncorrectConstruction);
164 164 }
165 165  
166   -TEST_F(TApp, IncorrectConstructionRequiresCannotFind) {
  166 +TEST_F(TApp, IncorrectConstructionNeedsCannotFind) {
167 167 auto cat = app.add_flag("--cat");
168   - EXPECT_THROW(cat->requires("--nothing"), CLI::IncorrectConstruction);
  168 + EXPECT_THROW(cat->needs("--nothing"), CLI::IncorrectConstruction);
169 169 }
170 170  
171 171 TEST_F(TApp, IncorrectConstructionExcludesCannotFind) {
... ... @@ -173,18 +173,18 @@ TEST_F(TApp, IncorrectConstructionExcludesCannotFind) {
173 173 EXPECT_THROW(cat->excludes("--nothing"), CLI::IncorrectConstruction);
174 174 }
175 175  
176   -TEST_F(TApp, IncorrectConstructionDuplicateRequires) {
  176 +TEST_F(TApp, IncorrectConstructionDuplicateNeeds) {
177 177 auto cat = app.add_flag("--cat");
178 178 auto other = app.add_flag("--other");
179   - ASSERT_NO_THROW(cat->requires(other));
180   - EXPECT_THROW(cat->requires(other), CLI::OptionAlreadyAdded);
  179 + ASSERT_NO_THROW(cat->needs(other));
  180 + EXPECT_THROW(cat->needs(other), CLI::OptionAlreadyAdded);
181 181 }
182 182  
183   -TEST_F(TApp, IncorrectConstructionDuplicateRequiresTxt) {
  183 +TEST_F(TApp, IncorrectConstructionDuplicateNeedsTxt) {
184 184 auto cat = app.add_flag("--cat");
185 185 app.add_flag("--other");
186   - ASSERT_NO_THROW(cat->requires("--other"));
187   - EXPECT_THROW(cat->requires("--other"), CLI::OptionAlreadyAdded);
  186 + ASSERT_NO_THROW(cat->needs("--other"));
  187 + EXPECT_THROW(cat->needs("--other"), CLI::OptionAlreadyAdded);
188 188 }
189 189  
190 190 TEST_F(TApp, IncorrectConstructionDuplicateExcludes) {
... ...
tests/HelpTest.cpp
... ... @@ -153,24 +153,24 @@ TEST(THelp, EnvName) {
153 153 EXPECT_THAT(help, HasSubstr("SOME_ENV"));
154 154 }
155 155  
156   -TEST(THelp, Requires) {
  156 +TEST(THelp, Needs) {
157 157 CLI::App app{"My prog"};
158 158  
159 159 CLI::Option *op1 = app.add_flag("--op1");
160   - app.add_flag("--op2")->requires(op1);
  160 + app.add_flag("--op2")->needs(op1);
161 161  
162 162 std::string help = app.help();
163 163  
164 164 EXPECT_THAT(help, HasSubstr("Requires: --op1"));
165 165 }
166 166  
167   -TEST(THelp, RequiresPositional) {
  167 +TEST(THelp, NeedsPositional) {
168 168 CLI::App app{"My prog"};
169 169  
170 170 int x, y;
171 171  
172 172 CLI::Option *op1 = app.add_option("op1", x, "one");
173   - app.add_option("op2", y, "two")->requires(op1);
  173 + app.add_option("op2", y, "two")->needs(op1);
174 174  
175 175 std::string help = app.help();
176 176  
... ...
tests/IniTest.cpp
... ... @@ -248,7 +248,7 @@ TEST_F(TApp, IniGetNoRemaining) {
248 248 int two = 0;
249 249 app.add_option("--two", two);
250 250 EXPECT_NO_THROW(run());
251   - EXPECT_EQ(app.remaining().size(), 0);
  251 + EXPECT_EQ(app.remaining().size(), (size_t)0);
252 252 }
253 253  
254 254 TEST_F(TApp, IniNotRequiredNotDefault) {
... ...