mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 07:04:39 +00:00
Added support for compound arguments, e.g., ./main -aux foo bar
This commit is contained in:
parent
41009046f2
commit
07cad7ac9e
@ -70,6 +70,7 @@ struct Argument {
|
||||
|
||||
Argument& implicit_value(std::any aImplicitValue) {
|
||||
mImplicitValue = aImplicitValue;
|
||||
mNumArgs = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -156,7 +157,7 @@ class ArgumentParser {
|
||||
add_argument_internal(tArgument, Fargs...);
|
||||
|
||||
for (auto& mName : tArgument->mNames) {
|
||||
if (starts_with(mName, "--") || starts_with(mName, "-"))
|
||||
if (is_optional(mName))
|
||||
tArgument->mIsOptional = true;
|
||||
}
|
||||
|
||||
@ -189,8 +190,8 @@ class ArgumentParser {
|
||||
// Check to see if implicit value should be used
|
||||
// Two cases to handle here:
|
||||
// (1) User has explicitly programmed nargs to be 0
|
||||
// (2) User has left nargs to be default, i.e., 1 and provided an implicit value
|
||||
if (tCount == 0 || (tArgument->mImplicitValue.has_value() && tCount == 1)) {
|
||||
// (2) User has provided an implicit value, which also sets nargs to 0
|
||||
if (tCount == 0) {
|
||||
// Use implicit value for this optional argument
|
||||
tArgument->mValues.push_back(tArgument->mImplicitValue);
|
||||
tArgument->mRawValues.push_back("");
|
||||
@ -212,6 +213,30 @@ class ArgumentParser {
|
||||
tCount -= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (is_optional(argv[i])) {
|
||||
// This is possibly a compound optional argument
|
||||
// Example: We have three optional arguments -a, -u and -x
|
||||
// The user provides ./main -aux ...
|
||||
// Here -aux is a compound optional argument
|
||||
std::string tCompoundArgument = std::string(argv[i]);
|
||||
for (size_t j = 1; j < tCompoundArgument.size(); j++) {
|
||||
std::string tArgument(1, tCompoundArgument[j]);
|
||||
size_t tNumArgs = 0;
|
||||
std::map<std::string, std::shared_ptr<Argument>>::iterator tIterator = mArgumentMap.find("-" + tArgument);
|
||||
if (tIterator != mArgumentMap.end()) {
|
||||
auto tArgumentObject = tIterator->second;
|
||||
tNumArgs = tArgumentObject->mNumArgs;
|
||||
}
|
||||
std::vector<std::string> tArgumentsForRecursiveParsing = { "", "-" + tArgument };
|
||||
while (tNumArgs > 0) {
|
||||
i += 1;
|
||||
tArgumentsForRecursiveParsing.push_back(argv[i]);
|
||||
tNumArgs -= 1;
|
||||
}
|
||||
parse_args(tArgumentsForRecursiveParsing);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This is a positional argument.
|
||||
// Parse and save into mPositionalArguments vector
|
||||
@ -242,6 +267,7 @@ class ArgumentParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T = std::string>
|
||||
typename std::enable_if<is_specialization<T, std::vector>::value == false, T>::type
|
||||
@ -279,6 +305,15 @@ class ArgumentParser {
|
||||
return *aArgument;
|
||||
}
|
||||
|
||||
bool is_optional(const std::string& aName) {
|
||||
return (starts_with(aName, "--") || starts_with(aName, "-"));
|
||||
}
|
||||
|
||||
bool is_valid_argument(const std::string& aName) {
|
||||
std::map<std::string, std::shared_ptr<Argument>>::iterator tIterator = mArgumentMap.find(aName);
|
||||
return (tIterator != mArgumentMap.end());
|
||||
}
|
||||
|
||||
std::string mProgramName;
|
||||
std::vector<std::shared_ptr<Argument>> mPositionalArguments;
|
||||
size_t mNextPositionalArgument;
|
||||
|
@ -25,3 +25,72 @@ TEST_CASE("Parse toggle arguments with implicit value", "[parse_args]") {
|
||||
REQUIRE(arguments.size() == 1);
|
||||
REQUIRE(program.get<bool>("--verbose") == true);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse multiple toggle arguments with implicit values", "[parse_args]") {
|
||||
argparse::ArgumentParser program("test");
|
||||
program.add_argument("-a")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("-u")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("-x")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.parse_args({ "./test.exe", "-a", "-x" });
|
||||
auto arguments = program.get_arguments();
|
||||
REQUIRE(arguments.size() == 3);
|
||||
REQUIRE(program.get<bool>("-a") == true);
|
||||
REQUIRE(program.get<bool>("-u") == false);
|
||||
REQUIRE(program.get<bool>("-x") == true);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse compound toggle arguments with implicit values", "[parse_args]") {
|
||||
argparse::ArgumentParser program("test");
|
||||
program.add_argument("-a")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("-u")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("-x")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.parse_args({ "./test.exe", "-aux" });
|
||||
auto arguments = program.get_arguments();
|
||||
REQUIRE(arguments.size() == 3);
|
||||
REQUIRE(program.get<bool>("-a") == true);
|
||||
REQUIRE(program.get<bool>("-u") == true);
|
||||
REQUIRE(program.get<bool>("-x") == true);
|
||||
}
|
||||
|
||||
TEST_CASE("Parse compound toggle arguments with implicit values and nargs", "[parse_args]") {
|
||||
argparse::ArgumentParser program("test");
|
||||
program.add_argument("-a")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("-b")
|
||||
.default_value(false)
|
||||
.implicit_value(true);
|
||||
|
||||
program.add_argument("-c")
|
||||
.nargs(2)
|
||||
.action([](const std::string& value) { return std::stof(value); });
|
||||
|
||||
program.parse_args({ "./test.exe", "-abc", "3.14", "2.718" });
|
||||
auto arguments = program.get_arguments();
|
||||
REQUIRE(arguments.size() == 3);
|
||||
REQUIRE(program.get<bool>("-a") == true);
|
||||
REQUIRE(program.get<bool>("-b") == true);
|
||||
auto c = program.get<std::vector<float>>("-c");
|
||||
REQUIRE(c.size() == 2);
|
||||
REQUIRE(c[0] == 3.14f);
|
||||
REQUIRE(c[1] == 2.718f);
|
||||
}
|
Loading…
Reference in New Issue
Block a user