Merge pull request #344 from rouault/At_least_one_followed_by_exactly_one

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:
Pranav 2024-04-02 19:46:38 -04:00 committed by GitHub
commit 9550b0a88c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 0 deletions

View File

@ -2336,6 +2336,22 @@ protected:
}
}
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);
continue;
}

View File

@ -264,3 +264,40 @@ TEST_CASE("Square a number" * test_suite("positional_arguments")) {
program.parse_args({"./main", "15"});
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"}));
}
}
}
}