diff options
author | Marcus Tillmanns <marcus.tillmanns@qt.io> | 2023-04-27 12:18:07 +0200 |
---|---|---|
committer | Marcus Tillmanns <marcus.tillmanns@qt.io> | 2023-05-02 06:53:54 +0000 |
commit | 015d12ccf317443576c286ef87c09ddb01e4d34c (patch) | |
tree | 3260928b3f0bb6ed8eb1b2c3f88428ce4232a95b /src | |
parent | 8f345bbc35e3d1d7e92fdee25d4f42b1194e9793 (diff) |
FakeVim: Accept suggestion with Tab Key
* Changed signals to callbacks as only one receiver was ever added
* Added "tabPressedInInsertMode" callback to allow accepting
a suggestion with the Tab Key
Fixes: QTCREATORBUG-28830
Change-Id: Ie70ba595b8802b6100fff495164d8e0471b1354c
Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/fakevim/fakevimhandler.cpp | 20 | ||||
-rw-r--r-- | src/plugins/fakevim/fakevimhandler.h | 85 | ||||
-rw-r--r-- | src/plugins/fakevim/fakevimplugin.cpp | 72 |
3 files changed, 96 insertions, 81 deletions
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 05ea400bbba..bd1e035f48a 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -5459,16 +5459,18 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input) } else if (input.isKey(Key_PageUp) || input.isControl('b')) { movePageUp(); } else if (input.isKey(Key_Tab)) { - m_buffer->insertState.insertingSpaces = true; - if (s.expandTab.value()) { - const int ts = s.tabStop.value(); - const int col = logicalCursorColumn(); - QString str = QString(ts - col % ts, ' '); - insertText(str); - } else { - insertInInsertMode(input.raw()); + if (q->tabPressedInInsertMode()) { + m_buffer->insertState.insertingSpaces = true; + if (s.expandTab.value()) { + const int ts = s.tabStop.value(); + const int col = logicalCursorColumn(); + QString str = QString(ts - col % ts, ' '); + insertText(str); + } else { + insertInInsertMode(input.raw()); + } + m_buffer->insertState.insertingSpaces = false; } - m_buffer->insertState.insertingSpaces = false; } else if (input.isControl('d')) { // remove one level of indentation from the current line const int shift = s.shiftWidth.value(); diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h index 30ee5599ef8..b19e2579092 100644 --- a/src/plugins/fakevim/fakevimhandler.h +++ b/src/plugins/fakevim/fakevimhandler.h @@ -61,23 +61,30 @@ enum MessageLevel MessageShowCmd // partial command }; -template <typename Type> -class Signal +template<typename> +class Callback; + +template<typename R, typename... Params> +class Callback<R(Params...)> { public: - using Callable = std::function<Type>; - - void connect(const Callable &callable) { m_callables.push_back(callable); } + static constexpr auto IsVoidReturnType = std::is_same_v<R, void>; + using Function = std::function<R(Params...)>; + void set(const Function &callable) { m_callable = callable; } - template <typename ...Args> - void operator()(Args ...args) const + R operator()(Params... params) { - for (const Callable &callable : m_callables) - callable(args...); - } + if (!m_callable) + return R(); + + if constexpr (IsVoidReturnType) + m_callable(std::forward<Params>(params)...); + else + return m_callable(std::forward<Params>(params)...); + } private: - std::vector<Callable> m_callables; + Function m_callable; }; class FakeVimHandler : public QObject @@ -131,33 +138,35 @@ public: bool eventFilter(QObject *ob, QEvent *ev) override; - Signal<void(const QString &msg, int cursorPos, int anchorPos, int messageLevel)> commandBufferChanged; - Signal<void(const QString &msg)> statusDataChanged; - Signal<void(const QString &msg)> extraInformationChanged; - Signal<void(const QList<QTextEdit::ExtraSelection> &selection)> selectionChanged; - Signal<void(const QString &needle)> highlightMatches; - Signal<void(bool *moved, bool *forward, QTextCursor *cursor)> moveToMatchingParenthesis; - Signal<void(bool *result, QChar c)> checkForElectricCharacter; - Signal<void(int beginLine, int endLine, QChar typedChar)> indentRegion; - Signal<void(const QString &needle, bool forward)> simpleCompletionRequested; - Signal<void(const QString &key, int count)> windowCommandRequested; - Signal<void(bool reverse)> findRequested; - Signal<void(bool reverse)> findNextRequested; - Signal<void(bool *handled, const ExCommand &cmd)> handleExCommandRequested; - Signal<void()> requestDisableBlockSelection; - Signal<void(const QTextCursor &cursor)> requestSetBlockSelection; - Signal<void(QTextCursor *cursor)> requestBlockSelection; - Signal<void(bool *on)> requestHasBlockSelection; - Signal<void(int depth)> foldToggle; - Signal<void(bool fold)> foldAll; - Signal<void(int depth, bool dofold)> fold; - Signal<void(int count, bool current)> foldGoTo; - Signal<void(QChar mark, bool backTickMode, const QString &fileName)> requestJumpToLocalMark; - Signal<void(QChar mark, bool backTickMode, const QString &fileName)> requestJumpToGlobalMark; - Signal<void()> completionRequested; - Signal<void()> tabPreviousRequested; - Signal<void()> tabNextRequested; - Signal<void(bool insertMode)> modeChanged; + Callback<void(const QString &msg, int cursorPos, int anchorPos, int messageLevel)> + commandBufferChanged; + Callback<void(const QString &msg)> statusDataChanged; + Callback<void(const QString &msg)> extraInformationChanged; + Callback<void(const QList<QTextEdit::ExtraSelection> &selection)> selectionChanged; + Callback<void(const QString &needle)> highlightMatches; + Callback<void(bool *moved, bool *forward, QTextCursor *cursor)> moveToMatchingParenthesis; + Callback<void(bool *result, QChar c)> checkForElectricCharacter; + Callback<void(int beginLine, int endLine, QChar typedChar)> indentRegion; + Callback<void(const QString &needle, bool forward)> simpleCompletionRequested; + Callback<void(const QString &key, int count)> windowCommandRequested; + Callback<void(bool reverse)> findRequested; + Callback<void(bool reverse)> findNextRequested; + Callback<void(bool *handled, const ExCommand &cmd)> handleExCommandRequested; + Callback<void()> requestDisableBlockSelection; + Callback<void(const QTextCursor &cursor)> requestSetBlockSelection; + Callback<void(QTextCursor *cursor)> requestBlockSelection; + Callback<void(bool *on)> requestHasBlockSelection; + Callback<void(int depth)> foldToggle; + Callback<void(bool fold)> foldAll; + Callback<void(int depth, bool dofold)> fold; + Callback<void(int count, bool current)> foldGoTo; + Callback<void(QChar mark, bool backTickMode, const QString &fileName)> requestJumpToLocalMark; + Callback<void(QChar mark, bool backTickMode, const QString &fileName)> requestJumpToGlobalMark; + Callback<void()> completionRequested; + Callback<void()> tabPreviousRequested; + Callback<void()> tabNextRequested; + Callback<void(bool insertMode)> modeChanged; + Callback<bool()> tabPressedInInsertMode; public: class Private; diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index e41d83be2c0..d0c399ac31b 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -1586,7 +1586,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) new DeferredDeleter(widget, handler); m_editorToHandler[editor].handler = handler; - handler->extraInformationChanged.connect([this](const QString &text) { + handler->extraInformationChanged.set([this](const QString &text) { EditorManager::splitSideBySide(); QString title = "stdout.txt"; IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8()); @@ -1596,17 +1596,27 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) handler->handleCommand("0"); }); - handler->commandBufferChanged - .connect([this, handler](const QString &contents, int cursorPos, int anchorPos, int messageLevel) { - showCommandBuffer(handler, contents, cursorPos, anchorPos, messageLevel); - }); + handler->commandBufferChanged.set( + [this, handler](const QString &contents, int cursorPos, int anchorPos, int messageLevel) { + showCommandBuffer(handler, contents, cursorPos, anchorPos, messageLevel); + }); - handler->selectionChanged.connect([tew](const QList<QTextEdit::ExtraSelection> &selection) { + handler->selectionChanged.set([tew](const QList<QTextEdit::ExtraSelection> &selection) { if (tew) tew->setExtraSelections(TextEditorWidget::FakeVimSelection, selection); }); - handler->modeChanged.connect([tew, this, editor](bool insertMode) { + handler->tabPressedInInsertMode.set([tew]() { + auto suggestion = tew->currentSuggestion(); + if (suggestion) { + suggestion->apply(); + return false; + } + + return true; + }); + + handler->modeChanged.set([tew, this, editor](bool insertMode) { HandlerAndData &handlerAndData = m_editorToHandler[editor]; // We don't want to show suggestions unless we are in insert mode. @@ -1617,7 +1627,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) tew->clearSuggestion(); }); - handler->highlightMatches.connect([](const QString &needle) { + handler->highlightMatches.set([](const QString &needle) { for (IEditor *editor : EditorManager::visibleEditors()) { QWidget *w = editor->widget(); if (auto find = Aggregation::query<IFindSupport>(w)) @@ -1625,7 +1635,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) } }); - handler->moveToMatchingParenthesis.connect([](bool *moved, bool *forward, QTextCursor *cursor) { + handler->moveToMatchingParenthesis.set([](bool *moved, bool *forward, QTextCursor *cursor) { *moved = false; bool undoFakeEOL = false; @@ -1658,7 +1668,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) } }); - handler->indentRegion.connect([tew](int beginBlock, int endBlock, QChar typedChar) { + handler->indentRegion.set([tew](int beginBlock, int endBlock, QChar typedChar) { if (!tew) return; @@ -1691,17 +1701,17 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) } }); - handler->checkForElectricCharacter.connect([tew](bool *result, QChar c) { + handler->checkForElectricCharacter.set([tew](bool *result, QChar c) { if (tew) *result = tew->textDocument()->indenter()->isElectricCharacter(c); }); - handler->requestDisableBlockSelection.connect([tew] { + handler->requestDisableBlockSelection.set([tew] { if (tew) tew->setTextCursor(tew->textCursor()); }); - handler->requestSetBlockSelection.connect([tew](const QTextCursor &cursor) { + handler->requestSetBlockSelection.set([tew](const QTextCursor &cursor) { if (tew) { const TabSettings &tabs = tew->textDocument()->tabSettings(); MultiTextCursor mtc; @@ -1725,7 +1735,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) } }); - handler->requestBlockSelection.connect([tew](QTextCursor *cursor) { + handler->requestBlockSelection.set([tew](QTextCursor *cursor) { if (tew && cursor) { MultiTextCursor mtc = tew->multiTextCursor(); *cursor = mtc.cursors().first(); @@ -1733,16 +1743,16 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) } }); - handler->requestHasBlockSelection.connect([tew](bool *on) { + handler->requestHasBlockSelection.set([tew](bool *on) { if (tew && on) *on = tew->multiTextCursor().hasMultipleCursors(); }); - handler->simpleCompletionRequested.connect([this, handler](const QString &needle, bool forward) { + handler->simpleCompletionRequested.set([this, handler](const QString &needle, bool forward) { runData->wordProvider.setActive(needle, forward, handler); }); - handler->windowCommandRequested.connect([this, handler](const QString &map, int count) { + handler->windowCommandRequested.set([this, handler](const QString &map, int count) { // normalize mapping const QString key = map.toUpper(); @@ -1772,22 +1782,22 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) qDebug() << "UNKNOWN WINDOW COMMAND: <C-W>" << map; }); - handler->findRequested.connect([](bool reverse) { + handler->findRequested.set([](bool reverse) { Find::setUseFakeVim(true); Find::openFindToolBar(reverse ? Find::FindBackwardDirection : Find::FindForwardDirection); }); - handler->findNextRequested.connect([](bool reverse) { + handler->findNextRequested.set([](bool reverse) { triggerAction(reverse ? Core::Constants::FIND_PREVIOUS : Core::Constants::FIND_NEXT); }); - handler->foldToggle.connect([this, handler](int depth) { + handler->foldToggle.set([this, handler](int depth) { QTextBlock block = handler->textCursor().block(); fold(handler, depth, !TextDocumentLayout::isFolded(block)); }); - handler->foldAll.connect([handler](bool fold) { + handler->foldAll.set([handler](bool fold) { QTextDocument *document = handler->textCursor().document(); auto documentLayout = qobject_cast<TextDocumentLayout*>(document->documentLayout()); QTC_ASSERT(documentLayout, return); @@ -1802,11 +1812,9 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) documentLayout->emitDocumentSizeChanged(); }); - handler->fold.connect([this, handler](int depth, bool dofold) { - fold(handler, depth, dofold); - }); + handler->fold.set([this, handler](int depth, bool dofold) { fold(handler, depth, dofold); }); - handler->foldGoTo.connect([handler](int count, bool current) { + handler->foldGoTo.set([handler](int count, bool current) { QTextCursor tc = handler->textCursor(); QTextBlock block = tc.block(); @@ -1858,7 +1866,7 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) } }); - handler->requestJumpToGlobalMark.connect( + handler->requestJumpToGlobalMark.set( [this](QChar mark, bool backTickMode, const QString &fileName) { if (IEditor *iedit = EditorManager::openEditor(FilePath::fromString(fileName))) { if (FakeVimHandler *handler = m_editorToHandler.value(iedit, {}).handler) @@ -1866,19 +1874,15 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) } }); - handler->handleExCommandRequested.connect([this, handler](bool *handled, const ExCommand &cmd) { + handler->handleExCommandRequested.set([this, handler](bool *handled, const ExCommand &cmd) { handleExCommand(handler, handled, cmd); }); - handler->tabNextRequested.connect([] { - triggerAction(Core::Constants::GOTONEXTINHISTORY); - }); + handler->tabNextRequested.set([] { triggerAction(Core::Constants::GOTONEXTINHISTORY); }); - handler->tabPreviousRequested.connect([] { - triggerAction(Core::Constants::GOTOPREVINHISTORY); - }); + handler->tabPreviousRequested.set([] { triggerAction(Core::Constants::GOTOPREVINHISTORY); }); - handler->completionRequested.connect([this, tew] { + handler->completionRequested.set([this, tew] { if (tew) tew->invokeAssist(Completion, &runData->wordProvider); }); |