From f8fae59dcc88071307bbb4b1a86fff0ca28973d5 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Thu, 26 Aug 2021 17:48:23 +0800 Subject: [PATCH] work save --- RedPandaIDE/editor.cpp | 125 +++++++++++++++++++++ RedPandaIDE/editor.h | 4 + RedPandaIDE/parser/cppparser.cpp | 24 ++-- RedPandaIDE/parser/cpppreprocessor.cpp | 66 ++++++----- RedPandaIDE/qsynedit/SynEdit.cpp | 50 +++++++++ RedPandaIDE/qsynedit/SynEdit.h | 12 +- RedPandaIDE/widgets/codecompletionview.cpp | 25 +++++ RedPandaIDE/widgets/codecompletionview.h | 2 + 8 files changed, 262 insertions(+), 46 deletions(-) diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index f6cf2bad..d2adbe62 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -1422,6 +1422,131 @@ bool Editor::testInFunc(int x, int y) return result; } +void Editor::completionInsert(bool appendFunc) +{ + PStatement statement = mCompletionPopup->selectedStatement(); + if (!statement) + return; +// if devCodeCompletion.RecordUsage and (Statement^._Kind <> skUserCodeIn) then begin +// idx:=Utils.FastIndexOf(dmMain.SymbolUsage,Statement^._FullName); +// if idx = -1 then begin +// usageCount:=1; +// dmMain.SymbolUsage.AddObject(Statement^._FullName, pointer(1)) +// end else begin +// usageCount := 1 + integer(dmMain.SymbolUsage.Objects[idx]); +// dmMain.SymbolUsage.Objects[idx] := pointer( usageCount ); +// end; +// Statement^._UsageCount := usageCount; +// end; + + QString funcAddOn = ""; + +// delete the part of the word that's already been typed ... + BufferCoord p = wordEnd(); + setBlockBegin(wordStart()); + setBlockEnd(p); + + // if we are inserting a function, + if (appendFunc) { + if (statement->kind == StatementKind::skFunction + || statement->kind == StatementKind::skConstructor + || statement->kind == StatementKind::skDestructor) { + if ((p.Char >= lineText().length()) // it's the last char on line + || (lineText()[p.Char] != '(')) { // it don't have '(' after it + if (statement->fullName!="std::endl") + funcAddOn = "()"; + } + } + } + + // ... by replacing the selection + if (statement->kind == StatementKind::skUserCodeIn) { // it's a user code template + //insertUserCodeIn(Statement->value); + } else { + if ( + (statement->kind == StatementKind::skKeyword + || statement->kind == StatementKind::skPreprocessor) + && (statement->command.startsWith('#') + || statement->command.startsWith('@')) + ) { + setSelText(statement->command.mid(1)); + } else + setSelText(statement->command + funcAddOn); + + if (!funcAddOn.isEmpty()) + mLastIdCharPressed = 0; + + // Move caret inside the ()'s, only when the user has something to do there... + if (!funcAddOn.isEmpty() + && (statement->args != "()") + && (statement->args != "(void)")) { + setCaretX(caretX() - funcAddOn.length()+1); + + //todo: function hint + // immediately activate function hint +// if devEditor.ShowFunctionTip and Assigned(fText.Highlighter) then begin +// fText.SetFocus; +// fFunctionTip.Parser := fParser; +// fFunctionTip.FileName := fFileName; +// fFunctionTip.Show; +// end; + } + } + mCompletionPopup->hide(); +} + +bool Editor::onCompletionKeyPressed(QKeyEvent *event) +{ + bool processed = false; + if (!mCompletionPopup->isEnabled()) + return false; + QString phrase; + BufferCoord pBeginPos,pEndPos; + switch (event->key()) { + case Qt::Key_Backspace: + ExecuteCommand( + SynEditorCommand::ecDeleteLastChar, + QChar(), nullptr); // Simulate backspace in editor + phrase = getWordAtPosition(caretXY(), + pBeginPos,pEndPos, + WordPurpose::wpCompletion); + mLastIdCharPressed = phrase.length(); + mCompletionPopup->search(phrase, false); + return true; + case Qt::Key_Escape: + mCompletionPopup->hide(); + return true; + case Qt::Key_Return: + case Qt::Key_Tab: + //CompletionInsert(devCodeCompletion.AppendFunc); + completionInsert(false); + return true; + default: + if (event->text().isEmpty()) { + //stop completion + mCompletionPopup->hide(); + keyPressEvent(event); + return true; + } + } + QChar ch = event->text().front(); + if (isIdentChar(ch)) { + setSelText(ch); + phrase = phrase = getWordAtPosition(caretXY(), + pBeginPos,pEndPos, + WordPurpose::wpCompletion); + mLastIdCharPressed = phrase.length(); + mCompletionPopup->search(phrase, false); + return true; + } else { + //stop completion + mCompletionPopup->hide(); + keyPressEvent(event); + return true; + } + return processed; +} + QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord &pWordEnd, WordPurpose purpose) { QString result = ""; diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 5612b1e0..50114b8e 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -167,6 +167,10 @@ private: bool testInFunc(int x,int y); + void completionInsert(bool appendFunc=false); + + bool onCompletionKeyPressed(QKeyEvent* event); + private: static int newfileCount; QByteArray mEncodingOption; // the encoding type set by the user diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 060c0647..f3d70fb6 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -2104,7 +2104,7 @@ void CppParser::handleOtherTypedefs() while ((mIndex< mTokenizer.tokenCount()) && !mTokenizer[mIndex]->text.startsWith(';')) mIndex++; //skip ; - if ((mIndex< mTokenizer.tokenCount()) && !mTokenizer[mIndex]->text.startsWith(';')) + if ((mIndex< mTokenizer.tokenCount()) && mTokenizer[mIndex]->text.startsWith(';')) mIndex++; return; } @@ -2186,7 +2186,7 @@ void CppParser::handleOtherTypedefs() newType += mTokenizer[mIndex]->text + ' '; mIndex++; } - if ((mIndex>= mTokenizer.tokenCount()) || (mTokenizer[mIndex]->text[1] == ';')) + if ((mIndex>= mTokenizer.tokenCount()) || (mTokenizer[mIndex]->text[0] == ';')) break; else if (mTokenizer[mIndex]->text.front() == ',') mIndex++; @@ -2528,14 +2528,14 @@ void CppParser::handleStructs(bool isTypedef) if (!(mTokenizer[i]->text.front() == '{' || mTokenizer[i]->text.front() == ',' || mTokenizer[i]->text.front() == ';')) { - if ((mTokenizer[i]->text.front() == '_') - && (mTokenizer[i]->text.back() == '_')) { - // skip possible gcc attributes - // start and end with 2 underscores (i.e. __attribute__) - // so, to avoid slow checks of strings, we just check the first and last letter of the token - // if both are underscores, we split - break; - } else { +// if ((mTokenizer[i]->text.front() == '_') +// && (mTokenizer[i]->text.back() == '_')) { +// // skip possible gcc attributes +// // start and end with 2 underscores (i.e. __attribute__) +// // so, to avoid slow checks of strings, we just check the first and last letter of the token +// // if both are underscores, we split +// break; +// } else { if (mTokenizer[i]->text.endsWith(']')) { // cut-off array brackets int pos = mTokenizer[i]->text.indexOf('['); command += mTokenizer[i]->text.mid(0,pos) + ' '; @@ -2546,7 +2546,7 @@ void CppParser::handleStructs(bool isTypedef) } else { command += mTokenizer[i]->text + ' '; } - } +// } } else { command = command.trimmed(); if (!command.isEmpty() && @@ -2873,9 +2873,9 @@ void CppParser::internalParse(const QString &fileName) }); // Let the preprocessor augment the include records // mPreprocessor.setIncludesList(mIncludesList); +// mPreprocessor.setScannedFileList(mScannedFiles); // mPreprocessor.setIncludePaths(mIncludePaths); // mPreprocessor.setProjectIncludePaths(mProjectIncludePaths); -// mPreprocessor.setScannedFileList(mScannedFiles); mPreprocessor.setScanOptions(mParseGlobalHeaders, mParseLocalHeaders); mPreprocessor.preprocess(fileName, buffer); #ifdef QT_DEBUG diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index f6cedfb8..c45adcfa 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -336,9 +336,10 @@ void CppPreprocessor::handleInclude(const QString &line) if (fileName.isEmpty()) return; - mCurrentIncludes->includeFiles.insert(fileName,true); + //mCurrentIncludes->includeFiles.insert(fileName,true); // And open a new entry openInclude(fileName); + mCurrentIncludes->includeFiles.insert(fileName,true); } void CppPreprocessor::handlePreprocessor(const QString &value) @@ -396,7 +397,7 @@ QString CppPreprocessor::expandMacros(const QString &line, int depth) } word = ""; if (i< lenLine) { - newLine += ch; + newLine += line[i]; } } i++; @@ -410,7 +411,9 @@ QString CppPreprocessor::expandMacros(const QString &line, int depth) void CppPreprocessor::expandMacro(const QString &line, QString &newLine, QString &word, int &i, int depth) { int lenLine = line.length(); - if (word == "__attribute__") { + if (word.startsWith("__") + && word.endsWith("__")) { +// if (word == "__attribute__") { //skip gcc __attribute__ while ((i lines()->count())) + return value; + QString line = lines()->getString(cy - 1); + if (cx>=line.length()) { + cx=line.length()-1; + } + + while (cx>=0 && cx lines()->count())) + return value; + QString line = lines()->getString(cy - 1); + + while (cx>=0 && cxcurrentIndex().row(); + if (mListView->currentIndex().isValid() + && (indexfileName) @@ -669,6 +686,11 @@ bool CodeCompletionView::isIncluded(const QString &fileName) return mIncludedFiles.contains(fileName); } +void CodeCompletionView::showEvent(QShowEvent *) +{ + mListView->setFocus(); +} + const PStatement &CodeCompletionView::currentStatement() const { return mCurrentStatement; @@ -819,6 +841,9 @@ QVariant CodeCompletionListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); + if (index.row()>=mStatements->count()) + return QVariant(); + if (role == Qt::DisplayRole) { PStatement statement = mStatements->at(index.row()); return statement->command; diff --git a/RedPandaIDE/widgets/codecompletionview.h b/RedPandaIDE/widgets/codecompletionview.h index 6691ca41..4833ad88 100644 --- a/RedPandaIDE/widgets/codecompletionview.h +++ b/RedPandaIDE/widgets/codecompletionview.h @@ -46,6 +46,7 @@ public: void prepareSearch(const QString& phrase, const QString& filename, int line); bool search(const QString& phrase, bool autoHideOnSingleResult); + PStatement selectedStatement(); const PCppParser &parser() const; void setParser(const PCppParser &newParser); @@ -111,6 +112,7 @@ private: // QWidget interface protected: + void showEvent(QShowEvent *event) override; void hideEvent(QHideEvent *event) override; };