Add greedy-flag for argument parser
This is useful if one needs to pass subsequent arguments as-is to another nested argument parser.
This commit is contained in:
parent
08194f5d32
commit
3c769fa242
|
@ -206,7 +206,8 @@ bool ArgumentReader::read(ArgumentVector &args)
|
|||
// iterate through all argument denotations; loop might exit earlier when an denotation is unknown
|
||||
while (argv != end) {
|
||||
// check whether there are still values to read
|
||||
if (values && lastArgInLevel->requiredValueCount() != Argument::varValueCount && values->size() < lastArgInLevel->requiredValueCount()) {
|
||||
if (values && ((lastArgInLevel->requiredValueCount() != Argument::varValueCount) || (lastArgInLevel->flags() & Argument::Flags::Greedy))
|
||||
&& values->size() < lastArgInLevel->requiredValueCount()) {
|
||||
// read arg as value and continue with next arg
|
||||
values->emplace_back(argDenotation ? argDenotation : *argv);
|
||||
++index;
|
||||
|
@ -1092,7 +1093,7 @@ void ArgumentParser::verifyArgs(const ArgumentVector &args)
|
|||
assert(!arg->abbreviation() || find(abbreviations.cbegin(), abbreviations.cend(), arg->abbreviation()) == abbreviations.cend());
|
||||
abbreviations.push_back(arg->abbreviation());
|
||||
assert(!arg->name() || find_if(names.cbegin(), names.cend(), [arg](const char *name) { return !strcmp(arg->name(), name); }) == names.cend());
|
||||
assert(arg->requiredValueCount() == 0 || arg->subArguments().size() == 0);
|
||||
assert(arg->requiredValueCount() == 0 || arg->subArguments().size() == 0 || (arg->flags() & Argument::Flags::Greedy));
|
||||
names.emplace_back(arg->name());
|
||||
}
|
||||
for (const Argument *arg : args) {
|
||||
|
|
|
@ -273,6 +273,7 @@ public:
|
|||
Implicit = 0x2,
|
||||
Operation = 0x4,
|
||||
Deprecated = 0x8,
|
||||
Greedy = 0x10,
|
||||
};
|
||||
|
||||
Argument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
|
||||
|
|
|
@ -452,6 +452,27 @@ void ArgumentParserTests::testParsing()
|
|||
CPPUNIT_ASSERT(fieldsArg.isPresent());
|
||||
CPPUNIT_ASSERT_EQUAL("fields"sv, std::string_view(fieldsArg.values().at(0)));
|
||||
CPPUNIT_ASSERT_EQUAL("album=test"sv, std::string_view(fieldsArg.values().at(1)));
|
||||
|
||||
// greedy-flag
|
||||
const char *argv19[] = { "tageditor", "get", "--fields", "foo", "bar", "--help" };
|
||||
parser.resetArgs();
|
||||
try {
|
||||
parser.parseArgs(6, argv19, ParseArgumentBehavior::CheckConstraints | ParseArgumentBehavior::InvokeCallbacks);
|
||||
CPPUNIT_FAIL("Exception expected.");
|
||||
} catch (const ParseError &e) {
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("--help assumed to be an argument without greedy-flag (leading to error)",
|
||||
"The argument \"help\" can not be combined with \"get\"."sv, std::string_view(e.what()));
|
||||
}
|
||||
parser.resetArgs();
|
||||
fieldsArg.setFlags(Argument::Flags::Greedy, true);
|
||||
parser.parseArgs(6, argv19, ParseArgumentBehavior::CheckConstraints | ParseArgumentBehavior::InvokeCallbacks);
|
||||
CPPUNIT_ASSERT(displayTagInfoArg.isPresent());
|
||||
CPPUNIT_ASSERT(fieldsArg.isPresent());
|
||||
CPPUNIT_ASSERT_MESSAGE("--help not considered an argument with greedy-flag", !parser.helpArg().isPresent());
|
||||
CPPUNIT_ASSERT_EQUAL("foo"sv, std::string_view(fieldsArg.values().at(0)));
|
||||
CPPUNIT_ASSERT_EQUAL("bar"sv, std::string_view(fieldsArg.values().at(1)));
|
||||
CPPUNIT_ASSERT_EQUAL("--help"sv, std::string_view(fieldsArg.values().at(2)));
|
||||
CPPUNIT_ASSERT_THROW(fieldsArg.values().at(3), std::out_of_range);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
Loading…
Reference in New Issue