mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-03 14:44:40 +00:00
Merge pull request #356 from elpaso/multiple-actions
FEATURE: multiple actions
This commit is contained in:
commit
22b54b8e62
@ -679,9 +679,9 @@ public:
|
||||
std::is_void_v<std::invoke_result_t<F, Args..., std::string const>>,
|
||||
void_action, valued_action>;
|
||||
if constexpr (sizeof...(Args) == 0) {
|
||||
m_action.emplace<action_type>(std::forward<F>(callable));
|
||||
m_actions.emplace_back<action_type>(std::forward<F>(callable));
|
||||
} else {
|
||||
m_action.emplace<action_type>(
|
||||
m_actions.emplace_back<action_type>(
|
||||
[f = std::forward<F>(callable),
|
||||
tup = std::make_tuple(std::forward<Args>(bound_args)...)](
|
||||
std::string const &opt) mutable {
|
||||
@ -1014,7 +1014,12 @@ public:
|
||||
if (num_args_max == 0) {
|
||||
if (!dry_run) {
|
||||
m_values.emplace_back(m_implicit_value);
|
||||
std::visit([](const auto &f) { f({}); }, m_action);
|
||||
for(auto &action: m_actions) {
|
||||
std::visit([&](const auto &f) { f({}); }, action);
|
||||
}
|
||||
if(m_actions.empty()){
|
||||
std::visit([&](const auto &f) { f({}); }, m_default_action);
|
||||
}
|
||||
m_is_used = true;
|
||||
}
|
||||
return start;
|
||||
@ -1054,7 +1059,12 @@ public:
|
||||
Argument &self;
|
||||
};
|
||||
if (!dry_run) {
|
||||
std::visit(ActionApply{start, end, *this}, m_action);
|
||||
for(auto &action: m_actions) {
|
||||
std::visit(ActionApply{start, end, *this}, action);
|
||||
}
|
||||
if(m_actions.empty()){
|
||||
std::visit(ActionApply{start, end, *this}, m_default_action);
|
||||
}
|
||||
m_is_used = true;
|
||||
}
|
||||
return end;
|
||||
@ -1604,7 +1614,8 @@ private:
|
||||
std::optional<std::vector<std::string>> m_choices{std::nullopt};
|
||||
using valued_action = std::function<std::any(const std::string &)>;
|
||||
using void_action = std::function<void(const std::string &)>;
|
||||
std::variant<valued_action, void_action> m_action{
|
||||
std::vector<std::variant<valued_action, void_action>> m_actions;
|
||||
std::variant<valued_action, void_action> m_default_action{
|
||||
std::in_place_type<valued_action>,
|
||||
[](const std::string &value) { return value; }};
|
||||
std::vector<std::any> m_values;
|
||||
|
@ -175,3 +175,28 @@ TEST_CASE("Users can run actions on parameterless optional arguments" *
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Users can add multiple actions and they are all run" *
|
||||
test_suite("actions")) {
|
||||
argparse::ArgumentParser program("test");
|
||||
|
||||
GIVEN("a flag argument with two counting actions") {
|
||||
int count = 0;
|
||||
program.add_argument("-V", "--verbose")
|
||||
.action([&](const auto &) { ++count; })
|
||||
.action([&](const auto &) { ++count; })
|
||||
.append()
|
||||
.default_value(false)
|
||||
.implicit_value(true)
|
||||
.nargs(0);
|
||||
|
||||
WHEN("the flag is parsed") {
|
||||
program.parse_args({"test", "-V"});
|
||||
|
||||
THEN("the count increments twice") {
|
||||
REQUIRE(program.get<bool>("-V"));
|
||||
REQUIRE(count == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -426,3 +426,50 @@ TEST_CASE_TEMPLATE("Parse floating-point argument of fixed format" *
|
||||
std::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test that scan also works with a custom action" *
|
||||
test_suite("scan")) {
|
||||
|
||||
GIVEN("an argument with scan followed by a custom action") {
|
||||
argparse::ArgumentParser program("test");
|
||||
int res;
|
||||
program.add_argument("--int").scan<'i', int>().action([&](const auto &s) {res = std::stoi(s);});
|
||||
|
||||
WHEN("the argument is parsed") {
|
||||
|
||||
SUBCASE("with a valid value") {
|
||||
program.parse_args({"./test.exe", "--int", "3"});
|
||||
THEN("the value is stored") {
|
||||
REQUIRE(res == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("with an invalid value") {
|
||||
REQUIRE_THROWS_AS(program.parse_args({"./test.exe", "--int", "XXX"}),
|
||||
std::invalid_argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("an argument with a custom action followed by scan") {
|
||||
argparse::ArgumentParser program("test");
|
||||
int res;
|
||||
program.add_argument("--int").action([&](const auto &s) {res = std::stoi(s);}).scan<'i', int>();
|
||||
|
||||
WHEN("the argument is parsed") {
|
||||
|
||||
SUBCASE("with a valid value") {
|
||||
program.parse_args({"./test.exe", "--int", "3"});
|
||||
THEN("the value is stored") {
|
||||
REQUIRE(res == 3);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("with an invalid value") {
|
||||
REQUIRE_THROWS_AS(program.parse_args({"./test.exe", "--int", "XXX"}),
|
||||
std::invalid_argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -286,3 +286,38 @@ TEST_CASE("Test store_into(set of string), default value, multi valued, specifie
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test store_into(int) still works with a custom action" *
|
||||
test_suite("store_into")) {
|
||||
|
||||
GIVEN("an argument with store_into followed by a custom action ") {
|
||||
argparse::ArgumentParser program("test");
|
||||
int res;
|
||||
std::string string_res;
|
||||
program.add_argument("--int").store_into(res).action([&](const auto &s) {string_res.append(s);});
|
||||
|
||||
WHEN("the argument is parsed") {
|
||||
program.parse_args({"./test.exe", "--int", "3"});
|
||||
THEN("the value is stored and the action was executed") {
|
||||
REQUIRE(res == 3);
|
||||
REQUIRE(string_res == "3");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("an argument with a custom action followed by store_into")
|
||||
{
|
||||
argparse::ArgumentParser program("test");
|
||||
int res;
|
||||
std::string string_res;
|
||||
program.add_argument("--int").action([&](const auto &s) {string_res.append(s);}).store_into(res);
|
||||
|
||||
WHEN("the argument is parsed") {
|
||||
program.parse_args({"./test.exe", "--int", "3"});
|
||||
THEN("the value is stored and the action was executed") {
|
||||
REQUIRE(res == 3);
|
||||
REQUIRE(string_res == "3");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user