Util+Test: Add parsing of multi-value options
This commit is contained in:
@@ -293,4 +293,21 @@ void ArgParser::addOption(std::string& value, char shortName, const char* longNa
|
|||||||
addOption(std::move(option));
|
addOption(std::move(option));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArgParser::addOption(std::vector<std::string>& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument)
|
||||||
|
{
|
||||||
|
Option option {
|
||||||
|
shortName,
|
||||||
|
longName,
|
||||||
|
argumentName,
|
||||||
|
usageString,
|
||||||
|
manString,
|
||||||
|
requiresArgument,
|
||||||
|
[&value](const char* a) -> bool {
|
||||||
|
value.push_back(a);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addOption(std::move(option));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Util
|
} // namespace Util
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public:
|
|||||||
void addOption(Option&& option);
|
void addOption(Option&& option);
|
||||||
void addOption(bool& value, char shortName, const char* longName, const char* usageString, const char* manString);
|
void addOption(bool& value, char shortName, const char* longName, const char* usageString, const char* manString);
|
||||||
void addOption(std::string& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No);
|
void addOption(std::string& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No);
|
||||||
|
void addOption(std::vector<std::string>& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No);
|
||||||
|
|
||||||
void setOptionIndex(int index) { m_optionIndex = index; }
|
void setOptionIndex(int index) { m_optionIndex = index; }
|
||||||
void setExitOnFirstError(bool state) { m_exitOnFirstError = state; }
|
void setExitOnFirstError(bool state) { m_exitOnFirstError = state; }
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "testcase.h"
|
#include "testcase.h"
|
||||||
@@ -299,6 +300,105 @@ TEST_CASE(SingleNonRequiredStringOptions)
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
|
TEST_CASE(VectorStringOptions)
|
||||||
|
{
|
||||||
|
// Required vector string short option, not given
|
||||||
|
std::vector<std::string> vectorOpt1 = {};
|
||||||
|
auto result = runParser({}, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 0);
|
||||||
|
|
||||||
|
// Required vector string short option, empty given
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "-v" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, false);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 0);
|
||||||
|
|
||||||
|
// Required vector string short option, one given
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "-v", "a vector argument!" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 1);
|
||||||
|
if (vectorOpt1.size() == 1) {
|
||||||
|
EXPECT_EQ(vectorOpt1[0], "a vector argument!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required vector string short option, two given
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "-v", "hello", "-v", "world" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 2);
|
||||||
|
if (vectorOpt1.size() == 2) {
|
||||||
|
EXPECT_EQ(vectorOpt1[0], "hello");
|
||||||
|
EXPECT_EQ(vectorOpt1[1], "world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required vector string short option, two given directly after
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "-vhello", "-vworld" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, 'v', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 2);
|
||||||
|
if (vectorOpt1.size() == 2) {
|
||||||
|
EXPECT_EQ(vectorOpt1[0], "hello");
|
||||||
|
EXPECT_EQ(vectorOpt1[1], "world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required vector string long option, empty given
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "--vector" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, false);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 0);
|
||||||
|
|
||||||
|
// Required vector string long option, one given
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "--vector", "a vector argument!" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 1);
|
||||||
|
if (vectorOpt1.size() == 1) {
|
||||||
|
EXPECT_EQ(vectorOpt1[0], "a vector argument!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required vector string long option, two given
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "--vector", "hello", "--vector", "world" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 2);
|
||||||
|
if (vectorOpt1.size() == 2) {
|
||||||
|
EXPECT_EQ(vectorOpt1[0], "hello");
|
||||||
|
EXPECT_EQ(vectorOpt1[1], "world");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required vector string long option, two given directly after
|
||||||
|
vectorOpt1 = {};
|
||||||
|
result = runParser({ "--vector=hello", "--vector=world" }, [&](auto& parser) {
|
||||||
|
parser.addOption(vectorOpt1, '\0', "vector", nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(vectorOpt1.size(), 2);
|
||||||
|
if (vectorOpt1.size() == 2) {
|
||||||
|
EXPECT_EQ(vectorOpt1[0], "hello");
|
||||||
|
EXPECT_EQ(vectorOpt1[1], "world");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
TEST_CASE(MultipleOptions)
|
TEST_CASE(MultipleOptions)
|
||||||
{
|
{
|
||||||
// Both short options, second is required, with a non-option argument in-between
|
// Both short options, second is required, with a non-option argument in-between
|
||||||
@@ -313,6 +413,8 @@ TEST_CASE(MultipleOptions)
|
|||||||
EXPECT_EQ(stringOpt1, "a-string-value");
|
EXPECT_EQ(stringOpt1, "a-string-value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
TEST_CASE(NonOptionMode)
|
TEST_CASE(NonOptionMode)
|
||||||
{
|
{
|
||||||
// Bool short options, missing
|
// Bool short options, missing
|
||||||
|
|||||||
Reference in New Issue
Block a user