work save
This commit is contained in:
parent
6020323818
commit
f3cc986c4e
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 ¤tStatement() 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;
|
||||
|
|
Loading…
Reference in New Issue