mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Rename requires to needs (#82)
* Adding fix for #75, rename requires to needs * Removing check for install commands (should still be run in subproject)
This commit is contained in:
parent
d465414455
commit
5186158442
18
CHANGELOG.md
18
CHANGELOG.md
@ -1,5 +1,23 @@
|
||||
## Version 1.4 (in progress)
|
||||
* Added `get_parent()` to access the parent from a subcommand
|
||||
* `app.allow_ini_extras()` added to allow extras in INI files [#70]
|
||||
* Adding install support for CMake [#79]
|
||||
* MakeSingleHeader now works if outside of git [#78]
|
||||
* Double printing of error message fixed [#77]
|
||||
* Descriptions can now be written with `config_to_str` [#66]
|
||||
* Multiline INI comments now supported
|
||||
* Added `ExistingPath` validator [#73]
|
||||
* Renamed `requires` to `needs` to avoid C++20 keyword [#75], [#82]
|
||||
|
||||
[#70]: https://github.com/CLIUtils/CLI11/issues/70
|
||||
[#75]: https://github.com/CLIUtils/CLI11/issues/75
|
||||
|
||||
[#82]: https://github.com/CLIUtils/CLI11/pull/82
|
||||
[#79]: https://github.com/CLIUtils/CLI11/pull/79
|
||||
[#78]: https://github.com/CLIUtils/CLI11/pull/78
|
||||
[#77]: https://github.com/CLIUtils/CLI11/pull/77
|
||||
[#73]: https://github.com/CLIUtils/CLI11/pull/73
|
||||
[#66]: https://github.com/CLIUtils/CLI11/pull/66
|
||||
|
||||
## Version 1.3: Refactor
|
||||
|
||||
|
@ -53,9 +53,7 @@ file(GLOB CLI_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/*")
|
||||
# To see in IDE, must be listed for target
|
||||
add_library(CLI11 INTERFACE)
|
||||
target_include_directories(CLI11 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
if (CUR_PROJ)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/CLI DESTINATION include)
|
||||
endif()
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/CLI DESTINATION include)
|
||||
|
||||
# Single file test
|
||||
find_package(PythonInterp)
|
||||
@ -64,6 +62,7 @@ if(CUR_PROJ AND PYTHONINTERP_FOUND)
|
||||
else()
|
||||
set(CLI_SINGLE_FILE_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
option(CLI_SINGLE_FILE "Generate a single header file (and test)" ${CLI_SINGLE_FILE_DEFAULT})
|
||||
if(CLI_SINGLE_FILE)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
@ -76,9 +75,7 @@ if(CLI_SINGLE_FILE)
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp")
|
||||
set_target_properties(generate_cli_single_file
|
||||
PROPERTIES FOLDER "Scripts")
|
||||
if (CUR_PROJ)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp DESTINATION include)
|
||||
endif()
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp DESTINATION include)
|
||||
add_library(CLI11_SINGLE INTERFACE)
|
||||
target_link_libraries(CLI11_SINGLE INTERFACE CLI11)
|
||||
add_dependencies(CLI11_SINGLE generate_cli_single_file)
|
||||
@ -98,3 +95,4 @@ option(CLI_EXAMPLES "Build the examples" ${CUR_PROJ})
|
||||
if(CLI_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
|
@ -171,7 +171,7 @@ The add commands return a pointer to an internally stored `Option`. If you set t
|
||||
|
||||
* `->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.
|
||||
* `->expected(N)`: Take `N` values instead of as many as possible, only for vector args. If negative, require at least `-N`.
|
||||
* `->requires(opt)`: This option requires another option to also be present, opt is an `Option` pointer.
|
||||
* `->needs(opt)`: This option requires another option to also be present, opt is an `Option` pointer.
|
||||
* `->excludes(opt)`: This option cannot be given with `opt` present, opt is an `Option` pointer.
|
||||
* `->envname(name)`: Gets the value from the environment if present and not passed on the command line.
|
||||
* `->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
|
||||
```
|
||||
|
||||
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
|
||||
arguments, use `.config_to_str(default_also=false)`, where `default_also` will also show any defaulted arguments.
|
||||
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.
|
||||
|
||||
## Inheriting defaults
|
||||
|
||||
|
@ -278,7 +278,7 @@ class Option : public OptionBase<Option> {
|
||||
}
|
||||
|
||||
/// Sets required options
|
||||
Option *requires(Option *opt) {
|
||||
Option *needs(Option *opt) {
|
||||
auto tup = requires_.insert(opt);
|
||||
if(!tup.second)
|
||||
throw OptionAlreadyAdded::Requires(get_name(), opt->get_name());
|
||||
@ -286,19 +286,33 @@ class Option : public OptionBase<Option> {
|
||||
}
|
||||
|
||||
/// Can find a string if needed
|
||||
template <typename T = App> Option *requires(std::string opt_name) {
|
||||
template <typename T = App> Option *needs(std::string opt_name) {
|
||||
for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
|
||||
if(opt.get() != this && opt->check_name(opt_name))
|
||||
return requires(opt.get());
|
||||
return needs(opt.get());
|
||||
throw IncorrectConstruction::MissingOption(opt_name);
|
||||
}
|
||||
|
||||
/// Any number supported, any mix of string and Opt
|
||||
template <typename A, typename B, typename... ARG> Option *requires(A opt, B opt1, ARG... args) {
|
||||
requires(opt);
|
||||
return requires(opt1, args...);
|
||||
template <typename A, typename B, typename... ARG> Option *needs(A opt, B opt1, ARG... args) {
|
||||
needs(opt);
|
||||
return needs(opt1, args...);
|
||||
}
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
/// Sets required options \deprecated
|
||||
Option *requires(Option *opt) { return needs(opt); }
|
||||
|
||||
/// Can find a string if needed \deprecated
|
||||
template <typename T = App> Option *requires(std::string opt_name) { return needs<T>(opt_name); }
|
||||
|
||||
/// Any number supported, any mix of string and Opt \deprecated
|
||||
template <typename A, typename B, typename... ARG> Option *requires(A opt, B opt1, ARG... args) {
|
||||
needs(opt);
|
||||
return needs(opt1, args...);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Sets excluded options
|
||||
Option *excludes(Option *opt) {
|
||||
auto tup = excludes_.insert(opt);
|
||||
@ -314,6 +328,7 @@ class Option : public OptionBase<Option> {
|
||||
return excludes(opt.get());
|
||||
throw IncorrectConstruction::MissingOption(opt_name);
|
||||
}
|
||||
|
||||
/// Any number supported, any mix of string and Opt
|
||||
template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
|
||||
excludes(opt);
|
||||
|
@ -982,9 +982,9 @@ TEST_F(TApp, OriginalOrder) {
|
||||
EXPECT_EQ(app.parse_order(), std::vector<CLI::Option *>({op1, op2, op1, op1}));
|
||||
}
|
||||
|
||||
TEST_F(TApp, RequiresFlags) {
|
||||
TEST_F(TApp, NeedsFlags) {
|
||||
CLI::Option *opt = app.add_flag("-s,--string");
|
||||
app.add_flag("--both")->requires(opt);
|
||||
app.add_flag("--both")->needs(opt);
|
||||
|
||||
run();
|
||||
|
||||
@ -1049,11 +1049,11 @@ TEST_F(TApp, ExcludesMixedFlags) {
|
||||
EXPECT_THROW(run(), CLI::ExcludesError);
|
||||
}
|
||||
|
||||
TEST_F(TApp, RequiresMultiFlags) {
|
||||
TEST_F(TApp, NeedsMultiFlags) {
|
||||
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||
CLI::Option *opt2 = app.add_flag("--opt2");
|
||||
CLI::Option *opt3 = app.add_flag("--opt3");
|
||||
app.add_flag("--optall")->requires(opt1, opt2, opt3);
|
||||
app.add_flag("--optall")->needs(opt1, opt2, opt3);
|
||||
|
||||
run();
|
||||
|
||||
@ -1082,6 +1082,41 @@ TEST_F(TApp, RequiresMultiFlags) {
|
||||
run();
|
||||
}
|
||||
|
||||
TEST_F(TApp, NeedsMixedFlags) {
|
||||
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||
app.add_flag("--opt2");
|
||||
app.add_flag("--opt3");
|
||||
app.add_flag("--optall")->needs(opt1, "--opt2", "--opt3");
|
||||
|
||||
run();
|
||||
|
||||
app.reset();
|
||||
args = {"--opt1"};
|
||||
run();
|
||||
|
||||
app.reset();
|
||||
args = {"--opt2"};
|
||||
run();
|
||||
|
||||
app.reset();
|
||||
args = {"--optall"};
|
||||
EXPECT_THROW(run(), CLI::RequiresError);
|
||||
|
||||
app.reset();
|
||||
args = {"--optall", "--opt1"};
|
||||
EXPECT_THROW(run(), CLI::RequiresError);
|
||||
|
||||
app.reset();
|
||||
args = {"--optall", "--opt2", "--opt1"};
|
||||
EXPECT_THROW(run(), CLI::RequiresError);
|
||||
|
||||
app.reset();
|
||||
args = {"--optall", "--opt1", "--opt2", "--opt3"};
|
||||
run();
|
||||
}
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
|
||||
TEST_F(TApp, RequiresMixedFlags) {
|
||||
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||
app.add_flag("--opt2");
|
||||
@ -1115,10 +1150,12 @@ TEST_F(TApp, RequiresMixedFlags) {
|
||||
run();
|
||||
}
|
||||
|
||||
TEST_F(TApp, RequiresChainedFlags) {
|
||||
#endif
|
||||
|
||||
TEST_F(TApp, NeedsChainedFlags) {
|
||||
CLI::Option *opt1 = app.add_flag("--opt1");
|
||||
CLI::Option *opt2 = app.add_flag("--opt2")->requires(opt1);
|
||||
app.add_flag("--opt3")->requires(opt2);
|
||||
CLI::Option *opt2 = app.add_flag("--opt2")->needs(opt1);
|
||||
app.add_flag("--opt3")->needs(opt2);
|
||||
|
||||
run();
|
||||
|
||||
|
@ -163,9 +163,9 @@ TEST_F(TApp, IncorrectConstructionTakeLastExpected) {
|
||||
EXPECT_THROW(cat->expected(2), CLI::IncorrectConstruction);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IncorrectConstructionRequiresCannotFind) {
|
||||
TEST_F(TApp, IncorrectConstructionNeedsCannotFind) {
|
||||
auto cat = app.add_flag("--cat");
|
||||
EXPECT_THROW(cat->requires("--nothing"), CLI::IncorrectConstruction);
|
||||
EXPECT_THROW(cat->needs("--nothing"), CLI::IncorrectConstruction);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IncorrectConstructionExcludesCannotFind) {
|
||||
@ -173,18 +173,18 @@ TEST_F(TApp, IncorrectConstructionExcludesCannotFind) {
|
||||
EXPECT_THROW(cat->excludes("--nothing"), CLI::IncorrectConstruction);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IncorrectConstructionDuplicateRequires) {
|
||||
TEST_F(TApp, IncorrectConstructionDuplicateNeeds) {
|
||||
auto cat = app.add_flag("--cat");
|
||||
auto other = app.add_flag("--other");
|
||||
ASSERT_NO_THROW(cat->requires(other));
|
||||
EXPECT_THROW(cat->requires(other), CLI::OptionAlreadyAdded);
|
||||
ASSERT_NO_THROW(cat->needs(other));
|
||||
EXPECT_THROW(cat->needs(other), CLI::OptionAlreadyAdded);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IncorrectConstructionDuplicateRequiresTxt) {
|
||||
TEST_F(TApp, IncorrectConstructionDuplicateNeedsTxt) {
|
||||
auto cat = app.add_flag("--cat");
|
||||
app.add_flag("--other");
|
||||
ASSERT_NO_THROW(cat->requires("--other"));
|
||||
EXPECT_THROW(cat->requires("--other"), CLI::OptionAlreadyAdded);
|
||||
ASSERT_NO_THROW(cat->needs("--other"));
|
||||
EXPECT_THROW(cat->needs("--other"), CLI::OptionAlreadyAdded);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IncorrectConstructionDuplicateExcludes) {
|
||||
|
@ -153,24 +153,24 @@ TEST(THelp, EnvName) {
|
||||
EXPECT_THAT(help, HasSubstr("SOME_ENV"));
|
||||
}
|
||||
|
||||
TEST(THelp, Requires) {
|
||||
TEST(THelp, Needs) {
|
||||
CLI::App app{"My prog"};
|
||||
|
||||
CLI::Option *op1 = app.add_flag("--op1");
|
||||
app.add_flag("--op2")->requires(op1);
|
||||
app.add_flag("--op2")->needs(op1);
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
EXPECT_THAT(help, HasSubstr("Requires: --op1"));
|
||||
}
|
||||
|
||||
TEST(THelp, RequiresPositional) {
|
||||
TEST(THelp, NeedsPositional) {
|
||||
CLI::App app{"My prog"};
|
||||
|
||||
int x, y;
|
||||
|
||||
CLI::Option *op1 = app.add_option("op1", x, "one");
|
||||
app.add_option("op2", y, "two")->requires(op1);
|
||||
app.add_option("op2", y, "two")->needs(op1);
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
|
@ -248,7 +248,7 @@ TEST_F(TApp, IniGetNoRemaining) {
|
||||
int two = 0;
|
||||
app.add_option("--two", two);
|
||||
EXPECT_NO_THROW(run());
|
||||
EXPECT_EQ(app.remaining().size(), 0);
|
||||
EXPECT_EQ(app.remaining().size(), (size_t)0);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniNotRequiredNotDefault) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user