Refactor value completion in ArgumentParser::printBashCompletion()

This commit is contained in:
Martchus 2018-05-06 00:33:33 +02:00
parent 872ee49979
commit 0e8dcbecae
1 changed files with 88 additions and 85 deletions

View File

@ -1149,7 +1149,7 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
// read the "opening" (started but not finished argument denotation)
const char *opening = nullptr;
string compoundOpening;
size_t openingLen, compoundOpeningStartLen = 0;
size_t openingLen = 0, compoundOpeningStartLen = 0;
unsigned char openingDenotationType = Value;
if (argc && completionInfo.nextArgumentOrValue) {
if (currentWordIndex < static_cast<unsigned int>(argc)) {
@ -1159,7 +1159,7 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
// This is not how values are treated by the argument parser. Hence the opening
// must be joined again. In this case only the part after the equation sign needs to be
// provided for completion so compoundOpeningStartLen is set to number of characters to skip.
size_t minCurrentWordIndex = (completionInfo.lastDetectedArg ? completionInfo.lastDetectedArgIndex : 0);
const size_t minCurrentWordIndex = (completionInfo.lastDetectedArg ? completionInfo.lastDetectedArgIndex : 0);
if (currentWordIndex > minCurrentWordIndex && !strcmp(opening, "=")) {
compoundOpening.reserve(compoundOpeningStartLen = strlen(argv[--currentWordIndex]) + 1);
compoundOpening = argv[currentWordIndex];
@ -1184,14 +1184,18 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
cout << "COMPREPLY=(";
// -> completions for parameter values
bool noWhitespace = false;
for (const Argument *arg : completionInfo.relevantPreDefinedValues) {
for (const Argument *const arg : completionInfo.relevantPreDefinedValues) {
if (arg->valueCompletionBehaviour() & ValueCompletionBehavior::InvokeCallback && arg->m_callbackFunction) {
arg->m_callbackFunction(arg->isPresent() ? arg->m_occurrences.front() : ArgumentOccurrence(Argument::varValueCount));
}
if (arg->preDefinedCompletionValues()) {
bool appendEquationSign = arg->valueCompletionBehaviour() & ValueCompletionBehavior::AppendEquationSign;
if (!arg->preDefinedCompletionValues()) {
continue;
}
const bool appendEquationSign = arg->valueCompletionBehaviour() & ValueCompletionBehavior::AppendEquationSign;
if (argc && currentWordIndex <= completionInfo.lastSpecifiedArgIndex && opening) {
if (openingDenotationType == Value) {
if (openingDenotationType != Value) {
continue;
}
bool wordStart = true, ok = false, equationSignAlreadyPresent = false;
size_t wordIndex = 0;
for (const char *i = arg->preDefinedCompletionValues(), *end = opening + openingLen; *i;) {
@ -1214,7 +1218,10 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
} else if (*i == '=') {
equationSignAlreadyPresent = true;
}
if (ok) {
if (!ok) {
++i;
continue;
}
if (!compoundOpeningStartLen || wordIndex >= compoundOpeningStartLen) {
if (*i == '\'') {
cout << "'\"'\"'";
@ -1236,12 +1243,8 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
cout << '\'';
}
}
} else {
++i;
}
}
cout << ' ';
}
} else if (const char *i = arg->preDefinedCompletionValues()) {
bool equationSignAlreadyPresent = false;
cout << '\'';
@ -1273,9 +1276,8 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
cout << '\'' << ' ';
}
}
}
// -> completions for further arguments
for (const Argument *arg : completionInfo.relevantArgs) {
for (const Argument *const arg : completionInfo.relevantArgs) {
if (argc && currentWordIndex <= completionInfo.lastSpecifiedArgIndex && opening) {
switch (openingDenotationType) {
case Value:
@ -1360,7 +1362,9 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
list<string> entries = directoryEntries(actualDir.c_str(), entryTypes);
findAndReplace(actualDir, replace, with);
for (string &dirEntry : entries) {
if (startsWith(dirEntry, actualFile)) {
if (!startsWith(dirEntry, actualFile)) {
continue;
}
cout << '\'';
if (actualDir != ".") {
cout << actualDir;
@ -1369,7 +1373,6 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
cout << dirEntry << '\'' << ' ';
haveFileOrDirCompletions = true;
}
}
} else {
for (string &dirEntry : directoryEntries(".", entryTypes)) {
findAndReplace(dirEntry, replace, with);