Util+Test: Add setting to stop parsing on first non-option
This commit is contained in:
@@ -24,7 +24,7 @@ void ArgParser::printOptionError(char name, Error error)
|
|||||||
|
|
||||||
void ArgParser::printOptionError(const char* name, Error error, bool longName)
|
void ArgParser::printOptionError(const char* name, Error error, bool longName)
|
||||||
{
|
{
|
||||||
if (!m_errorMessages) {
|
if (!m_errorReporting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,14 +206,15 @@ bool ArgParser::parse(int argc, const char* argv[])
|
|||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
|
// Skip program name argument
|
||||||
|
m_optionIndex = 1;
|
||||||
|
|
||||||
// By default parse all '-' prefixed parameters as options
|
// By default parse all '-' prefixed parameters as options
|
||||||
m_nonOptionMode = false;
|
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;
|
||||||
|
|
||||||
printf("name: %s\n", m_name);
|
|
||||||
|
|
||||||
std::string_view argument;
|
std::string_view argument;
|
||||||
std::string_view next;
|
std::string_view next;
|
||||||
for (; m_optionIndex < argc; ++m_optionIndex) {
|
for (; m_optionIndex < argc; ++m_optionIndex) {
|
||||||
@@ -250,6 +251,9 @@ bool ArgParser::parse(int argc, const char* argv[])
|
|||||||
}
|
}
|
||||||
// Argument
|
// Argument
|
||||||
else {
|
else {
|
||||||
|
if (m_stopParsingOnFirstNonOption) {
|
||||||
|
m_nonOptionMode = true;
|
||||||
|
}
|
||||||
printf("-> argu: '%s'", argument.data());
|
printf("-> argu: '%s'", argument.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,10 +54,9 @@ public:
|
|||||||
void addOption(double& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No);
|
void addOption(double& 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 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 setErrorReporting(bool state) { m_errorReporting = state; }
|
||||||
void setExitOnFirstError(bool state) { m_exitOnFirstError = state; }
|
void setExitOnFirstError(bool state) { m_exitOnFirstError = state; }
|
||||||
void setErrorMessages(bool state) { m_errorMessages = state; }
|
void setStopParsingOnFirstNonOption(bool state) { m_stopParsingOnFirstNonOption = state; }
|
||||||
void setNonOptionAfterFirst(bool state) { m_nonOptionAfterFirst = state; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void printOptionError(char name, Error error);
|
void printOptionError(char name, Error error);
|
||||||
@@ -65,12 +64,12 @@ private:
|
|||||||
bool parseShortOption(std::string_view option, std::string_view next);
|
bool parseShortOption(std::string_view option, std::string_view next);
|
||||||
bool parseLongOption(std::string_view option, std::string_view next);
|
bool parseLongOption(std::string_view option, std::string_view next);
|
||||||
|
|
||||||
|
bool m_errorReporting { true };
|
||||||
|
bool m_exitOnFirstError { true };
|
||||||
|
bool m_stopParsingOnFirstNonOption { false };
|
||||||
|
|
||||||
int m_optionIndex { 1 };
|
int m_optionIndex { 1 };
|
||||||
bool m_nonOptionMode { false };
|
bool m_nonOptionMode { false };
|
||||||
bool m_exitOnFirstError { true };
|
|
||||||
bool m_errorMessages { true };
|
|
||||||
// TODO: Implement this, maybe combine with error messages flag, enum class? or bitfield
|
|
||||||
bool m_nonOptionAfterFirst { false };
|
|
||||||
|
|
||||||
const char* m_name;
|
const char* m_name;
|
||||||
std::vector<Option> m_options;
|
std::vector<Option> m_options;
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ TEST_CASE(MultipleOptions)
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
TEST_CASE(NonOptionMode)
|
TEST_CASE(StopOnDoubleDashOption)
|
||||||
{
|
{
|
||||||
// Bool short options, missing
|
// Bool short options, missing
|
||||||
// Expected: The bool options are interpreted as non-option parameters
|
// Expected: The bool options are interpreted as non-option parameters
|
||||||
@@ -534,3 +534,60 @@ TEST_CASE(NonOptionMode)
|
|||||||
EXPECT_EQ(boolOpt1, true);
|
EXPECT_EQ(boolOpt1, true);
|
||||||
EXPECT_EQ(boolOpt2, false);
|
EXPECT_EQ(boolOpt2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
TEST_CASE(StopOnFirstNonOption)
|
||||||
|
{
|
||||||
|
// Do not stop on first non-option; arguments are in correct order
|
||||||
|
// Expected: The bool options are set and one non-option parameter
|
||||||
|
bool boolOpt1 = false;
|
||||||
|
bool boolOpt2 = false;
|
||||||
|
auto result = runParser({ "-b", "-c", "stopping" }, [&](auto& parser) {
|
||||||
|
parser.setStopParsingOnFirstNonOption(false);
|
||||||
|
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, true);
|
||||||
|
|
||||||
|
// Do not stop on first non-option; arguments are in wrong order
|
||||||
|
// Expected: The bool options are set and one non-option parameter
|
||||||
|
boolOpt1 = false;
|
||||||
|
boolOpt2 = false;
|
||||||
|
result = runParser({ "-b", "stopping", "-c" }, [&](auto& parser) {
|
||||||
|
parser.setStopParsingOnFirstNonOption(false);
|
||||||
|
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, true);
|
||||||
|
|
||||||
|
// Stop on first non option, arguments are in correct order
|
||||||
|
// Expected: The bool options are set and one non-option parameter
|
||||||
|
boolOpt1 = false;
|
||||||
|
boolOpt2 = false;
|
||||||
|
result = runParser({ "-b", "-c", "stopping" }, [&](auto& parser) {
|
||||||
|
parser.setStopParsingOnFirstNonOption(true);
|
||||||
|
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, true);
|
||||||
|
|
||||||
|
// Stop on first non option, arguments are in wrong order
|
||||||
|
// Expected: boolOpt1 is set and the rest are non-option parameters
|
||||||
|
boolOpt1 = false;
|
||||||
|
boolOpt2 = false;
|
||||||
|
result = runParser({ "-b", "stopping", "-c" }, [&](auto& parser) {
|
||||||
|
parser.setStopParsingOnFirstNonOption(true);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user