Commit 8f1215873c8f5aa2c82c89294e4874ebd071817d

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 03039295

Allow -- to end unlimited options

CHANGELOG.md
1   -## Version 1.5: Optional
2   -
  1 +## Version 1.5: Optionals
3 2  
4 3 This version introduced support for optionals, along with clarification and examples of custom conversion overloads. Enums now have been dropped from the automatic conversion system, allowing explicit protection for out-of-range ints (or a completely custom conversion). This version has some internal cleanup and improved support for the newest compilers. Several bugs were fixed, as well.
5 4  
... ... @@ -11,6 +10,7 @@ Note: This is the final release with `requires`, please switch to `needs`.
11 10 * All macros/CMake variables now start with `CLI11_` instead of just `CLI_` [#95]
12 11 * The internal stream was not being cleared before use in some cases. Fixed. [#95]
13 12 * Using an emum now requires explicit conversion overload [#97]
  13 +* The separator `--` now is removed when it ends unlimited arguments [#100]
14 14  
15 15 Other, non-user facing changes:
16 16  
... ... @@ -21,12 +21,15 @@ Other, non-user facing changes:
21 21 * Better single file generation [#95]
22 22 * Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next version of GTest)
23 23 * Types now have a specific size, separate from the expected number - cleaner and more powerful internally [#92]
  24 +* Examples now run as part of testing [#99]
24 25  
25 26 [#64]: https://github.com/CLIUtils/CLI11/issues/64
26 27 [#90]: https://github.com/CLIUtils/CLI11/issues/90
27 28 [#92]: https://github.com/CLIUtils/CLI11/issues/92
28 29 [#95]: https://github.com/CLIUtils/CLI11/pull/95
29 30 [#97]: https://github.com/CLIUtils/CLI11/pull/97
  31 +[#99]: https://github.com/CLIUtils/CLI11/pull/99
  32 +[#100]: https://github.com/CLIUtils/CLI11/pull/100
30 33  
31 34  
32 35 ## Version 1.4: More feedback
... ...
README.md
... ... @@ -176,7 +176,7 @@ On a compiler that supports C++17's `__has_include`, you can also use `std::opti
176 176 The add commands return a pointer to an internally stored `Option`. If you set the final argument to true, the default value is captured and printed on the command line with the help flag. This option can be used directly to check for the count (`->count()`) after parsing to avoid a string based lookup. Before parsing, you can set the following options:
177 177  
178 178 * `->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.
179   -* `->expected(N)`: Take `N` values instead of as many as possible, only for vector args. If negative, require at least `-N`.
  179 +* `->expected(N)`: Take `N` values instead of as many as possible, only for vector args. If negative, require at least `-N`; end with `--` or another recognized option.
180 180 * `->needs(opt)`: This option requires another option to also be present, opt is an `Option` pointer.
181 181 * `->excludes(opt)`: This option cannot be given with `opt` present, opt is an `Option` pointer.
182 182 * `->envname(name)`: Gets the value from the environment if present and not passed on the command line.
... ...
examples/CMakeLists.txt
... ... @@ -65,7 +65,7 @@ add_cli_exe(prefix_command prefix_command.cpp)
65 65 add_test(NAME prefix_command COMMAND prefix_command -v 3 2 1 -- other one two 3)
66 66 set_property(TEST prefix_command PROPERTY PASS_REGULAR_EXPRESSION
67 67 "Prefix: 3 : 2 : 1"
68   - "Remaining commands: -- other one two 3")
  68 + "Remaining commands: other one two 3")
69 69  
70 70 add_cli_exe(enum enum.cpp)
71 71 add_test(NAME enum_pass COMMAND enum -l 1)
... ...
include/CLI/App.hpp
... ... @@ -1035,12 +1035,14 @@ class App {
1035 1035 /// This gets a vector of pointers with the original parse order
1036 1036 const std::vector<Option *> &parse_order() const { return parse_order_; }
1037 1037  
1038   - /// This retuns the missing options from the current subcommand
  1038 + /// This returns the missing options from the current subcommand
1039 1039 std::vector<std::string> remaining(bool recurse = false) const {
1040 1040 std::vector<std::string> miss_list;
1041 1041 for(const std::pair<detail::Classifer, std::string> &miss : missing_) {
1042 1042 miss_list.push_back(std::get<1>(miss));
1043 1043 }
  1044 +
  1045 + // Recurse into subcommands
1044 1046 if(recurse) {
1045 1047 for(const App *sub : parsed_subcommands_) {
1046 1048 std::vector<std::string> output = sub->remaining(recurse);
... ... @@ -1472,6 +1474,10 @@ class App {
1472 1474 collected++;
1473 1475 }
1474 1476  
  1477 + // Allow -- to end an unlimited list and "eat" it
  1478 + if(!args.empty() && _recognize(args.back()) == detail::Classifer::POSITIONAL_MARK)
  1479 + args.pop_back();
  1480 +
1475 1481 } else {
1476 1482 while(num > 0 && !args.empty()) {
1477 1483 num--;
... ...
tests/AppTest.cpp
... ... @@ -581,6 +581,19 @@ TEST_F(TApp, RequiredOptsUnlimitedShort) {
581 581 EXPECT_EQ(remain, std::vector<std::string>({"two"}));
582 582 }
583 583  
  584 +TEST_F(TApp, OptsUnlimitedEnd) {
  585 + std::vector<std::string> strs;
  586 + app.add_option("-s,--str", strs);
  587 + app.allow_extras();
  588 +
  589 + args = {"one", "-s", "two", "three", "--", "four"};
  590 +
  591 + run();
  592 +
  593 + EXPECT_EQ(strs, std::vector<std::string>({"two", "three"}));
  594 + EXPECT_EQ(app.remaining(), std::vector<std::string>({"one", "four"}));
  595 +}
  596 +
584 597 TEST_F(TApp, RequireOptPriority) {
585 598  
586 599 std::vector<std::string> strs;
... ...
tests/SubcommandTest.cpp
... ... @@ -430,7 +430,7 @@ TEST_F(TApp, PrefixSeparation) {
430 430  
431 431 run();
432 432  
433   - EXPECT_EQ(app.remaining(), std::vector<std::string>({"--", "other"}));
  433 + EXPECT_EQ(app.remaining(), std::vector<std::string>({"other"}));
434 434 EXPECT_EQ(vals, std::vector<int>({1, 2, 3}));
435 435 }
436 436  
... ...