Commit 9e3f3115d2249dc2689b39bdc51a412a23c04204
1 parent
b0078c65
Don't overwrite positional arguments.
Fixes #30. The positional arguments are not overwritten when they have already been given on the command line.
Showing
2 changed files
with
66 additions
and
15 deletions
src/cxxopts.hpp
| ... | ... | @@ -1031,20 +1031,35 @@ Options::add_to_option(const std::string& option, const std::string& arg) |
| 1031 | 1031 | bool |
| 1032 | 1032 | Options::consume_positional(std::string a) |
| 1033 | 1033 | { |
| 1034 | - if (m_next_positional != m_positional.end()) | |
| 1034 | + while (m_next_positional != m_positional.end()) | |
| 1035 | 1035 | { |
| 1036 | - add_to_option(*m_next_positional, a); | |
| 1037 | - | |
| 1038 | 1036 | auto iter = m_options.find(*m_next_positional); |
| 1039 | - if (iter != m_options.end() && !iter->second->value().is_container()) { | |
| 1040 | - ++m_next_positional; | |
| 1037 | + if (iter != m_options.end()) | |
| 1038 | + { | |
| 1039 | + if (!iter->second->value().is_container()) | |
| 1040 | + { | |
| 1041 | + if (iter->second->count() == 0) | |
| 1042 | + { | |
| 1043 | + add_to_option(*m_next_positional, a); | |
| 1044 | + ++m_next_positional; | |
| 1045 | + return true; | |
| 1046 | + } | |
| 1047 | + else | |
| 1048 | + { | |
| 1049 | + ++m_next_positional; | |
| 1050 | + continue; | |
| 1051 | + } | |
| 1052 | + } | |
| 1053 | + else | |
| 1054 | + { | |
| 1055 | + add_to_option(*m_next_positional, a); | |
| 1056 | + return true; | |
| 1057 | + } | |
| 1041 | 1058 | } |
| 1042 | - return true; | |
| 1043 | - } | |
| 1044 | - else | |
| 1045 | - { | |
| 1046 | - return false; | |
| 1059 | + ++m_next_positional; | |
| 1047 | 1060 | } |
| 1061 | + | |
| 1062 | + return false; | |
| 1048 | 1063 | } |
| 1049 | 1064 | |
| 1050 | 1065 | void | ... | ... |
test/options.cpp
| ... | ... | @@ -78,11 +78,47 @@ TEST_CASE("Basic options", "[options]") |
| 78 | 78 | |
| 79 | 79 | TEST_CASE("No positional", "[positional]") |
| 80 | 80 | { |
| 81 | - cxxopts::Options options("test_positional", " - test no positional options"); | |
| 81 | + cxxopts::Options options("test_no_positional", | |
| 82 | + " - test no positional options"); | |
| 82 | 83 | |
| 83 | - Argv argv({"tester", "a", "b", "def"}); | |
| 84 | + Argv av({"tester", "a", "b", "def"}); | |
| 84 | 85 | |
| 85 | - char** passed_argv = argv.argv(); | |
| 86 | - auto argc = argv.argc(); | |
| 87 | - options.parse(argc, passed_argv); | |
| 86 | + char** argv = av.argv(); | |
| 87 | + auto argc = av.argc(); | |
| 88 | + options.parse(argc, argv); | |
| 89 | + | |
| 90 | + REQUIRE(argc == 4); | |
| 91 | + CHECK(strcmp(argv[1], "a") == 0); | |
| 92 | +} | |
| 93 | + | |
| 94 | +TEST_CASE("Some positional explicit", "[positional]") | |
| 95 | +{ | |
| 96 | + cxxopts::Options options("positional_explicit", " - test positional"); | |
| 97 | + | |
| 98 | + options.add_options() | |
| 99 | + ("input", "Input file", cxxopts::value<std::string>()) | |
| 100 | + ("output", "Output file", cxxopts::value<std::string>()) | |
| 101 | + ("positional", "Positional parameters", | |
| 102 | + cxxopts::value<std::vector<std::string>>()) | |
| 103 | + ; | |
| 104 | + | |
| 105 | + options.parse_positional({"input", "output", "positional"}); | |
| 106 | + | |
| 107 | + Argv av({"tester", "--output", "a", "b", "c", "d"}); | |
| 108 | + | |
| 109 | + char** argv = av.argv(); | |
| 110 | + auto argc = av.argc(); | |
| 111 | + | |
| 112 | + options.parse(argc, argv); | |
| 113 | + | |
| 114 | + CHECK(argc == 1); | |
| 115 | + CHECK(options.count("output")); | |
| 116 | + CHECK(options["input"].as<std::string>() == "b"); | |
| 117 | + CHECK(options["output"].as<std::string>() == "a"); | |
| 118 | + | |
| 119 | + auto& positional = options["positional"].as<std::vector<std::string>>(); | |
| 120 | + | |
| 121 | + REQUIRE(positional.size() == 2); | |
| 122 | + CHECK(positional[0] == "c"); | |
| 123 | + CHECK(positional[1] == "d"); | |
| 88 | 124 | } | ... | ... |