Commit 9e3f3115d2249dc2689b39bdc51a412a23c04204

Authored by Jarryd Beck
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.
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 }
... ...