Refactor value completion in ArgumentParser::printBashCompletion()
This commit is contained in:
parent
872ee49979
commit
0e8dcbecae
|
@ -1149,7 +1149,7 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
|
||||||
// read the "opening" (started but not finished argument denotation)
|
// read the "opening" (started but not finished argument denotation)
|
||||||
const char *opening = nullptr;
|
const char *opening = nullptr;
|
||||||
string compoundOpening;
|
string compoundOpening;
|
||||||
size_t openingLen, compoundOpeningStartLen = 0;
|
size_t openingLen = 0, compoundOpeningStartLen = 0;
|
||||||
unsigned char openingDenotationType = Value;
|
unsigned char openingDenotationType = Value;
|
||||||
if (argc && completionInfo.nextArgumentOrValue) {
|
if (argc && completionInfo.nextArgumentOrValue) {
|
||||||
if (currentWordIndex < static_cast<unsigned int>(argc)) {
|
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
|
// 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
|
// 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.
|
// 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, "=")) {
|
if (currentWordIndex > minCurrentWordIndex && !strcmp(opening, "=")) {
|
||||||
compoundOpening.reserve(compoundOpeningStartLen = strlen(argv[--currentWordIndex]) + 1);
|
compoundOpening.reserve(compoundOpeningStartLen = strlen(argv[--currentWordIndex]) + 1);
|
||||||
compoundOpening = argv[currentWordIndex];
|
compoundOpening = argv[currentWordIndex];
|
||||||
|
@ -1184,98 +1184,100 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
|
||||||
cout << "COMPREPLY=(";
|
cout << "COMPREPLY=(";
|
||||||
// -> completions for parameter values
|
// -> completions for parameter values
|
||||||
bool noWhitespace = false;
|
bool noWhitespace = false;
|
||||||
for (const Argument *arg : completionInfo.relevantPreDefinedValues) {
|
for (const Argument *const arg : completionInfo.relevantPreDefinedValues) {
|
||||||
if (arg->valueCompletionBehaviour() & ValueCompletionBehavior::InvokeCallback && arg->m_callbackFunction) {
|
if (arg->valueCompletionBehaviour() & ValueCompletionBehavior::InvokeCallback && arg->m_callbackFunction) {
|
||||||
arg->m_callbackFunction(arg->isPresent() ? arg->m_occurrences.front() : ArgumentOccurrence(Argument::varValueCount));
|
arg->m_callbackFunction(arg->isPresent() ? arg->m_occurrences.front() : ArgumentOccurrence(Argument::varValueCount));
|
||||||
}
|
}
|
||||||
if (arg->preDefinedCompletionValues()) {
|
if (!arg->preDefinedCompletionValues()) {
|
||||||
bool appendEquationSign = arg->valueCompletionBehaviour() & ValueCompletionBehavior::AppendEquationSign;
|
continue;
|
||||||
if (argc && currentWordIndex <= completionInfo.lastSpecifiedArgIndex && opening) {
|
}
|
||||||
if (openingDenotationType == Value) {
|
const bool appendEquationSign = arg->valueCompletionBehaviour() & ValueCompletionBehavior::AppendEquationSign;
|
||||||
bool wordStart = true, ok = false, equationSignAlreadyPresent = false;
|
if (argc && currentWordIndex <= completionInfo.lastSpecifiedArgIndex && opening) {
|
||||||
size_t wordIndex = 0;
|
if (openingDenotationType != Value) {
|
||||||
for (const char *i = arg->preDefinedCompletionValues(), *end = opening + openingLen; *i;) {
|
continue;
|
||||||
if (wordStart) {
|
}
|
||||||
const char *i1 = i, *i2 = opening;
|
bool wordStart = true, ok = false, equationSignAlreadyPresent = false;
|
||||||
for (; *i1 && i2 != end && *i1 == *i2; ++i1, ++i2)
|
size_t wordIndex = 0;
|
||||||
;
|
for (const char *i = arg->preDefinedCompletionValues(), *end = opening + openingLen; *i;) {
|
||||||
if ((ok = (i2 == end))) {
|
if (wordStart) {
|
||||||
cout << '\'';
|
const char *i1 = i, *i2 = opening;
|
||||||
}
|
for (; *i1 && i2 != end && *i1 == *i2; ++i1, ++i2)
|
||||||
wordStart = false;
|
;
|
||||||
wordIndex = 0;
|
if ((ok = (i2 == end))) {
|
||||||
} else if ((wordStart = (*i == ' ') || (*i == '\n'))) {
|
cout << '\'';
|
||||||
equationSignAlreadyPresent = false;
|
|
||||||
if (ok) {
|
|
||||||
cout << '\'' << ' ';
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
continue;
|
|
||||||
} else if (*i == '=') {
|
|
||||||
equationSignAlreadyPresent = true;
|
|
||||||
}
|
|
||||||
if (ok) {
|
|
||||||
if (!compoundOpeningStartLen || wordIndex >= compoundOpeningStartLen) {
|
|
||||||
if (*i == '\'') {
|
|
||||||
cout << "'\"'\"'";
|
|
||||||
} else {
|
|
||||||
cout << *i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++i, ++wordIndex;
|
|
||||||
switch (*i) {
|
|
||||||
case ' ':
|
|
||||||
case '\n':
|
|
||||||
case '\0':
|
|
||||||
if (appendEquationSign && !equationSignAlreadyPresent) {
|
|
||||||
cout << '=';
|
|
||||||
noWhitespace = true;
|
|
||||||
equationSignAlreadyPresent = false;
|
|
||||||
}
|
|
||||||
if (*i == '\0') {
|
|
||||||
cout << '\'';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cout << ' ';
|
wordStart = false;
|
||||||
|
wordIndex = 0;
|
||||||
|
} else if ((wordStart = (*i == ' ') || (*i == '\n'))) {
|
||||||
|
equationSignAlreadyPresent = false;
|
||||||
|
if (ok) {
|
||||||
|
cout << '\'' << ' ';
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
} else if (*i == '=') {
|
||||||
|
equationSignAlreadyPresent = true;
|
||||||
}
|
}
|
||||||
} else if (const char *i = arg->preDefinedCompletionValues()) {
|
if (!ok) {
|
||||||
bool equationSignAlreadyPresent = false;
|
++i;
|
||||||
cout << '\'';
|
continue;
|
||||||
while (*i) {
|
}
|
||||||
|
if (!compoundOpeningStartLen || wordIndex >= compoundOpeningStartLen) {
|
||||||
if (*i == '\'') {
|
if (*i == '\'') {
|
||||||
cout << "'\"'\"'";
|
cout << "'\"'\"'";
|
||||||
} else {
|
} else {
|
||||||
cout << *i;
|
cout << *i;
|
||||||
}
|
}
|
||||||
switch (*(++i)) {
|
}
|
||||||
case '=':
|
++i, ++wordIndex;
|
||||||
equationSignAlreadyPresent = true;
|
switch (*i) {
|
||||||
break;
|
case ' ':
|
||||||
case ' ':
|
case '\n':
|
||||||
case '\n':
|
case '\0':
|
||||||
case '\0':
|
if (appendEquationSign && !equationSignAlreadyPresent) {
|
||||||
if (appendEquationSign && !equationSignAlreadyPresent) {
|
cout << '=';
|
||||||
cout << '=';
|
noWhitespace = true;
|
||||||
equationSignAlreadyPresent = false;
|
equationSignAlreadyPresent = false;
|
||||||
}
|
}
|
||||||
if (*i != '\0') {
|
if (*i == '\0') {
|
||||||
cout << '\'';
|
cout << '\'';
|
||||||
if (*(++i)) {
|
}
|
||||||
cout << ' ' << '\'';
|
}
|
||||||
}
|
}
|
||||||
|
cout << ' ';
|
||||||
|
} else if (const char *i = arg->preDefinedCompletionValues()) {
|
||||||
|
bool equationSignAlreadyPresent = false;
|
||||||
|
cout << '\'';
|
||||||
|
while (*i) {
|
||||||
|
if (*i == '\'') {
|
||||||
|
cout << "'\"'\"'";
|
||||||
|
} else {
|
||||||
|
cout << *i;
|
||||||
|
}
|
||||||
|
switch (*(++i)) {
|
||||||
|
case '=':
|
||||||
|
equationSignAlreadyPresent = true;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
case '\n':
|
||||||
|
case '\0':
|
||||||
|
if (appendEquationSign && !equationSignAlreadyPresent) {
|
||||||
|
cout << '=';
|
||||||
|
equationSignAlreadyPresent = false;
|
||||||
|
}
|
||||||
|
if (*i != '\0') {
|
||||||
|
cout << '\'';
|
||||||
|
if (*(++i)) {
|
||||||
|
cout << ' ' << '\'';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cout << '\'' << ' ';
|
|
||||||
}
|
}
|
||||||
|
cout << '\'' << ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// -> completions for further arguments
|
// -> completions for further arguments
|
||||||
for (const Argument *arg : completionInfo.relevantArgs) {
|
for (const Argument *const arg : completionInfo.relevantArgs) {
|
||||||
if (argc && currentWordIndex <= completionInfo.lastSpecifiedArgIndex && opening) {
|
if (argc && currentWordIndex <= completionInfo.lastSpecifiedArgIndex && opening) {
|
||||||
switch (openingDenotationType) {
|
switch (openingDenotationType) {
|
||||||
case Value:
|
case Value:
|
||||||
|
@ -1360,15 +1362,16 @@ void ArgumentParser::printBashCompletion(int argc, const char *const *argv, unsi
|
||||||
list<string> entries = directoryEntries(actualDir.c_str(), entryTypes);
|
list<string> entries = directoryEntries(actualDir.c_str(), entryTypes);
|
||||||
findAndReplace(actualDir, replace, with);
|
findAndReplace(actualDir, replace, with);
|
||||||
for (string &dirEntry : entries) {
|
for (string &dirEntry : entries) {
|
||||||
if (startsWith(dirEntry, actualFile)) {
|
if (!startsWith(dirEntry, actualFile)) {
|
||||||
cout << '\'';
|
continue;
|
||||||
if (actualDir != ".") {
|
|
||||||
cout << actualDir;
|
|
||||||
}
|
|
||||||
findAndReplace(dirEntry, replace, with);
|
|
||||||
cout << dirEntry << '\'' << ' ';
|
|
||||||
haveFileOrDirCompletions = true;
|
|
||||||
}
|
}
|
||||||
|
cout << '\'';
|
||||||
|
if (actualDir != ".") {
|
||||||
|
cout << actualDir;
|
||||||
|
}
|
||||||
|
findAndReplace(dirEntry, replace, with);
|
||||||
|
cout << dirEntry << '\'' << ' ';
|
||||||
|
haveFileOrDirCompletions = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (string &dirEntry : directoryEntries(".", entryTypes)) {
|
for (string &dirEntry : directoryEntries(".", entryTypes)) {
|
||||||
|
|
Loading…
Reference in New Issue