work save

This commit is contained in:
royqh1979@gmail.com 2021-08-26 11:58:29 +08:00
parent f3cc986c4e
commit bf4d12b89f
4 changed files with 302 additions and 156 deletions

View File

@ -1381,133 +1381,179 @@ void Editor::showHeaderCompletion(bool autoComplete)
//todo: //todo:
} }
bool Editor::testInFunc(int x, int y)
{
bool result = false;
QString s = lines()->getString(y);
int posY = y;
int posX = std::min(x,s.length()-1); // x is started from 1
int bracketLevel=0;
while (true) {
while (posX < 0) {
posY--;
if (posY < 0)
return false;
s = lines()->getString(posY);
posX = s.length()-1;
}
if (s[posX] == '>'
|| s[posX] == ']') {
bracketLevel++;
} else if (s[posX] == '<'
|| s[posX] == '[') {
bracketLevel--;
} else if (bracketLevel==0) {
switch (s[posX].unicode()) {
case '(':
return true;
case ';':
case '{':
return false;
}
if (!(isIdentChar(s[posX])
|| s[posX] == ' '
|| s[posX] == '\t'
|| s[posX] == '*'
|| s[posX] == '&'))
break;;
}
posX--;
}
return result;
}
QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord &pWordEnd, WordPurpose purpose) QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord &pWordEnd, WordPurpose purpose)
{ {
QString result = ""; QString result = "";
QString s; QString s;
if ((p.Line >= 1) && (p.Line <= lines()->count())) { if ((p.Line<1) || (p.Line>lines()->count())) {
s = lines()->getString(p.Line - 1); pWordBegin = p;
int len = s.length(); pWordEnd = p;
return "";
}
int wordBegin = p.Char - 1 - 1; //BufferCoord::Char starts with 1 s = lines()->getString(p.Line - 1);
int wordEnd = p.Char - 1 - 1; int len = s.length();
// Copy forward until end of word int wordBegin = p.Char - 1 - 1; //BufferCoord::Char starts with 1
if (purpose == WordPurpose::wpEvaluation int wordEnd = p.Char - 1 - 1;
|| purpose == WordPurpose::wpInformation) {
while (wordEnd + 1 < len) do { // Copy forward until end of word
if ((purpose == WordPurpose::wpEvaluation) if (purpose == WordPurpose::wpEvaluation
&& (s[wordEnd + 1] == '[')) { || purpose == WordPurpose::wpInformation) {
if (!findComplement(s, '[', ']', wordEnd, 1)) while (wordEnd + 1 < len) {
break; if ((purpose == WordPurpose::wpEvaluation)
} else if (isIdentChar(s[wordEnd + 1])) { && (s[wordEnd + 1] == '[')) {
wordEnd++; if (!findComplement(s, '[', ']', wordEnd, 1))
} else
break; break;
} } else if (isIdentChar(s[wordEnd + 1])) {
wordEnd++;
} else
break;
} }
}
// Copy backward until # // Copy backward until #
if (purpose == WordPurpose::wpDirective) { if (purpose == WordPurpose::wpDirective) {
while ((wordBegin >= 0) && (wordBegin < len)) { while ((wordBegin >= 0) && (wordBegin < len)) {
if (isIdentChar(s[wordBegin])) if (isIdentChar(s[wordBegin]))
wordBegin--; wordBegin--;
else if (s[wordBegin] == '#') { else if (s[wordBegin] == '#') {
wordBegin--; wordBegin--;
break; break;
} else } else
break; break;
}
} }
}
// Copy backward until @ // Copy backward until @
if (purpose == WordPurpose::wpJavadoc) { if (purpose == WordPurpose::wpJavadoc) {
while ((wordBegin >= 0) && (wordBegin < len)) { while ((wordBegin >= 0) && (wordBegin < len)) {
if (isIdentChar(s[wordBegin])) if (isIdentChar(s[wordBegin]))
wordBegin--; wordBegin--;
else if (s[wordBegin] == '@') { else if (s[wordBegin] == '@') {
wordBegin--; wordBegin--;
break; break;
} else } else
break; break;
}
} }
}
// Copy backward until begin of path // Copy backward until begin of path
if (purpose == wpHeaderCompletion) { if (purpose == WordPurpose::wpHeaderCompletion) {
while ((wordBegin >= 0) && (wordBegin < len)) { while ((wordBegin >= 0) && (wordBegin < len)) {
if (isIdentChar(s[wordBegin])) if (isIdentChar(s[wordBegin]))
wordBegin--; wordBegin--;
else if (s[wordBegin] == '/' else if (s[wordBegin] == '/'
|| s[wordBegin] == '\\'
|| s[wordBegin] == '.') {
wordBegin--;
break;
} else
break;
}
}
if (purpose == WordPurpose::wpHeaderCompletionStart) {
while ((wordBegin >= 0) && (wordBegin < len)) {
if (s[wordBegin] == '"'
|| s[wordBegin] == '<') {
wordBegin--;
break;
} else if (s[wordBegin] == '/'
|| s[wordBegin] == '\\' || s[wordBegin] == '\\'
|| s[wordBegin] == '.') { || s[wordBegin] == '.') {
wordBegin--; wordBegin--;
break; } else if (isIdentChar(s[wordBegin]))
} else wordBegin--;
break; else
} break;
} }
}
if (purpose == WordPurpose::wpHeaderCompletionStart) { // && ( wordBegin < len)
while ((wordBegin >= 0) && (wordBegin < len)) { // Copy backward until begin of word
if (s[wordBegin] == '"' if (purpose == WordPurpose::wpCompletion
|| s[wordBegin] == '<']) { || purpose == WordPurpose::wpEvaluation
wordBegin--; || purpose == WordPurpose::wpInformation) {
while ((wordBegin >= 0) && (wordBegin<len)) {
if (s[wordBegin] == ']') {
if (!findComplement(s, ']', '[', wordBegin, -1))
break; break;
} else if (s[wordBegin] == '/'
|| s[wordBegin] == '\\'
|| s[wordBegin] == '.') {
wordBegin--;
} else if (isIdentChar(s[wordBegin]))
wordBegin--;
else else
wordBegin++; // step over mathing [
} else if (isIdentChar(s[wordBegin])) {
wordBegin--;
} else if (s[wordBegin] == '.'
|| s[wordBegin] == ':'
|| s[wordBegin] == '~') { // allow destructor signs
wordBegin--;
} else if (
(s[wordBegin] == '>')
&& (wordBegin+2<len)
&& (s[wordBegin+1]==':')
&& (s[wordBegin+2]==':')
) { // allow template
if (!findComplement(s, '>', '<', wordBegin, -1))
break; break;
} else
} wordBegin--; // step over >
} else if ((wordBegin-1 >= 0)
// Copy backward until begin of word && (s[wordBegin - 1] == '-')
if (purpose == WordPurpose::wpCompletion && (s[wordBegin] == '>')) {
|| purpose == WordPurpose::wpEvaluation wordBegin-=2;
|| purpose == WordPurpose::wpInformation) { } else if ((wordBegin-1 >= 0)
while ((wordBegin >= 0) && (wordBegin < len)) { && (s[wordBegin - 1] == ':')
if (s[wordBegin] == ']') then { && (s[wordBegin] == ':')) {
if (!findComplement(s, ']', '[', wordBegin, -1)) wordBegin-=2;
break } else if ((wordBegin > 0)
else && (s[wordBegin] == ')')) {
wordBegin++; // step over [ if (!findComplement(s, ')', '(', wordBegin, -1))
} else if (isIdentChar(s[wordBegin])) {
wordBegin--;
} else if (s[wordBegin] == '.'
|| s[wordBegin] == ':'
|| s[wordBegin] == '~') { // allow destructor signs
wordBegin--;
} else if (
(s[wordBegin] == '>')
&& (wordBegin+2<len)
&& (s[WordBegin+1]==':')
&& (s[WordBegin+2]==':')
) { // allow template
if (!findComplement(s, '>', '<', wordBegin, -1))
break;
else
wordBegin--; // step over >
} else if ((wordBegin-1 >= 0)
&& (s[wordBegin - 1] == '-')
&& (s[wordBegin] == '>')) {
wordBegin-=2;
} else if ((wordBegin-1 >= 0)
&& (s[wordBegin - 1] == ':')
&& (s[wordBegin] == ':')) {
wordBegin-=2;
} else if ((wordBegin > 0)
&& (s[wordBegin] == ')')) {
if (!findComplement(s, ')', '(', WordBegin, -1))
break;
else
wordBegin--; // step over (
} else
break; break;
} else
wordBegin--; // step over mathing (
} else
break;
} }
} }
@ -1517,62 +1563,134 @@ QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin,
pWordBegin.Char = wordBegin+1; pWordBegin.Char = wordBegin+1;
pWordEnd.Line = p.Line; pWordEnd.Line = p.Line;
pWordEnd.Char = wordEnd; pWordEnd.Char = wordEnd;
if (!result.isEmpty() && (
result[0] in ['.','-']) // last line still have part of word
and (Purpose in [wpCompletion, wpEvaluation, wpInformation]) then begin if (!result.isEmpty()
i:=WordBegin; && (
line:=p.Line; result[0] == '.'
while line>=1 do begin || result[0] == '-')
while i>=1 do begin && (purpose == WordPurpose::wpCompletion
if S[i] in [' ',#9] then || purpose == WordPurpose::wpEvaluation
dec(i) || purpose == WordPurpose::wpInformation)) {
else int i = wordBegin;
break; int line=p.Line;
end; while (line>=1) {
if i<1 then begin while (i>=0) {
dec(line); if (s[i] == ' '
if (line>=1) then begin || s[i] == '\t')
S:=editor.Lines[line-1]; i--;
i:=Length(s); else
continue; break;
end else }
break; if (i<0) {
end else begin line--;
HighlightPos.Line := line; if (line>=1) {
HighlightPos.Char := i+1; s=lines()->getString(line-1);
Result := GetWordAtPosition(editor,highlightPos,pWordBegin,pDummy,Purpose)+Result; i=s.length();
break; continue;
end; } else
end; break;
end; } else {
BufferCoord highlightPos;
BufferCoord pDummy;
highlightPos.Line = line;
highlightPos.Char = i+1;
result = getWordAtPosition(highlightPos,pWordBegin,pDummy,purpose)+result;
break;
}
}
}
// Strip function parameters // Strip function parameters
while true do begin int paramBegin,paramEnd;
ParamBegin := Pos('(', Result); while (true) {
if ParamBegin > 0 then begin paramBegin = result.indexOf('(');
ParamEnd := ParamBegin; if (paramBegin > 0) {
if (ParamBegin=1) and FindComplement(Result, '(', ')', ParamEnd, 1) paramEnd = paramBegin;
and (ParamEnd = Length(Result)) then begin if ((paramBegin==0)
Delete(Result,ParamEnd,1); && findComplement(result, '(', ')', paramEnd, 1)
Delete(Result,ParamBegin,1); && (paramEnd = result.length()-1) ) {
continue; //remove the enclosing parenthese pair
end else begin result = result.mid(1,result.length()-2);
ParamEnd := ParamBegin; continue;
if FindComplement(Result, '(', ')', ParamEnd, 1) then begin } else {
Delete(Result, ParamBegin, ParamEnd - ParamBegin + 1); paramEnd = paramBegin;
end else if (findComplement(result, '(', ')', paramEnd, 1)) {
result.remove(paramBegin, paramEnd - paramBegin + 1);
} else
break;
}
} else
break; break;
end; }
end else
break;
end;
ParamBegin := 1; paramBegin = 0;
while (ParamBegin <= Length(Result)) and (Result[ParamBegin] = '*') do begin while ((paramBegin < result.length()) && (result[paramBegin] == '*')) {
inc(ParamBegin); paramBegin++;
end; }
Delete(Result,1,ParamBegin-1); result.remove(0,paramBegin);
return result;
}
QString Editor::getPreviousWordAtPositionForSuggestion(const BufferCoord &p)
{
QString result;
if ((p.Line<1) || (p.Line>lines()->count())) {
return "";
}
bool inFunc = testInFunc(p.Char-1,p.Line-1);
QString s = lines()->getString(p.Line - 1);
int wordBegin;
int wordEnd = p.Char-1;
if (wordEnd >= s.length())
wordEnd = s.length()-1;
while (true) {
int bracketLevel=0;
bool skipNextWord=false;
while (wordEnd > 0) {
if (s[wordEnd] == '>'
|| s[wordEnd] == ']') {
bracketLevel++;
} else if (s[wordEnd] == '<'
|| s[wordEnd] == '[') {
bracketLevel--;
} else if (bracketLevel==0) {
//we can't differentiate multiple definition and function parameter define here , so we don't handle ','
if (s[wordEnd] == ',') {
if (inFunc) // in func, dont skip ','
break;
else
skipNextWord=true;
} else if (s[wordEnd] != ' '
&& s[wordEnd] != '\t') {
break;
}
}
wordEnd--;
}
if (wordEnd<0)
return "";
if (bracketLevel > 0)
return "";
if (!isIdentChar(s[wordEnd]))
return "";
wordBegin = wordEnd;
while ((wordBegin >= 0) && isIdentChar(s[wordBegin])) {
wordBegin--;
}
wordBegin++;
if (s[wordBegin]>='0' && s[wordBegin]<='9') // not valid word
return "";
result = s.mid(wordBegin, wordEnd - wordBegin+1);
if ((result != "const") && !skipNextWord)
break;
wordEnd = wordBegin-1;
}
return result;
} }
const PCppParser &Editor::parser() const const PCppParser &Editor::parser() const

View File

@ -129,6 +129,7 @@ public:
BufferCoord& pWordBegin, BufferCoord& pWordBegin,
BufferCoord& pWordEnd, BufferCoord& pWordEnd,
WordPurpose purpose); WordPurpose purpose);
QString getPreviousWordAtPositionForSuggestion(const BufferCoord& p);
const PCppParser &parser() const; const PCppParser &parser() const;
@ -164,6 +165,8 @@ private:
void showCompletion(bool autoComplete); void showCompletion(bool autoComplete);
void showHeaderCompletion(bool autoComplete); void showHeaderCompletion(bool autoComplete);
bool testInFunc(int x,int y);
private: private:
static int newfileCount; static int newfileCount;
QByteArray mEncodingOption; // the encoding type set by the user QByteArray mEncodingOption; // the encoding type set by the user

View File

@ -541,3 +541,22 @@ void resetCppParser(std::shared_ptr<CppParser> parser)
} }
parser->parseHardDefines(); parser->parseHardDefines();
} }
bool findComplement(const QString &s, const QChar &fromToken, const QChar &toToken, int &curPos, int increment)
{
int curPosBackup = curPos;
int level = 0;
//todo: skip comment, char and strings
while ((curPos < s.length()) && (curPos >= 0)) {
if (s[curPos] == fromToken) {
level++;
} else if (s[curPos] == toToken) {
level--;
if (level == 0)
return true;
}
curPos += increment;
}
curPos = curPosBackup;
return false;
}

View File

@ -105,6 +105,12 @@ int compareFileModifiedTime(const QString& filename1, const QString& filename2);
void changeTheme(const QString& themeName); void changeTheme(const QString& themeName);
bool findComplement(const QString& s,
const QChar& fromToken,
const QChar& toToken,
int& curPos,
int increment);
class CppParser; class CppParser;
void resetCppParser(std::shared_ptr<CppParser> parser); void resetCppParser(std::shared_ptr<CppParser> parser);