work save

This commit is contained in:
royqh1979@gmail.com 2021-08-25 23:53:35 +08:00
parent 6020323818
commit f3cc986c4e
4 changed files with 388 additions and 45 deletions

View File

@ -1315,57 +1315,264 @@ void Editor::showCompletion(bool autoComplete)
BufferCoord{caretX() - 1,
caretY()}, s, tokenFinished,tokenType, attr)) {
if (tokenType == SynHighlighterTokenType::PreprocessDirective) {//Preprocessor
word = getWordAtPosition(this, caretXY(),pBeginPos,pEndPos, wpDirective);
if not StartsStr('#',word) then begin
ShowTabnineCompletion;
Exit;
end;
end else if attr = dmMain.Cpp.CommentAttri then begin //Comment, javadoc tag
word:=GetWordAtPosition(fText, fText.CaretXY,pBeginPos,pEndPos, wpJavadoc);
if not StartsStr('@',word) then begin
Exit;
end;
end else if (attr <> fText.Highlighter.SymbolAttribute) and
(attr <> fText.Highlighter.WhitespaceAttribute) and
(attr <> fText.Highlighter.IdentifierAttribute) then begin
Exit;
end;
word = getWordAtPosition(caretXY(),pBeginPos,pEndPos, WordPurpose::wpDirective);
if (!word.startsWith('#')) {
//showTabnineCompletion();
return;
}
} else if (tokenType == SynHighlighterTokenType::Comment) { //Comment, javadoc tag
word = getWordAtPosition(caretXY(),pBeginPos,pEndPos, WordPurpose::wpJavadoc);
if (!word.startsWith('@')) {
return;
}
} else if (
(tokenType != SynHighlighterTokenType::Symbol) &&
(tokenType != SynHighlighterTokenType::Space) &&
(tokenType != SynHighlighterTokenType::Identifier)
) {
return;
}
}
// Position it at the top of the next line
P := fText.RowColumnToPixels(fText.DisplayXY);
Inc(P.Y, fText.LineHeight + 2);
fCompletionBox.Position := fText.ClientToScreen(P);
QPoint p = RowColumnToPixels(displayXY());
p+=QPoint(0,textHeight()+2);
mCompletionPopup->move(mapToGlobal(p));
fCompletionBox.RecordUsage := devCodeCompletion.RecordUsage;
fCompletionBox.SortByScope := devCodeCompletion.SortByScope;
fCompletionBox.ShowKeywords := devCodeCompletion.ShowKeywords;
fCompletionBox.ShowCodeIns := devCodeCompletion.ShowCodeIns;
fCompletionBox.IgnoreCase := devCodeCompletion.IgnoreCase;
fCompletionBox.CodeInsList := dmMain.CodeInserts.ItemList;
fCompletionBox.SymbolUsage := dmMain.SymbolUsage;
fCompletionBox.ShowCount := devCodeCompletion.MaxCount;
// fCompletionBox.RecordUsage := devCodeCompletion.RecordUsage;
// fCompletionBox.SortByScope := devCodeCompletion.SortByScope;
// fCompletionBox.ShowKeywords := devCodeCompletion.ShowKeywords;
// fCompletionBox.ShowCodeIns := devCodeCompletion.ShowCodeIns;
// fCompletionBox.IgnoreCase := devCodeCompletion.IgnoreCase;
// fCompletionBox.CodeInsList := dmMain.CodeInserts.ItemList;
// fCompletionBox.SymbolUsage := dmMain.SymbolUsage;
// fCompletionBox.ShowCount := devCodeCompletion.MaxCount;
//Set Font size;
fCompletionBox.FontSize := fText.Font.Size;
mCompletionPopup->setFont(font());
// Redirect key presses to completion box if applicable
fCompletionBox.OnKeyPress := CompletionKeyPress;
fCompletionBox.OnKeyDown := CompletionKeyDown;
fCompletionBox.Parser := fParser;
fCompletionBox.useCppKeyword := fUseCppSyntax;
fCompletionBox.Show;
//todo:
mCompletionPopup->setKeypressedCallback([this](QKeyEvent *event)->bool{
return onCompletionKeyPressed(event);
});
mCompletionPopup->setParser(mParser);
//todo:
//mCompletionPopup->setUseCppKeyword(mUseCppSyntax);
mCompletionPopup->show();
// Scan the current function body
fCompletionBox.CurrentStatement := fParser.FindAndScanBlockAt(fFileName, fText.CaretY);
mCompletionPopup->setCurrentStatement(
mParser->findAndScanBlockAt(mFilename, caretY())
);
if word='' then
word:=GetWordAtPosition(fText, fText.CaretXY,pBeginPos,pEndPos, wpCompletion);
if (word.isEmpty())
word=getWordAtPosition(caretXY(),pBeginPos,pEndPos, WordPurpose::wpCompletion);
//if not fCompletionBox.Visible then
fCompletionBox.PrepareSearch(word, fFileName,pBeginPos.Line);
mCompletionPopup->prepareSearch(word, mFilename, pBeginPos.Line);
// Filter the whole statement list
if fCompletionBox.Search(word, fFileName, autoComplete) then //only one suggestion and it's not input while typing
CompletionInsert(); // if only have one suggestion, just use it
if (mCompletionPopup->search(word, autoComplete)) { //only one suggestion and it's not input while typing
completionInsert(); // if only have one suggestion, just use it
}
}
void Editor::showHeaderCompletion(bool autoComplete)
{
//todo:
}
QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord &pWordEnd, WordPurpose purpose)
{
QString result = "";
QString s;
if ((p.Line >= 1) && (p.Line <= lines()->count())) {
s = lines()->getString(p.Line - 1);
int len = s.length();
int wordBegin = p.Char - 1 - 1; //BufferCoord::Char starts with 1
int wordEnd = p.Char - 1 - 1;
// Copy forward until end of word
if (purpose == WordPurpose::wpEvaluation
|| purpose == WordPurpose::wpInformation) {
while (wordEnd + 1 < len) do {
if ((purpose == WordPurpose::wpEvaluation)
&& (s[wordEnd + 1] == '[')) {
if (!findComplement(s, '[', ']', wordEnd, 1))
break;
} else if (isIdentChar(s[wordEnd + 1])) {
wordEnd++;
} else
break;
}
}
// Copy backward until #
if (purpose == WordPurpose::wpDirective) {
while ((wordBegin >= 0) && (wordBegin < len)) {
if (isIdentChar(s[wordBegin]))
wordBegin--;
else if (s[wordBegin] == '#') {
wordBegin--;
break;
} else
break;
}
}
// Copy backward until @
if (purpose == WordPurpose::wpJavadoc) {
while ((wordBegin >= 0) && (wordBegin < len)) {
if (isIdentChar(s[wordBegin]))
wordBegin--;
else if (s[wordBegin] == '@') {
wordBegin--;
break;
} else
break;
}
}
// Copy backward until begin of path
if (purpose == wpHeaderCompletion) {
while ((wordBegin >= 0) && (wordBegin < len)) {
if (isIdentChar(s[wordBegin]))
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] == '.') {
wordBegin--;
} else if (isIdentChar(s[wordBegin]))
wordBegin--;
else
break;
}
}
// Copy backward until begin of word
if (purpose == WordPurpose::wpCompletion
|| purpose == WordPurpose::wpEvaluation
|| purpose == WordPurpose::wpInformation) {
while ((wordBegin >= 0) && (wordBegin < len)) {
if (s[wordBegin] == ']') then {
if (!findComplement(s, ']', '[', wordBegin, -1))
break
else
wordBegin++; // step over [
} 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;
}
}
}
// Get end result
result = s.mid(wordBegin + 1, wordEnd - wordBegin);
pWordBegin.Line = p.Line;
pWordBegin.Char = wordBegin+1;
pWordEnd.Line = p.Line;
pWordEnd.Char = wordEnd;
if (!result.isEmpty() && (
result[0] in ['.','-'])
and (Purpose in [wpCompletion, wpEvaluation, wpInformation]) then begin
i:=WordBegin;
line:=p.Line;
while line>=1 do begin
while i>=1 do begin
if S[i] in [' ',#9] then
dec(i)
else
break;
end;
if i<1 then begin
dec(line);
if (line>=1) then begin
S:=editor.Lines[line-1];
i:=Length(s);
continue;
end else
break;
end else begin
HighlightPos.Line := line;
HighlightPos.Char := i+1;
Result := GetWordAtPosition(editor,highlightPos,pWordBegin,pDummy,Purpose)+Result;
break;
end;
end;
end;
// Strip function parameters
while true do begin
ParamBegin := Pos('(', Result);
if ParamBegin > 0 then begin
ParamEnd := ParamBegin;
if (ParamBegin=1) and FindComplement(Result, '(', ')', ParamEnd, 1)
and (ParamEnd = Length(Result)) then begin
Delete(Result,ParamEnd,1);
Delete(Result,ParamBegin,1);
continue;
end else begin
ParamEnd := ParamBegin;
if FindComplement(Result, '(', ')', ParamEnd, 1) then begin
Delete(Result, ParamBegin, ParamEnd - ParamBegin + 1);
end else
break;
end;
end else
break;
end;
ParamBegin := 1;
while (ParamBegin <= Length(Result)) and (Result[ParamBegin] = '*') do begin
inc(ParamBegin);
end;
Delete(Result,1,ParamBegin-1);
}
const PCppParser &Editor::parser() const

View File

@ -125,6 +125,10 @@ public:
bool hasBreakpoint(int line);
void removeBreakpointFocus();
void setActiveBreakpointFocus(int Line, bool setFocus=true);
QString getWordAtPosition(const BufferCoord& p,
BufferCoord& pWordBegin,
BufferCoord& pWordEnd,
WordPurpose purpose);
const PCppParser &parser() const;
@ -158,6 +162,7 @@ private:
void reparse();
void showCompletion(bool autoComplete);
void showHeaderCompletion(bool autoComplete);
private:
static int newfileCount;
@ -182,6 +187,7 @@ private:
PCppParser mParser;
std::shared_ptr<CodeCompletionView> mCompletionPopup;
int mLastIdCharPressed;
bool mUseCppSyntax;
// QWidget interface
protected:

View File

@ -669,6 +669,106 @@ bool CodeCompletionView::isIncluded(const QString &fileName)
return mIncludedFiles.contains(fileName);
}
const PStatement &CodeCompletionView::currentStatement() const
{
return mCurrentStatement;
}
void CodeCompletionView::setCurrentStatement(const PStatement &newCurrentStatement)
{
mCurrentStatement = newCurrentStatement;
}
bool CodeCompletionView::useCppKeyword() const
{
return mUseCppKeyword;
}
void CodeCompletionView::setUseCppKeyword(bool newUseCppKeyword)
{
mUseCppKeyword = newUseCppKeyword;
}
bool CodeCompletionView::sortByScope() const
{
return mSortByScope;
}
void CodeCompletionView::setSortByScope(bool newSortByScope)
{
mSortByScope = newSortByScope;
}
bool CodeCompletionView::ignoreCase() const
{
return mIgnoreCase;
}
void CodeCompletionView::setIgnoreCase(bool newIgnoreCase)
{
mIgnoreCase = newIgnoreCase;
}
bool CodeCompletionView::showCodeIns() const
{
return mShowCodeIns;
}
void CodeCompletionView::setShowCodeIns(bool newShowCodeIns)
{
mShowCodeIns = newShowCodeIns;
}
bool CodeCompletionView::showKeywords() const
{
return mShowKeywords;
}
void CodeCompletionView::setShowKeywords(bool newShowKeywords)
{
mShowKeywords = newShowKeywords;
}
bool CodeCompletionView::recordUsage() const
{
return mRecordUsage;
}
void CodeCompletionView::setRecordUsage(bool newRecordUsage)
{
mRecordUsage = newRecordUsage;
}
bool CodeCompletionView::onlyGlobals() const
{
return mOnlyGlobals;
}
void CodeCompletionView::setOnlyGlobals(bool newOnlyGlobals)
{
mOnlyGlobals = newOnlyGlobals;
}
int CodeCompletionView::showCount() const
{
return mShowCount;
}
void CodeCompletionView::setShowCount(int newShowCount)
{
mShowCount = newShowCount;
}
const PCppParser &CodeCompletionView::parser() const
{
return mParser;
}
void CodeCompletionView::setParser(const PCppParser &newParser)
{
mParser = newParser;
}
void CodeCompletionView::hideEvent(QHideEvent *event)
{
QMutexLocker locker(&mMutex);
@ -710,7 +810,7 @@ CodeCompletionListModel::CodeCompletionListModel(StatementList *statements, QObj
}
int CodeCompletionListModel::rowCount(const QModelIndex &parent) const
int CodeCompletionListModel::rowCount(const QModelIndex &) const
{
return mStatements->count();
}

View File

@ -47,6 +47,36 @@ public:
bool search(const QString& phrase, bool autoHideOnSingleResult);
const PCppParser &parser() const;
void setParser(const PCppParser &newParser);
int showCount() const;
void setShowCount(int newShowCount);
bool onlyGlobals() const;
void setOnlyGlobals(bool newOnlyGlobals);
bool recordUsage() const;
void setRecordUsage(bool newRecordUsage);
bool showKeywords() const;
void setShowKeywords(bool newShowKeywords);
bool showCodeIns() const;
void setShowCodeIns(bool newShowCodeIns);
bool ignoreCase() const;
void setIgnoreCase(bool newIgnoreCase);
bool sortByScope() const;
void setSortByScope(bool newSortByScope);
bool useCppKeyword() const;
void setUseCppKeyword(bool newUseCppKeyword);
const PStatement &currentStatement() const;
void setCurrentStatement(const PStatement &newCurrentStatement);
private:
void addChildren(PStatement scopeStatement, const QString& fileName,
int line);
@ -59,26 +89,26 @@ private:
CodeCompletionListModel* mModel;
QList<PCodeIns> mCodeInsList; //(Code template list)
//QList<PStatement> mCodeInsStatements; //temporary (user code template) statements created when show code suggestion
PCppParser mParser;
StatementList mFullCompletionStatementList;
StatementList mCompletionStatementList;
int mShowCount;
bool mOnlyGlobals;
PStatement mCurrentStatement;
QSet<QString> mIncludedFiles;
QSet<QString> mUsings;
QSet<QString> mAddedStatements;
QString mPhrase;
QHash<QString,int> mSymbolUsage;
QRecursiveMutex mMutex;
PCppParser mParser;
PStatement mCurrentStatement;
int mShowCount;
bool mOnlyGlobals;
bool mRecordUsage;
bool mShowKeywords;
bool mShowCodeIns;
bool mIgnoreCase;
QRecursiveMutex mMutex;
bool mSortByScope;
bool mUseCppKeyword;
// QWidget interface
protected:
void hideEvent(QHideEvent *event) override;