diff --git a/include/argparse/argparse.hpp b/include/argparse/argparse.hpp index 3baba88..f0dd85b 100644 --- a/include/argparse/argparse.hpp +++ b/include/argparse/argparse.hpp @@ -2336,6 +2336,22 @@ protected: } } auto argument = positional_argument_it++; + + // Deal with the situation of ... + if (argument->m_num_args_range.get_min() == 1 && + argument->m_num_args_range.get_max() == (std::numeric_limits::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; } diff --git a/test/test_positional_arguments.cpp b/test/test_positional_arguments.cpp index 1665048..ae5b99f 100644 --- a/test/test_positional_arguments.cpp +++ b/test/test_positional_arguments.cpp @@ -264,3 +264,40 @@ TEST_CASE("Square a number" * test_suite("positional_arguments")) { program.parse_args({"./main", "15"}); REQUIRE(program.get("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 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{"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{"one", "two"}); + REQUIRE(exactly_one == "three"); + } + } + + WHEN("provided one, two") { + THEN("parse_args throws") { + REQUIRE_THROWS(program.parse_args({"./main", "one"})); + } + } + } +}