Commit abe9ebd6b4084d576ceb79904c94ef8c9c0e6c56
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.
Showing
3 changed files
with
14 additions
and
4 deletions
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("Booleans", "[boolean]") { | @@ -428,7 +428,7 @@ TEST_CASE("Booleans", "[boolean]") { | ||
| 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(); |