mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 15:14:39 +00:00
Merge pull request #46 from zhihaoy/void-action
Allow actions that return void
This commit is contained in:
commit
77692fda8d
@ -41,6 +41,7 @@ SOFTWARE.
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace argparse {
|
namespace argparse {
|
||||||
@ -114,8 +115,14 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Argument &action(std::function<std::any(const std::string &)> aAction) {
|
template <class F>
|
||||||
mAction = std::move(aAction);
|
auto action(F &&aAction)
|
||||||
|
-> std::enable_if_t<std::is_invocable_v<F, std::string const>,
|
||||||
|
Argument &> {
|
||||||
|
if constexpr (std::is_void_v<std::invoke_result_t<F, std::string const>>)
|
||||||
|
mAction.emplace<void_action>(std::forward<F>(aAction));
|
||||||
|
else
|
||||||
|
mAction.emplace<valued_action>(std::forward<F>(aAction));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +146,21 @@ public:
|
|||||||
if (std::any_of(start, end, Argument::is_optional)) {
|
if (std::any_of(start, end, Argument::is_optional)) {
|
||||||
throw std::runtime_error("optional argument in parameter sequence");
|
throw std::runtime_error("optional argument in parameter sequence");
|
||||||
}
|
}
|
||||||
std::transform(start, end, std::back_inserter(mValues), mAction);
|
struct action_apply {
|
||||||
|
void operator()(valued_action &f) {
|
||||||
|
std::transform(start, end, std::back_inserter(self.mValues), f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(void_action &f) {
|
||||||
|
std::for_each(start, end, f);
|
||||||
|
if (!self.mDefaultValue.has_value())
|
||||||
|
self.mValues.resize(self.mNumArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator start, end;
|
||||||
|
Argument &self;
|
||||||
|
};
|
||||||
|
std::visit(action_apply{start, end, *this}, mAction);
|
||||||
return end;
|
return end;
|
||||||
} else if (mDefaultValue.has_value()) {
|
} else if (mDefaultValue.has_value()) {
|
||||||
return start;
|
return start;
|
||||||
@ -306,8 +327,11 @@ private:
|
|||||||
std::string mHelp;
|
std::string mHelp;
|
||||||
std::any mDefaultValue;
|
std::any mDefaultValue;
|
||||||
std::any mImplicitValue;
|
std::any mImplicitValue;
|
||||||
std::function<std::any(const std::string &)> mAction =
|
using valued_action = std::function<std::any(const std::string &)>;
|
||||||
[](const std::string &aValue) { return aValue; };
|
using void_action = std::function<void(const std::string &)>;
|
||||||
|
std::variant<valued_action, void_action> mAction{
|
||||||
|
std::in_place_type<valued_action>,
|
||||||
|
[](const std::string &aValue) { return aValue; }};
|
||||||
std::vector<std::any> mValues;
|
std::vector<std::any> mValues;
|
||||||
std::vector<std::string> mRawValues;
|
std::vector<std::string> mRawValues;
|
||||||
size_t mNumArgs = 1;
|
size_t mNumArgs = 1;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <argparse.hpp>
|
#include <argparse.hpp>
|
||||||
|
|
||||||
TEST_CASE("Users can use defaul value inside actions", "[actions]") {
|
TEST_CASE("Users can use default value inside actions", "[actions]") {
|
||||||
argparse::ArgumentParser program("test");
|
argparse::ArgumentParser program("test");
|
||||||
program.add_argument("input")
|
program.add_argument("input")
|
||||||
.default_value("bar")
|
.default_value("bar")
|
||||||
@ -17,3 +17,25 @@ TEST_CASE("Users can use defaul value inside actions", "[actions]") {
|
|||||||
program.parse_args({ "test", "fez" });
|
program.parse_args({ "test", "fez" });
|
||||||
REQUIRE(program.get("input") == "bar");
|
REQUIRE(program.get("input") == "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Users can add actions that return nothing", "[actions]") {
|
||||||
|
argparse::ArgumentParser program("test");
|
||||||
|
bool pressed = false;
|
||||||
|
auto &arg = program.add_argument("button").action(
|
||||||
|
[&](const std::string &) mutable { pressed = true; });
|
||||||
|
|
||||||
|
REQUIRE_FALSE(pressed);
|
||||||
|
|
||||||
|
SECTION("action performed") {
|
||||||
|
program.parse_args({"test", "ignored"});
|
||||||
|
REQUIRE(pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("action performed and nothing overrides the default value") {
|
||||||
|
arg.default_value(42);
|
||||||
|
|
||||||
|
program.parse_args({"test", "ignored"});
|
||||||
|
REQUIRE(pressed);
|
||||||
|
REQUIRE(program.get<int>("button") == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user