Merge pull request #310 from p-ranav/bugfix/307_choices

Bugfix/307 choices
This commit is contained in:
Pranav 2023-11-13 16:23:15 -06:00 committed by GitHub
commit 69dabd88a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 4 deletions

View File

@ -657,7 +657,7 @@ public:
} }
template <class F, class... Args> template <class F, class... Args>
auto action(F &&callable, Args &&...bound_args) auto action(F &&callable, Args &&... bound_args)
-> std::enable_if_t<std::is_invocable_v<F, Args..., std::string const>, -> std::enable_if_t<std::is_invocable_v<F, Args..., std::string const>,
Argument &> { Argument &> {
using action_type = std::conditional_t< using action_type = std::conditional_t<
@ -783,7 +783,7 @@ public:
} }
template <typename T, typename... U> template <typename T, typename... U>
Argument &choices(T &&first, U &&...rest) { Argument &choices(T &&first, U &&... rest) {
add_choice(std::forward<T>(first)); add_choice(std::forward<T>(first));
choices(std::forward<U>(rest)...); choices(std::forward<U>(rest)...);
return *this; return *this;
@ -845,8 +845,14 @@ public:
if (m_choices.has_value()) { if (m_choices.has_value()) {
// Check each value in (start, end) and make sure // Check each value in (start, end) and make sure
// it is in the list of allowed choices/options // it is in the list of allowed choices/options
std::size_t i = 0;
auto max_number_of_args = m_num_args_range.get_max();
for (auto it = start; it != end; ++it) { for (auto it = start; it != end; ++it) {
if (i == max_number_of_args) {
break;
}
find_value_in_choices_or_throw(it); find_value_in_choices_or_throw(it);
i += 1;
} }
} }
@ -1546,7 +1552,7 @@ public:
// Parameter packed add_parents method // Parameter packed add_parents method
// Accepts a variadic number of ArgumentParser objects // Accepts a variadic number of ArgumentParser objects
template <typename... Targs> template <typename... Targs>
ArgumentParser &add_parents(const Targs &...f_args) { ArgumentParser &add_parents(const Targs &... f_args) {
for (const ArgumentParser &parent_parser : {std::ref(f_args)...}) { for (const ArgumentParser &parent_parser : {std::ref(f_args)...}) {
for (const auto &argument : parent_parser.m_positional_arguments) { for (const auto &argument : parent_parser.m_positional_arguments) {
auto it = m_positional_arguments.insert( auto it = m_positional_arguments.insert(

View File

@ -23,6 +23,72 @@ TEST_CASE("Parse argument that is in the fixed number of allowed choices" *
program.parse_args({"test", "red"}); program.parse_args({"test", "red"});
} }
TEST_CASE("Parse argument that is in the fixed number of allowed choices, with "
"other positional argument" *
test_suite("choices")) {
argparse::ArgumentParser program("test");
program.add_argument("--input")
.default_value(std::string{"baz"})
.choices("foo", "bar", "baz");
program.add_argument("--value").scan<'i', int>().default_value(0);
REQUIRE_NOTHROW(
program.parse_args({"test", "--input", "foo", "--value", "1"}));
REQUIRE(program.get("--input") == "foo");
REQUIRE(program.get<int>("--value") == 1);
}
TEST_CASE(
"Parse nargs argument that is in the fixed number of allowed choices, with "
"other positional argument" *
test_suite("choices")) {
argparse::ArgumentParser program("test");
program.add_argument("--input")
.default_value(std::string{"baz"})
.choices("foo", "bar", "baz")
.nargs(2);
program.add_argument("--value").scan<'i', int>().default_value(0);
REQUIRE_NOTHROW(
program.parse_args({"test", "--input", "foo", "bar", "--value", "1"}));
REQUIRE((program.get<std::vector<std::string>>("--input") ==
std::vector<std::string>{"foo", "bar"}));
REQUIRE(program.get<int>("--value") == 1);
}
TEST_CASE("Parse argument that is in the fixed number of allowed choices, with "
"other positional argument (reversed)" *
test_suite("choices")) {
argparse::ArgumentParser program("test");
program.add_argument("--input")
.default_value(std::string{"baz"})
.choices("foo", "bar", "baz");
program.add_argument("--value").scan<'i', int>().default_value(0);
REQUIRE_NOTHROW(
program.parse_args({"test", "--value", "1", "--input", "foo"}));
REQUIRE(program.get("--input") == "foo");
REQUIRE(program.get<int>("--value") == 1);
}
TEST_CASE(
"Parse nargs argument that is in the fixed number of allowed choices, with "
"other positional argument (reversed)" *
test_suite("choices")) {
argparse::ArgumentParser program("test");
program.add_argument("--input")
.default_value(std::string{"baz"})
.choices("foo", "bar", "baz")
.nargs(2);
program.add_argument("--value").scan<'i', int>().default_value(0);
REQUIRE_NOTHROW(
program.parse_args({"test", "--value", "1", "--input", "foo", "bar"}));
REQUIRE((program.get<std::vector<std::string>>("--input") ==
std::vector<std::string>{"foo", "bar"}));
REQUIRE(program.get<int>("--value") == 1);
}
TEST_CASE("Parse argument that is in the fixed number of allowed choices, with " TEST_CASE("Parse argument that is in the fixed number of allowed choices, with "
"invalid default" * "invalid default" *
test_suite("choices")) { test_suite("choices")) {
@ -88,4 +154,4 @@ TEST_CASE("Parse multiple arguments that are not in fixed number of allowed "
program.parse_args({"test", "6", "7"}), program.parse_args({"test", "6", "7"}),
"Invalid argument \"6\" - allowed options: {1, 2, 3, 4, 5}", "Invalid argument \"6\" - allowed options: {1, 2, 3, 4, 5}",
std::runtime_error); std::runtime_error);
} }