Util+Test: Add support for '--' to enable non-option mode
This commit is contained in:
+11
-2
@@ -204,6 +204,9 @@ bool ArgParser::parse(int argc, const char* argv[])
|
|||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
|
// By default parse all '-' prefixed parameters as options
|
||||||
|
m_nonOptionMode = false;
|
||||||
|
|
||||||
// Get program name
|
// Get program name
|
||||||
m_name = argv[0] + std::string_view(argv[0]).find_last_of('/') + 1;
|
m_name = argv[0] + std::string_view(argv[0]).find_last_of('/') + 1;
|
||||||
|
|
||||||
@@ -214,6 +217,7 @@ bool ArgParser::parse(int argc, const char* argv[])
|
|||||||
for (; m_optionIndex < argc; ++m_optionIndex) {
|
for (; m_optionIndex < argc; ++m_optionIndex) {
|
||||||
printf("argv[%d]: %s\n", m_optionIndex, argv[m_optionIndex]);
|
printf("argv[%d]: %s\n", m_optionIndex, argv[m_optionIndex]);
|
||||||
|
|
||||||
|
// Get the current and next parameter
|
||||||
argument = argv[m_optionIndex];
|
argument = argv[m_optionIndex];
|
||||||
if (m_optionIndex + 1 < argc && argv[m_optionIndex + 1][0] != '-') {
|
if (m_optionIndex + 1 < argc && argv[m_optionIndex + 1][0] != '-') {
|
||||||
next = argv[m_optionIndex + 1];
|
next = argv[m_optionIndex + 1];
|
||||||
@@ -222,15 +226,20 @@ bool ArgParser::parse(int argc, const char* argv[])
|
|||||||
next = {};
|
next = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop parsing '-' prefixed parameters as options afer '--'
|
||||||
|
if (argument.compare("--") == 0) {
|
||||||
|
m_nonOptionMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Long Option
|
// Long Option
|
||||||
if (argument[0] == '-' && argument[1] == '-') {
|
if (!m_nonOptionMode && argument[0] == '-' && argument[1] == '-') {
|
||||||
argument = argument.substr(argument.find_first_not_of('-'));
|
argument = argument.substr(argument.find_first_not_of('-'));
|
||||||
if (!parseLongOption(argument, next)) {
|
if (!parseLongOption(argument, next)) {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Short Option
|
// Short Option
|
||||||
else if (argument[0] == '-') {
|
else if (!m_nonOptionMode && argument[0] == '-') {
|
||||||
argument = argument.substr(argument.find_first_not_of('-'));
|
argument = argument.substr(argument.find_first_not_of('-'));
|
||||||
if (!parseShortOption(argument, next)) {
|
if (!parseShortOption(argument, next)) {
|
||||||
result = false;
|
result = false;
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ private:
|
|||||||
bool parseLongOption(std::string_view option, std::string_view next);
|
bool parseLongOption(std::string_view option, std::string_view next);
|
||||||
|
|
||||||
int m_optionIndex { 1 };
|
int m_optionIndex { 1 };
|
||||||
|
bool m_nonOptionMode { false };
|
||||||
bool m_exitOnFirstError { true };
|
bool m_exitOnFirstError { true };
|
||||||
bool m_errorMessages { true };
|
bool m_errorMessages { true };
|
||||||
// TODO: Implement this, maybe combine with error messages flag, enum class? or bitfield
|
// TODO: Implement this, maybe combine with error messages flag, enum class? or bitfield
|
||||||
|
|||||||
@@ -312,3 +312,54 @@ TEST_CASE(MultipleOptions)
|
|||||||
EXPECT_EQ(boolOpt1, true);
|
EXPECT_EQ(boolOpt1, true);
|
||||||
EXPECT_EQ(stringOpt1, "a-string-value");
|
EXPECT_EQ(stringOpt1, "a-string-value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE(NonOptionMode)
|
||||||
|
{
|
||||||
|
// Bool short options, missing
|
||||||
|
// Expected: The bool options are interpreted as non-option parameters
|
||||||
|
bool boolOpt1 = false;
|
||||||
|
bool boolOpt2 = false;
|
||||||
|
auto result = runParser({ "--", "-b", "-c" }, [&](auto& parser) {
|
||||||
|
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||||
|
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(boolOpt1, false);
|
||||||
|
EXPECT_EQ(boolOpt2, false);
|
||||||
|
|
||||||
|
// Bool short options, one given
|
||||||
|
// Expected: boolOpt1 is set, one non-option parameter
|
||||||
|
boolOpt1 = false;
|
||||||
|
boolOpt2 = false;
|
||||||
|
result = runParser({ "-b", "--", "-c" }, [&](auto& parser) {
|
||||||
|
parser.addOption(boolOpt1, 'b', nullptr, nullptr, nullptr);
|
||||||
|
parser.addOption(boolOpt2, 'c', nullptr, nullptr, nullptr);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(boolOpt1, true);
|
||||||
|
EXPECT_EQ(boolOpt2, false);
|
||||||
|
|
||||||
|
// Bool long options, missing
|
||||||
|
// Expected: The bool options are interpreted as non-option parameters
|
||||||
|
boolOpt1 = false;
|
||||||
|
boolOpt2 = false;
|
||||||
|
result = runParser({ "--", "--bool", "--cool" }, [&](auto& parser) {
|
||||||
|
parser.addOption(boolOpt1, '\0', "bool", nullptr, nullptr);
|
||||||
|
parser.addOption(boolOpt2, '\0', "cool", nullptr, nullptr);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(boolOpt1, false);
|
||||||
|
EXPECT_EQ(boolOpt2, false);
|
||||||
|
|
||||||
|
// Bool long options, one given
|
||||||
|
// Expected: boolOpt1 is set, one non-option parameter
|
||||||
|
boolOpt1 = false;
|
||||||
|
boolOpt2 = false;
|
||||||
|
result = runParser({ "--bool", "--", "--cool" }, [&](auto& parser) {
|
||||||
|
parser.addOption(boolOpt1, '\0', "bool", nullptr, nullptr);
|
||||||
|
parser.addOption(boolOpt2, '\0', "cool", nullptr, nullptr);
|
||||||
|
});
|
||||||
|
EXPECT_EQ(result, true);
|
||||||
|
EXPECT_EQ(boolOpt1, true);
|
||||||
|
EXPECT_EQ(boolOpt2, false);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user