Browse Source

Util+Test: Add setting to stop parsing on first non-option

master
Riyyi 3 years ago
parent
commit
f92b75a463
  1. 10
      src/util/argparser.cpp
  2. 13
      src/util/argparser.h
  3. 59
      test/testutilargparser.cpp

10
src/util/argparser.cpp

@ -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());
} }
} }

13
src/util/argparser.h

@ -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;

59
test/testutilargparser.cpp

@ -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);
}

Loading…
Cancel
Save