mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-03 22:54:39 +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>>,
|
std::is_void_v<std::invoke_result_t<F, Args..., std::string const>>,
|
||||||
void_action, valued_action>;
|
void_action, valued_action>;
|
||||||
if constexpr (sizeof...(Args) == 0) {
|
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 {
|
} else {
|
||||||
m_action.emplace<action_type>(
|
m_actions.emplace_back<action_type>(
|
||||||
[f = std::forward<F>(callable),
|
[f = std::forward<F>(callable),
|
||||||
tup = std::make_tuple(std::forward<Args>(bound_args)...)](
|
tup = std::make_tuple(std::forward<Args>(bound_args)...)](
|
||||||
std::string const &opt) mutable {
|
std::string const &opt) mutable {
|
||||||
@ -1014,7 +1014,12 @@ public:
|
|||||||
if (num_args_max == 0) {
|
if (num_args_max == 0) {
|
||||||
if (!dry_run) {
|
if (!dry_run) {
|
||||||
m_values.emplace_back(m_implicit_value);
|
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;
|
m_is_used = true;
|
||||||
}
|
}
|
||||||
return start;
|
return start;
|
||||||
@ -1054,7 +1059,12 @@ public:
|
|||||||
Argument &self;
|
Argument &self;
|
||||||
};
|
};
|
||||||
if (!dry_run) {
|
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;
|
m_is_used = true;
|
||||||
}
|
}
|
||||||
return end;
|
return end;
|
||||||
@ -1604,7 +1614,8 @@ private:
|
|||||||
std::optional<std::vector<std::string>> m_choices{std::nullopt};
|
std::optional<std::vector<std::string>> m_choices{std::nullopt};
|
||||||
using valued_action = std::function<std::any(const std::string &)>;
|
using valued_action = std::function<std::any(const std::string &)>;
|
||||||
using void_action = std::function<void(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>,
|
std::in_place_type<valued_action>,
|
||||||
[](const std::string &value) { return value; }};
|
[](const std::string &value) { return value; }};
|
||||||
std::vector<std::any> m_values;
|
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);
|
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