diff --git a/packages/CLI11/.gitrepo b/packages/CLI11/.gitrepo index 529dab07528697a59e5c2dbdd31b500d3742757f..7c4acccc96c7629f0266ca22bf67012d55357201 100644 --- a/packages/CLI11/.gitrepo +++ b/packages/CLI11/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@github.com:CLIUtils/CLI11.git branch = master - commit = b683f4ed96b2da6c4992e63f49482b8c9cd00968 - parent = b9ec061afdb0aefa3489d9beaecf99cd608f3d15 + commit = bd4dc911847d0cde7a6b41dfa626a85aab213baf + parent = 5c82607003abda391c299d089e4624664a41de7a cmdver = 0.4.0 method = merge diff --git a/packages/CLI11/CHANGELOG.md b/packages/CLI11/CHANGELOG.md index ba405ea012b21239467c9c1d48adf9ca0ee1d55b..0b8ade8eadf04574261dc5dd52d523973fd14690 100644 --- a/packages/CLI11/CHANGELOG.md +++ b/packages/CLI11/CHANGELOG.md @@ -1,6 +1,6 @@ ## Version 1.6.2: Help-all -This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. +This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. Several smaller fixes. * Fixed help-all formatting [#163] * Printing help-all on nested command now fixed (App) @@ -11,11 +11,16 @@ This version fixes some formatting bugs with help-all. It also adds fixes for se * Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156] * Fixed warning about local variable hiding class member with MSVC [#157] * Fixed compile error with default settings on Clang 7 and libc++ [#158] +* Fixed special case of `--help` on subcommands (general fix planned for 1.7) [#168] +* Removing an option with links [#179] [#156]: https://github.com/CLIUtils/CLI11/issues/156 [#157]: https://github.com/CLIUtils/CLI11/issues/157 [#158]: https://github.com/CLIUtils/CLI11/issues/158 [#163]: https://github.com/CLIUtils/CLI11/pull/163 +[#168]: https://github.com/CLIUtils/CLI11/issues/168 +[#179]: https://github.com/CLIUtils/CLI11/pull/179 + ## Version 1.6.1: Platform fixes diff --git a/packages/CLI11/README.md b/packages/CLI11/README.md index 319769ff0943e40d905356886b2ececac1c7fe12..c03b5e904ac05b9a558abde3ac5f3576bcae7ea3 100644 --- a/packages/CLI11/README.md +++ b/packages/CLI11/README.md @@ -458,6 +458,9 @@ Significant features and/or improvements to the code were contributed by: - [Nathan Hourt](https://github.com/nathanhourt) - [Sean Fisk](https://github.com/seanfisk) - [Stéphane Del Pino](https://github.com/delpinux) +- [Mak Kolybabi](https://github.com/mogigoma) +- [Paweł Bylica](https://github.com/chfast) + ## License diff --git a/packages/CLI11/include/CLI/App.hpp b/packages/CLI11/include/CLI/App.hpp index 99bc977421956edd0d16ce14b91b5f771ede82b6..4b207e13373c60b7fd15c1af75a4cdddc15422d5 100644 --- a/packages/CLI11/include/CLI/App.hpp +++ b/packages/CLI11/include/CLI/App.hpp @@ -781,6 +781,12 @@ class App { /// Removes an option from the App. Takes an option pointer. Returns true if found and removed. bool remove_option(Option *opt) { + // Make sure no links exist + for(Option_p &op : options_) { + op->remove_needs(opt); + op->remove_excludes(opt); + } + auto iterator = std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; }); if(iterator != std::end(options_)) { @@ -1356,7 +1362,7 @@ class App { throw RequiredError(opt->get_name()); } // Requires - for(const Option *opt_req : opt->requires_) + for(const Option *opt_req : opt->needs_) if(opt->count() > 0 && opt_req->count() == 0) throw RequiresError(opt->get_name(), opt_req->get_name()); // Excludes @@ -1383,7 +1389,7 @@ class App { } } - /// Return True if a help flag detected (checks all parents) + /// Return True if a help flag detected (checks all parents) (only run if help called before subcommand) bool _any_help_flag() const { bool result = false; const Option *help_ptr = get_help_ptr(); diff --git a/packages/CLI11/include/CLI/Option.hpp b/packages/CLI11/include/CLI/Option.hpp index a5f046a22acf1a75aa7e406959dfd4feadedcbab..c37e39f7b0049dc7f522dbf27ddf99778eb97978 100644 --- a/packages/CLI11/include/CLI/Option.hpp +++ b/packages/CLI11/include/CLI/Option.hpp @@ -200,7 +200,7 @@ class Option : public OptionBase<Option> { std::vector<std::function<std::string(std::string &)>> validators_; /// A list of options that are required with this option - std::set<Option *> requires_; + std::set<Option *> needs_; /// A list of options that are excluded with this option std::set<Option *> excludes_; @@ -322,7 +322,7 @@ class Option : public OptionBase<Option> { /// Sets required options Option *needs(Option *opt) { - auto tup = requires_.insert(opt); + auto tup = needs_.insert(opt); if(!tup.second) throw OptionAlreadyAdded::Requires(get_name(), opt->get_name()); return this; @@ -342,6 +342,18 @@ class Option : public OptionBase<Option> { return needs(opt1, args...); } + /// Remove needs link from an option. Returns true if the option really was in the needs list. + bool remove_needs(Option *opt) { + auto iterator = std::find(std::begin(needs_), std::end(needs_), opt); + + if(iterator != std::end(needs_)) { + needs_.erase(iterator); + return true; + } else { + return false; + } + } + /// Sets excluded options Option *excludes(Option *opt) { excludes_.insert(opt); @@ -369,6 +381,18 @@ class Option : public OptionBase<Option> { return excludes(opt1, args...); } + /// Remove needs link from an option. Returns true if the option really was in the needs list. + bool remove_excludes(Option *opt) { + auto iterator = std::find(std::begin(excludes_), std::end(excludes_), opt); + + if(iterator != std::end(excludes_)) { + excludes_.erase(iterator); + return true; + } else { + return false; + } + } + /// Sets environment variable to read if no option given Option *envname(std::string name) { envname_ = name; @@ -418,7 +442,7 @@ class Option : public OptionBase<Option> { std::string get_envname() const { return envname_; } /// The set of options needed - std::set<Option *> get_needs() const { return requires_; } + std::set<Option *> get_needs() const { return needs_; } /// The set of options excluded std::set<Option *> get_excludes() const { return excludes_; } diff --git a/packages/CLI11/include/CLI/Version.hpp b/packages/CLI11/include/CLI/Version.hpp index 80eaf2a0d2b674d03e4f222d83d2696657b4bb81..b2ae8641d8dc69513719a3e5fad72d2e0a0a98f7 100644 --- a/packages/CLI11/include/CLI/Version.hpp +++ b/packages/CLI11/include/CLI/Version.hpp @@ -7,7 +7,7 @@ #define CLI11_VERSION_MAJOR 1 #define CLI11_VERSION_MINOR 6 -#define CLI11_VERSION_PATCH 1 -#define CLI11_VERSION "1.6.1" +#define CLI11_VERSION_PATCH 2 +#define CLI11_VERSION "1.6.2" // [CLI11:verbatim] diff --git a/packages/CLI11/tests/AppTest.cpp b/packages/CLI11/tests/AppTest.cpp index 1c6a969f7f05d6c33bdd944fc3796257bb8b3d5f..b1bd218e5e3bec2a8cd27f2ad4a21dd0ea000f93 100644 --- a/packages/CLI11/tests/AppTest.cpp +++ b/packages/CLI11/tests/AppTest.cpp @@ -816,6 +816,34 @@ TEST_F(TApp, RemoveOption) { EXPECT_THROW(run(), CLI::ExtrasError); } +TEST_F(TApp, RemoveNeedsLinks) { + auto one = app.add_flag("--one"); + auto two = app.add_flag("--two"); + + two->needs(one); + one->needs(two); + + EXPECT_TRUE(app.remove_option(one)); + + args = {"--two"}; + + run(); +} + +TEST_F(TApp, RemoveExcludesLinks) { + auto one = app.add_flag("--one"); + auto two = app.add_flag("--two"); + + two->excludes(one); + one->excludes(two); + + EXPECT_TRUE(app.remove_option(one)); + + args = {"--two"}; + + run(); // Mostly hoping it does not crash +} + TEST_F(TApp, FileNotExists) { std::string myfile{"TestNonFileNotUsed.txt"}; ASSERT_NO_THROW(CLI::NonexistentPath(myfile)); diff --git a/packages/CLI11/tests/SubcommandTest.cpp b/packages/CLI11/tests/SubcommandTest.cpp index bc5d8ca0095c0c311ce586107d1f2b90eef2fd7f..e752f4f2c74bd8ea35cbd2562a5862d8f40e00bb 100644 --- a/packages/CLI11/tests/SubcommandTest.cpp +++ b/packages/CLI11/tests/SubcommandTest.cpp @@ -438,6 +438,8 @@ struct SubcommandProgram : public TApp { int count; SubcommandProgram() { + app.set_help_all_flag("--help-all"); + start = app.add_subcommand("start", "Start prog"); stop = app.add_subcommand("stop", "Stop prog"); @@ -541,6 +543,18 @@ TEST_F(SubcommandProgram, HelpOrder) { EXPECT_THROW(run(), CLI::CallForHelp); } +TEST_F(SubcommandProgram, HelpAllOrder) { + + args = {"--help-all"}; + EXPECT_THROW(run(), CLI::CallForAllHelp); + + args = {"start", "--help-all"}; + EXPECT_THROW(run(), CLI::CallForAllHelp); + + args = {"--help-all", "start"}; + EXPECT_THROW(run(), CLI::CallForAllHelp); +} + TEST_F(SubcommandProgram, Callbacks) { start->callback([]() { throw CLI::Success(); });