Fix parsing of a program that accepts a positional argument with 1:* cardinality followed by another positional argument with 1:1

This commit is contained in:
Even Rouault 2024-04-02 23:34:35 +02:00
parent a1c41c5537
commit 2c245a2c3b
No known key found for this signature in database
GPG Key ID: 33EBBFC47B3DD87D
2 changed files with 53 additions and 0 deletions

View File

@ -2322,6 +2322,22 @@ protected:
} }
} }
auto argument = positional_argument_it++; auto argument = positional_argument_it++;
// Deal with the situation of <positional_arg1>... <positional_arg2>
if (argument->m_num_args_range.get_min() == 1 &&
argument->m_num_args_range.get_max() == (std::numeric_limits<std::size_t>::max)() &&
positional_argument_it != std::end(m_positional_arguments) &&
std::next(positional_argument_it) == std::end(m_positional_arguments) &&
positional_argument_it->m_num_args_range.get_min() == 1 &&
positional_argument_it->m_num_args_range.get_max() == 1 ) {
if (std::next(it) != end) {
positional_argument_it->consume(std::prev(end), end);
end = std::prev(end);
} else {
throw std::runtime_error("Missing " + positional_argument_it->m_names.front());
}
}
it = argument->consume(it, end); it = argument->consume(it, end);
continue; continue;
} }

View File

@ -264,3 +264,40 @@ TEST_CASE("Square a number" * test_suite("positional_arguments")) {
program.parse_args({"./main", "15"}); program.parse_args({"./main", "15"});
REQUIRE(program.get<double>("square") == 225); REQUIRE(program.get<double>("square") == 225);
} }
TEST_CASE("At_least_one_followed_by_exactly_one" * test_suite("positional_arguments")) {
GIVEN("a program that accepts a positional argument with at_least_one cardinality followed by another positional argument with 1:1") {
argparse::ArgumentParser program;
std::vector<std::string> at_least_one;
program.add_argument("at_least_one")
.nargs(argparse::nargs_pattern::at_least_one)
.store_into(at_least_one);
std::string exactly_one;
program.add_argument("exactly_one")
.store_into(exactly_one);
WHEN("provided one, two") {
THEN("parse_args works") {
program.parse_args({"./main", "one", "two"});
REQUIRE(at_least_one == std::vector<std::string>{"one"});
REQUIRE(exactly_one == "two");
}
}
WHEN("provided one, two, three") {
THEN("parse_args works") {
program.parse_args({"./main", "one", "two", "three"});
REQUIRE(at_least_one == std::vector<std::string>{"one", "two"});
REQUIRE(exactly_one == "three");
}
}
WHEN("provided one, two") {
THEN("parse_args throws") {
REQUIRE_THROWS(program.parse_args({"./main", "one"}));
}
}
}
}