diff --git a/NEWS.md b/NEWS.md index db385fbf..1607f932 100644 --- a/NEWS.md +++ b/NEWS.md @@ -20,6 +20,7 @@ Version 0.3.0 - implement: auto generate javadoc-style docstring for functions - enhancement: use up/down key to navigate function parameter tooltip - enhancement: press esc to close function parameter tooltip + - enhancement: code suggestion for unicode identifiers Version 0.2.1 - fix: crash when load last opens diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 5195ca1b..1fd1e916 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -1004,6 +1004,56 @@ void Editor::mouseReleaseEvent(QMouseEvent *event) SynEdit::mouseReleaseEvent(event); } +void Editor::inputMethodEvent(QInputMethodEvent *event) +{ + bool handled = false; + auto action = finally([this,&handled,event](){ + if (!handled) + SynEdit::inputMethodEvent(event); + }); + if (pMainWindow->completionPopup()->isVisible()) { + if (onCompletionInputMethod(event)) { + handled = true; + return; + } + } else { + QString s = event->commitString(); + if (!s.isEmpty()) { + mLastIdCharPressed+=s.length(); + if (pSettings->codeCompletion().enabled() + && pSettings->codeCompletion().showCompletionWhileInput() ) { + if (mLastIdCharPressed>=1) { + QString lastWord = getPreviousWordAtPositionForSuggestion(caretXY()); + if (!lastWord.isEmpty()) { + if (CppTypeKeywords.contains(lastWord)) { + return; + } + PStatement statement = mParser->findStatementOf( + mFilename, + lastWord, + caretY()); + StatementKind kind = mParser->getKindOfStatement(statement); + if (kind == StatementKind::skClass + || kind == StatementKind::skEnumClassType + || kind == StatementKind::skEnumType + || kind == StatementKind::skTypedef) { + //last word is a typedef/class/struct, this is a var or param define, and dont show suggestion + // if devEditor.UseTabnine then + // ShowTabnineCompletion; + return; + } + } + setSelText(s); + showCompletion(false); + handled = true; + return; + } + + } + } + } +} + void Editor::copyToClipboard() { if (pSettings->editor().copySizeLimit()) { @@ -2233,6 +2283,9 @@ bool Editor::onCompletionKeyPressed(QKeyEvent *event) BufferCoord pBeginPos,pEndPos; switch (event->key()) { case Qt::Key_Shift: + case Qt::Key_Control: + case Qt::Key_Meta: + case Qt::Key_Alt: //ignore it return true; case Qt::Key_Backspace: @@ -2334,6 +2387,25 @@ bool Editor::onHeaderCompletionKeyPressed(QKeyEvent *event) return processed; } +bool Editor::onCompletionInputMethod(QInputMethodEvent *event) +{ + bool processed = false; + if (!mCompletionPopup->isVisible()) + return processed; + QString s=event->commitString(); + if (!s.isEmpty()) { + setSelText(s); + BufferCoord pBeginPos,pEndPos; + QString phrase = getWordAtPosition(this,caretXY(), + pBeginPos,pEndPos, + WordPurpose::wpCompletion); + mLastIdCharPressed = phrase.length(); + mCompletionPopup->search(phrase, false); + return true; + } + return processed; +} + Editor::TipType Editor::getTipType(QPoint point, BufferCoord& pos) { // Only allow in the text area... diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 87a0f8bd..22a510ec 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -200,6 +200,7 @@ private: bool onCompletionKeyPressed(QKeyEvent* event); bool onHeaderCompletionKeyPressed(QKeyEvent* event); + bool onCompletionInputMethod(QInputMethodEvent *event); TipType getTipType(QPoint point, BufferCoord& pos); void cancelHint(); @@ -283,6 +284,10 @@ public: protected: void mouseReleaseEvent(QMouseEvent *event) override; + + // QWidget interface +protected: + void inputMethodEvent(QInputMethodEvent *) override; }; QString getWordAtPosition(SynEdit* editor, diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 872add99..f2a12c99 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -3593,8 +3593,9 @@ bool CppParser::isSpaceChar(const QChar &ch) bool CppParser::isWordChar(const QChar &ch) { - return (ch>= 'A' && ch<='Z') - || (ch>='a' && ch<='z') +// return (ch>= 'A' && ch<='Z') +// || (ch>='a' && ch<='z') + return ch.isLetter() || ch == '_' || ch == '*' || ch == '&'; @@ -3602,8 +3603,9 @@ bool CppParser::isWordChar(const QChar &ch) bool CppParser::isLetterChar(const QChar &ch) { - return (ch>= 'A' && ch<='Z') - || (ch>='a' && ch<='z') +// return (ch>= 'A' && ch<='Z') +// || (ch>='a' && ch<='z') + return ch.isLetter() || ch == '_'; } diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 6043acd2..2efae0a0 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -1000,7 +1000,10 @@ void CppPreprocessor::skipToPreprocessor() bool CppPreprocessor::isWordChar(const QChar &ch) { - if (ch=='_' || (ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9')) { + if (ch=='_' + // || (ch>='a' && ch<='z') || (ch>='A' && ch<='Z') + || ch.isLetter() + || (ch>='0' && ch<='9')) { return true; } return false; @@ -1009,7 +1012,9 @@ bool CppPreprocessor::isWordChar(const QChar &ch) bool CppPreprocessor::isIdentChar(const QChar &ch) { if (ch=='_' || ch == '*' || ch == '&' || ch == '~' || - (ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9')) { + ch.isLetter() + //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') + || (ch>='0' && ch<='9')) { return true; } return false; @@ -1048,7 +1053,9 @@ bool CppPreprocessor::isOperatorChar(const QChar &ch) bool CppPreprocessor::isMacroIdentChar(const QChar &ch) { - return (ch>='A' && ch<='Z') || (ch>='a' && ch<='z') || ch == '_'; + //return (ch>='A' && ch<='Z') || (ch>='a' && ch<='z') + return ch.isLetter() + || ch == '_'; } bool CppPreprocessor::isDigit(const QChar &ch) diff --git a/RedPandaIDE/widgets/codecompletionlistview.cpp b/RedPandaIDE/widgets/codecompletionlistview.cpp index fca7ce4b..b85608f8 100644 --- a/RedPandaIDE/widgets/codecompletionlistview.cpp +++ b/RedPandaIDE/widgets/codecompletionlistview.cpp @@ -5,7 +5,6 @@ CodeCompletionListView::CodeCompletionListView(QWidget *parent) : QListView(parent) { - } void CodeCompletionListView::keyPressEvent(QKeyEvent *event) @@ -20,7 +19,7 @@ void CodeCompletionListView::keyPressEvent(QKeyEvent *event) } } -void CodeCompletionListView::focusInEvent(QFocusEvent *event) +void CodeCompletionListView::focusInEvent(QFocusEvent *) { Editor *editor = pMainWindow->editorList()->getEditor(); if (editor) { diff --git a/RedPandaIDE/widgets/codecompletionlistview.h b/RedPandaIDE/widgets/codecompletionlistview.h index d84e79ba..be5853d7 100644 --- a/RedPandaIDE/widgets/codecompletionlistview.h +++ b/RedPandaIDE/widgets/codecompletionlistview.h @@ -5,6 +5,7 @@ #include #include "../parser/parserutils.h" using KeyPressedCallback = std::function; +using InputMethodCallback = std::function; class CodeCompletionListView: public QListView { Q_OBJECT @@ -15,6 +16,9 @@ public: const KeyPressedCallback &keypressedCallback() const; void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback); + const InputMethodCallback &inputMethodCallback() const; + void setInputMethodCallback(const InputMethodCallback &newInputMethodCallback); + protected: void keyPressEvent(QKeyEvent *event) override; private: