Commit abe9ebd6b4084d576ceb79904c94ef8c9c0e6c56

Authored by Jarryd Beck
1 parent 0a49b820

Fix handling of implicit values

Fixes #84. Implicit values are not handled very well. For example:

    --foo false true
    --foo --bar

In the first, `false` is an argument to `--foo`, and then `true` is a
positional argument. In the second, because of the hyphen in `--bar`, `--foo`
is parsed with its implicit value. This seems inconsistent and unintuitive.

Better is that implicit values *never* consume the next parameter to be
completely consistent. This means that values with an implicit parameter
*must* be specified using the `--option=value` form.
CHANGELOG.md
@@ -3,6 +3,16 @@ @@ -3,6 +3,16 @@
3 This is the changelog for `cxxopts`, a C++11 library for parsing command line 3 This is the changelog for `cxxopts`, a C++11 library for parsing command line
4 options. The project adheres to semantic versioning. 4 options. The project adheres to semantic versioning.
5 5
  6 +## 2.1
  7 +
  8 +### Changed
  9 +
  10 +* Options with implicit arguments now require the `--option=value` form if
  11 + they are to be specified with an option. This is to remove the ambiguity
  12 + when a positional argument could follow an option with an implicit value.
  13 + For example, `--foo value`, where `foo` has an implicit value, will be
  14 + parsed as `--foo=implicit` and a positional argument `value`.
  15 +
6 ## 2.0 16 ## 2.0
7 17
8 ### Changed 18 ### Changed
include/cxxopts.hpp
@@ -1522,7 +1522,7 @@ ParseResult::checked_parse_arg @@ -1522,7 +1522,7 @@ ParseResult::checked_parse_arg
1522 } 1522 }
1523 else 1523 else
1524 { 1524 {
1525 - if (argv[current + 1][0] == '-' && value->value().has_implicit()) 1525 + if (value->value().has_implicit())
1526 { 1526 {
1527 parse_option(value, name, value->value().get_implicit_value()); 1527 parse_option(value, name, value->value().get_implicit_value());
1528 } 1528 }
@@ -1696,7 +1696,7 @@ ParseResult::parse(int& argc, char**& argv) @@ -1696,7 +1696,7 @@ ParseResult::parse(int& argc, char**& argv)
1696 auto opt = iter->second; 1696 auto opt = iter->second;
1697 1697
1698 //equals provided for long option? 1698 //equals provided for long option?
1699 - if (result[3].length() != 0) 1699 + if (result[2].length() != 0)
1700 { 1700 {
1701 //parse the option given 1701 //parse the option given
1702 1702
test/options.cpp
@@ -218,7 +218,7 @@ TEST_CASE("Empty with implicit value", "[implicit]") @@ -218,7 +218,7 @@ TEST_CASE("Empty with implicit value", "[implicit]")
218 ("implicit", "Has implicit", cxxopts::value<std::string>() 218 ("implicit", "Has implicit", cxxopts::value<std::string>()
219 ->implicit_value("foo")); 219 ->implicit_value("foo"));
220 220
221 - Argv av({"implicit", "--implicit", ""}); 221 + Argv av({"implicit", "--implicit="});
222 222
223 char** argv = av.argv(); 223 char** argv = av.argv();
224 auto argc = av.argc(); 224 auto argc = av.argc();
@@ -428,7 +428,7 @@ TEST_CASE(&quot;Booleans&quot;, &quot;[boolean]&quot;) { @@ -428,7 +428,7 @@ TEST_CASE(&quot;Booleans&quot;, &quot;[boolean]&quot;) {
428 428
429 options.parse_positional("others"); 429 options.parse_positional("others");
430 430
431 - Argv av({"booleans", "--bool=false", "--debug", "true", "--timing", "extra"}); 431 + Argv av({"booleans", "--bool=false", "--debug=true", "--timing", "extra"});
432 432
433 char** argv = av.argv(); 433 char** argv = av.argv();
434 auto argc = av.argc(); 434 auto argc = av.argc();