diff options
author | hjk <hjk@qt.io> | 2018-02-09 18:49:18 +0100 |
---|---|---|
committer | hjk <hjk@qt.io> | 2018-03-02 09:07:33 +0000 |
commit | 3ea4b0156c7a0567656eecabd67d801ad14c7eb5 (patch) | |
tree | 8cb3174f574137590b3847ff0f83602aacca821c /src/plugins/fakevim | |
parent | 33f2c240490b02ecae00a296022cdb8061a69a3d (diff) |
FakeVim: Experiment with hand-written signals
Change-Id: If76c68d3abb42240a279c15cf4b3d4b9e04460bd
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/plugins/fakevim')
-rw-r--r-- | src/plugins/fakevim/fakevimhandler.cpp | 76 | ||||
-rw-r--r-- | src/plugins/fakevim/fakevimhandler.h | 77 | ||||
-rw-r--r-- | src/plugins/fakevim/fakevimplugin.cpp | 621 |
3 files changed, 353 insertions, 421 deletions
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 60b277f5b98..45139a5bfdd 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1872,7 +1872,7 @@ public: m_cursor.movePosition(Right, KeepAnchor, n); } if (atEndOfLine()) - emit q->fold(q, 1, false); + q->fold(1, false); setTargetColumn(); } void moveLeft(int n = 1) { @@ -2516,7 +2516,7 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev) //m_tc = m_cursor; //bool hasBlock = false; - //emit q->requestHasBlockSelection(&hasBlock); + //q->requestHasBlockSelection(&hasBlock); //qDebug() << "IMPORT BLOCK 2:" << hasBlock; //if (0 && hasBlock) { @@ -3189,9 +3189,9 @@ void FakeVimHandler::Private::commitCursor() updateCursorShape(); if (isVisualBlockMode()) { - emit q->requestSetBlockSelection(q, tc); + q->requestSetBlockSelection(tc); } else { - emit q->requestDisableBlockSelection(q); + q->requestDisableBlockSelection(); if (editor()) EDITOR(setTextCursor(tc)); } @@ -3207,10 +3207,10 @@ void FakeVimHandler::Private::pullCursor() QTextCursor oldCursor = m_cursor; bool visualBlockMode = false; - emit q->requestHasBlockSelection(q, &visualBlockMode); + q->requestHasBlockSelection(&visualBlockMode); if (visualBlockMode) - q->requestBlockSelection(q, &m_cursor); + q->requestBlockSelection(&m_cursor); else if (editor()) m_cursor = editorCursor(); @@ -3327,7 +3327,7 @@ void FakeVimHandler::Private::moveToEndOfLineVisually(QTextCursor *tc) void FakeVimHandler::Private::moveBehindEndOfLine() { - emit q->fold(q, 1, false); + q->fold(1, false); int pos = qMin(block().position() + block().length() - 1, lastPositionInDocument() + 1); setPosition(pos); @@ -3601,7 +3601,7 @@ void FakeVimHandler::Private::updateSelection() } } //qDebug() << "SELECTION: " << selections; - emit q->selectionChanged(q, selections); + q->selectionChanged(selections); } void FakeVimHandler::Private::updateHighlights() @@ -3616,7 +3616,7 @@ void FakeVimHandler::Private::updateHighlights() return; } - emit q->highlightMatches(q, m_highlighted); + q->highlightMatches(m_highlighted); } void FakeVimHandler::Private::updateMiniBuffer() @@ -3684,7 +3684,7 @@ void FakeVimHandler::Private::updateMiniBuffer() if (g.isRecording && msg.startsWith("--")) msg.append(' ').append("Recording"); - emit q->commandBufferChanged(q, msg, cursorPos, anchorPos, messageLevel); + q->commandBufferChanged(msg, cursorPos, anchorPos, messageLevel); int linesInDoc = linesInDocument(); int l = cursorLine(); @@ -3696,7 +3696,7 @@ void FakeVimHandler::Private::updateMiniBuffer() status = Tr::tr("%1%2%").arg(pos, -10).arg(l * 100 / linesInDoc, 4); else status = Tr::tr("%1All").arg(pos, -10); - emit q->statusDataChanged(q, status); + q->statusDataChanged(status); } void FakeVimHandler::Private::showMessage(MessageLevel level, const QString &msg) @@ -3778,7 +3778,7 @@ bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input) handled = false; if (input.is('j') || input.is('k')) { int pos = position(); - emit q->foldGoTo(q, input.is('j') ? count() : -count(), false); + q->foldGoTo(input.is('j') ? count() : -count(), false); if (pos != position()) { handled = true; finishMovement(QString("%1z%2") @@ -3805,7 +3805,7 @@ bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input) else if (input.is(']') && g.subsubmode == CloseSquareSubSubMode) bracketSearchForward(&m_cursor, "^\\{", count(), g.submode != NoSubMode); else if (input.is('z')) - emit q->foldGoTo(q, g.subsubmode == OpenSquareSubSubMode ? -count() : count(), true); + q->foldGoTo(g.subsubmode == OpenSquareSubSubMode ? -count() : count(), true); handled = pos != position(); if (handled) { if (lineForPosition(pos) != lineForPosition(position())) @@ -3872,7 +3872,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) m_findStartPosition = position(); g.movetype = MoveExclusive; setAnchor(); // clear selection: otherwise, search is restricted to selection - emit q->findRequested(q, !g.lastSearchForward); + q->findRequested(!g.lastSearchForward); } else { // FIXME: make core find dialog sufficiently flexible to // produce the "default vi" behaviour too. For now, roll our own. @@ -4044,10 +4044,10 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) if (hasConfig(ConfigUseCoreSearch)) { bool forward = (input.is('n')) ? g.lastSearchForward : !g.lastSearchForward; int pos = position(); - emit q->findNextRequested(q, !forward); + q->findNextRequested(!forward); if (forward && pos == m_cursor.selectionStart()) { // if cursor is already positioned at the start of a find result, this is returned - emit q->findNextRequested(q, false); + q->findNextRequested(false); } setPosition(m_cursor.selectionStart()); } else { @@ -4385,7 +4385,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input) if (block().blockNumber() > 0) { moveUp(); if (line != lineNumber(block())) - emit q->fold(q, 1, true); + q->fold(1, true); moveDown(); } } else if (input.isControl('o')) { @@ -4662,7 +4662,7 @@ bool FakeVimHandler::Private::handleWindowSubMode(const Input &input) leaveVisualMode(); leaveCurrentMode(); - emit q->windowCommandRequested(q, input.toString(), count()); + q->windowCommandRequested(input.toString(), count()); return true; } @@ -4688,21 +4688,21 @@ bool FakeVimHandler::Private::handleZSubMode(const Input &input) } else if (input.is('o') || input.is('c')) { // Open/close current fold. foldMaybeClosed = input.is('c'); - emit q->fold(q, count(), foldMaybeClosed); + q->fold(count(), foldMaybeClosed); } else if (input.is('O') || input.is('C')) { // Recursively open/close current fold. foldMaybeClosed = input.is('C'); - emit q->fold(q, -1, foldMaybeClosed); + q->fold(-1, foldMaybeClosed); } else if (input.is('a') || input.is('A')) { // Toggle current fold. foldMaybeClosed = true; - emit q->foldToggle(q, input.is('a') ? count() : -1); + q->foldToggle(input.is('a') ? count() : -1); } else if (input.is('R') || input.is('M')) { // Open/close all folds in document. foldMaybeClosed = input.is('M'); - emit q->foldAll(q, foldMaybeClosed); + q->foldAll(foldMaybeClosed); } else if (input.is('j') || input.is('k')) { - emit q->foldGoTo(q, input.is('j') ? count() : -count(), false); + q->foldGoTo(input.is('j') ? count() : -count(), false); } else { handled = false; } @@ -5081,7 +5081,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input) moveToNextWordStart(1, false, false); QString str = selectText(Range(position(), tc.position())); m_cursor = tc; - emit q->simpleCompletionRequested(q, str, input.isControl('n')); + q->simpleCompletionRequested(str, input.isControl('n')); } else if (input.isShift(Qt::Key_Insert)) { // Insert text from clipboard. QClipboard *clipboard = QApplication::clipboard(); @@ -5568,7 +5568,7 @@ bool FakeVimHandler::Private::handleExTabNextCommand(const ExCommand &cmd) if (!cmd.matches("tabn", "tabnext")) return false; - emit q->tabNextRequested(q); + q->tabNextRequested(); return true; } @@ -5577,7 +5577,7 @@ bool FakeVimHandler::Private::handleExTabPreviousCommand(const ExCommand &cmd) if (!cmd.matches("tabp", "tabprevious")) return false; - emit q->tabPreviousRequested(q); + q->tabPreviousRequested(); return true; } @@ -5688,7 +5688,7 @@ bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd) ++i; info += QString("%1 %2\n").arg(i, -8).arg(item); } - emit q->extraInformationChanged(q, info); + q->extraInformationChanged(info); } else { notImplementedYet(); } @@ -5718,7 +5718,7 @@ bool FakeVimHandler::Private::handleExRegisterCommand(const ExCommand &cmd) QString value = quoteUnprintable(registerContents(reg)); info += QString("\"%1 %2\n").arg(reg).arg(value); } - emit q->extraInformationChanged(q, info); + q->extraInformationChanged(info); return true; } @@ -6037,7 +6037,7 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :! showMessage(MessageInfo, Tr::tr("%n lines filtered.", 0, input.count('\n'))); } else if (!result.isEmpty()) { - emit q->extraInformationChanged(q, result); + q->extraInformationChanged(result); } return true; @@ -6243,7 +6243,7 @@ bool FakeVimHandler::Private::handleExPluginCommand(const ExCommand &cmd) bool handled = false; int pos = m_cursor.position(); commitCursor(); - emit q->handleExCommandRequested(q, &handled, cmd); + q->handleExCommandRequested(&handled, cmd); //qDebug() << "HANDLER REQUEST: " << cmd.cmd << handled; if (handled && (m_textedit || m_plaintextedit)) { pullCursor(); @@ -6457,14 +6457,14 @@ void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar) // Don't remember current indentation in last text insertion. const QString lastInsertion = m_buffer->lastInsertion; - emit q->indentRegion(q, beginBlock, endBlock, typedChar); + q->indentRegion(beginBlock, endBlock, typedChar); m_buffer->lastInsertion = lastInsertion; } bool FakeVimHandler::Private::isElectricCharacter(QChar c) const { bool result = false; - emit q->checkForElectricCharacter(q, &result, c); + q->checkForElectricCharacter(&result, c); return result; } @@ -6588,7 +6588,7 @@ void FakeVimHandler::Private::miniBufferTextEdited(const QString &text, int curs // update command/search buffer cmdBuf.setContents(buffer.mid(1), pos - 1, anchor - 1); if (pos != cursorPos || anchor != anchorPos || buffer != text) - emit q->commandBufferChanged(q, buffer, pos, anchor, 0); + q->commandBufferChanged(buffer, pos, anchor, 0); // update search expression if (g.subsubmode == SearchSubSubMode) { updateFind(false); @@ -6775,7 +6775,7 @@ void FakeVimHandler::Private::moveToMatchingParanthesis() if (tc.atBlockEnd()) tc = m_cursor; - emit q->moveToMatchingParenthesis(q, &moved, &forward, &tc); + q->moveToMatchingParenthesis(&moved, &forward, &tc); if (moved) { if (forward) tc.movePosition(Left, KeepAnchor, 1); @@ -7342,7 +7342,7 @@ bool FakeVimHandler::Private::handleInsertInEditor(const Input &input) bool FakeVimHandler::Private::passEventToEditor(QEvent &event, QTextCursor &tc) { removeEventFilter(); - emit q->requestDisableBlockSelection(q); + q->requestDisableBlockSelection(); setThinCursor(); EDITOR(setTextCursor(tc)); @@ -7685,7 +7685,7 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved, } if (!m_highlighted.isEmpty()) - emit q->highlightMatches(q, m_highlighted); + q->highlightMatches(m_highlighted); } void FakeVimHandler::Private::onCursorPositionChanged() @@ -8451,7 +8451,7 @@ bool FakeVimHandler::Private::jumpToMark(QChar mark, bool backTickMode) return false; } if (!m.isLocal(m_currentFileName)) { - emit q->jumpToGlobalMark(q, mark, backTickMode, m.fileName()); + q->requestJumpToGlobalMark(mark, backTickMode, m.fileName()); return false; } @@ -8633,7 +8633,7 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) KEY_DEBUG("KEYPRESS" << kev->key() << kev->text() << QChar(kev->key())); EventResult res = d->handleEvent(kev); //if (Private::g.mode == InsertMode) - // emit completionRequested(); + // completionRequested(); // returning false core the app see it //KEY_DEBUG("HANDLED CODE:" << res); //return res != EventPassedToCore; diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h index 4cb22d9df1c..153cf83d507 100644 --- a/src/plugins/fakevim/fakevimhandler.h +++ b/src/plugins/fakevim/fakevimhandler.h @@ -28,6 +28,9 @@ #include <QObject> #include <QTextEdit> +#include <functional> +#include <vector> + namespace FakeVim { namespace Internal { @@ -80,6 +83,25 @@ enum MessageLevel MessageShowCmd // partial command }; +template <typename Type> +class Signal +{ +public: + using Callable = std::function<Type>; + + void connect(const Callable &callable) { m_callables.push_back(callable); } + + template <typename ...Args> + void operator()(Args ...args) const + { + for (const Callable &callable : m_callables) + callable(args...); + } + +private: + std::vector<Callable> m_callables; +}; + class FakeVimHandler : public QObject { Q_OBJECT @@ -131,34 +153,33 @@ public: bool eventFilter(QObject *ob, QEvent *ev); -signals: - void commandBufferChanged(FakeVimHandler *self, const QString &msg, int cursorPos, int anchorPos, - int messageLevel); - void statusDataChanged(FakeVimHandler *self, const QString &msg); - void extraInformationChanged(FakeVimHandler *self, const QString &msg); - void selectionChanged(FakeVimHandler *self, const QList<QTextEdit::ExtraSelection> &selection); - void highlightMatches(FakeVimHandler *self, const QString &needle); - void writeAllRequested(FakeVimHandler *self, QString *error); - void moveToMatchingParenthesis(FakeVimHandler *self, bool *moved, bool *forward, QTextCursor *cursor); - void checkForElectricCharacter(FakeVimHandler *self, bool *result, QChar c); - void indentRegion(FakeVimHandler *self, int beginLine, int endLine, QChar typedChar); - void completionRequested(FakeVimHandler *self); - void simpleCompletionRequested(FakeVimHandler *self, const QString &needle, bool forward); - void windowCommandRequested(FakeVimHandler *self, const QString &key, int count); - void findRequested(FakeVimHandler *self, bool reverse); - void findNextRequested(FakeVimHandler *self, bool reverse); - void handleExCommandRequested(FakeVimHandler *self, bool *handled, const ExCommand &cmd); - void requestDisableBlockSelection(FakeVimHandler *self); - void requestSetBlockSelection(FakeVimHandler *self, const QTextCursor &cursor); - void requestBlockSelection(FakeVimHandler *self, QTextCursor *cursor); - void requestHasBlockSelection(FakeVimHandler *self, bool *on); - void foldToggle(FakeVimHandler *self, int depth); - void foldAll(FakeVimHandler *self, bool fold); - void fold(FakeVimHandler *self, int depth, bool fold); - void foldGoTo(FakeVimHandler *self, int count, bool current); - void jumpToGlobalMark(FakeVimHandler *handler, QChar mark, bool backTickMode, const QString &fileName); - void tabNextRequested(FakeVimHandler *self); - void tabPreviousRequested(FakeVimHandler *self); + 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(QString *error)> writeAllRequested; + 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; public: class Private; diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 8d0ede09048..4b363705b97 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -97,6 +97,8 @@ #include <QTimer> #include <QTreeWidgetItem> +#include <functional> + using namespace TextEditor; using namespace Core; using namespace Utils; @@ -524,32 +526,13 @@ public: void setUseFakeVim(const QVariant &value); void setUseFakeVimInternal(bool on); void quitFakeVim(); - void triggerCompletions(FakeVimHandler *handler); - void triggerSimpleCompletions(FakeVimHandler *handler, const QString &needle, bool forward); - void windowCommand(FakeVimHandler *handler, const QString &key, int count); - void find(bool reverse); - void findNext(bool reverse); - void foldToggle(FakeVimHandler *handler, int depth); - void foldAll(FakeVimHandler *handler, bool fold); void fold(FakeVimHandler *handler, int depth, bool fold); - void foldGoTo(FakeVimHandler *handler, int count, bool current); - void jumpToGlobalMark(FakeVimHandler *, QChar mark, bool backTickMode, const QString &fileName); void maybeReadVimRc(); - void disableBlockSelection(FakeVimHandler *handler); - void setBlockSelection(FakeVimHandler *handler, const QTextCursor &cursor); - void blockSelection(FakeVimHandler *handler, QTextCursor *cursor); - void hasBlockSelection(FakeVimHandler *handler, bool *on); void setShowRelativeLineNumbers(const QVariant &value); void resetCommandBuffer(); void showCommandBuffer(FakeVimHandler *handler, const QString &contents, int cursorPos, int anchorPos, int messageLevel); - void showExtraInformation(FakeVimHandler *handler, const QString &msg); - void changeSelection(FakeVimHandler *handler, const QList<QTextEdit::ExtraSelection> &selections); - void highlightMatches(FakeVimHandler *handler, const QString &needle); - void moveToMatchingParenthesis(FakeVimHandler *handler, bool *moved, bool *forward, QTextCursor *cursor); - void checkForElectricCharacter(FakeVimHandler *handler, bool *result, QChar c); - void indentRegion(FakeVimHandler *handler, int beginBlock, int endBlock, QChar typedChar); void handleExCommand(FakeVimHandler *handler, bool *handled, const ExCommand &cmd); void writeSettings(); @@ -571,7 +554,6 @@ signals: public: QHash<IEditor *, FakeVimHandler *> m_editorToHandler; - void triggerAction(Id id); void setActionChecked(Id id, bool check); typedef int (*DistFunction)(const QRect &cursor, const QRect &other); @@ -1344,7 +1326,7 @@ void FakeVimPluginPrivate::maybeReadVimRc() //qDebug() << theFakeVimSetting(ConfigShiftWidth)->value(); } -void FakeVimPluginPrivate::triggerAction(Id id) +static void triggerAction(Id id) { Command *cmd = ActionManager::command(id); QTC_ASSERT(cmd, qDebug() << "UNKNOWN CODE: " << id.name(); return); @@ -1404,37 +1386,6 @@ static int moveDownWeight(const QRect &cursor, const QRect &other) return w; } -void FakeVimPluginPrivate::windowCommand(FakeVimHandler *handler, const QString &map, int count) -{ - // normalize mapping - const QString key = map.toUpper(); - - if (key == "C" || key == "<C-C>") - triggerAction(Core::Constants::REMOVE_CURRENT_SPLIT); - else if (key == "N" || key == "<C-N>") - triggerAction(Core::Constants::GOTONEXT); - else if (key == "O" || key == "<C-O>") - keepOnlyWindow(); - else if (key == "P" || key == "<C-P>") - triggerAction(Core::Constants::GOTOPREV); - else if (key == "S" || key == "<C-S>") - triggerAction(Core::Constants::SPLIT); - else if (key == "V" || key == "<C-V>") - triggerAction(Core::Constants::SPLIT_SIDE_BY_SIDE); - else if (key == "W" || key == "<C-W>") - triggerAction(Core::Constants::GOTO_NEXT_SPLIT); - else if (key.contains("RIGHT") || key == "L" || key == "<S-L>") - moveSomewhere(handler, &moveRightWeight, key == "<S-L>" ? -1 : count); - else if (key.contains("LEFT") || key == "H" || key == "<S-H>") - moveSomewhere(handler, &moveLeftWeight, key == "<S-H>" ? -1 : count); - else if (key.contains("UP") || key == "K" || key == "<S-K>") - moveSomewhere(handler, &moveUpWeight, key == "<S-K>" ? -1 : count); - else if (key.contains("DOWN") || key == "J" || key == "<S-J>") - moveSomewhere(handler, &moveDownWeight, key == "<S-J>" ? -1 : count); - else - qDebug() << "UNKNOWN WINDOW COMMAND: <C-W>" << map; -} - void FakeVimPluginPrivate::moveSomewhere(FakeVimHandler *handler, DistFunction f, int count) { QTC_ASSERT(handler, return); @@ -1491,45 +1442,6 @@ void FakeVimPluginPrivate::keepOnlyWindow() } } -void FakeVimPluginPrivate::find(bool reverse) -{ - Find::setUseFakeVim(true); - Find::openFindToolBar(reverse ? Find::FindBackwardDirection - : Find::FindForwardDirection); -} - -void FakeVimPluginPrivate::findNext(bool reverse) -{ - if (reverse) - triggerAction(Core::Constants::FIND_PREVIOUS); - else - triggerAction(Core::Constants::FIND_NEXT); -} - -void FakeVimPluginPrivate::foldToggle(FakeVimHandler *handler, int depth) -{ - QTC_ASSERT(handler, return); - QTextBlock block = handler->textCursor().block(); - fold(handler, depth, !TextDocumentLayout::isFolded(block)); -} - -void FakeVimPluginPrivate::foldAll(FakeVimHandler *handler, bool fold) -{ - QTC_ASSERT(handler, return); - QTextDocument *document = handler->textCursor().document(); - auto documentLayout = qobject_cast<TextDocumentLayout*>(document->documentLayout()); - QTC_ASSERT(documentLayout != 0, return); - - QTextBlock block = document->firstBlock(); - while (block.isValid()) { - TextDocumentLayout::doFoldOrUnfold(block, !fold); - block = block.next(); - } - - documentLayout->requestUpdate(); - documentLayout->emitDocumentSizeChanged(); -} - void FakeVimPluginPrivate::fold(FakeVimHandler *handler, int depth, bool fold) { QTC_ASSERT(handler, return); @@ -1583,71 +1495,6 @@ void FakeVimPluginPrivate::fold(FakeVimHandler *handler, int depth, bool fold) documentLayout->emitDocumentSizeChanged(); } -void FakeVimPluginPrivate::foldGoTo(FakeVimHandler *handler, int count, bool current) -{ - QTC_ASSERT(handler, return); - QTextCursor tc = handler->textCursor(); - QTextBlock block = tc.block(); - - int pos = -1; - if (count > 0) { - int repeat = count; - block = block.next(); - QTextBlock prevBlock = block; - int indent = TextDocumentLayout::foldingIndent(block); - block = block.next(); - while (block.isValid()) { - int newIndent = TextDocumentLayout::foldingIndent(block); - if (current ? indent > newIndent : indent < newIndent) { - if (prevBlock.isVisible()) { - pos = prevBlock.position(); - if (--repeat <= 0) - break; - } else if (current) { - indent = newIndent; - } - } - if (!current) - indent = newIndent; - prevBlock = block; - block = block.next(); - } - } else if (count < 0) { - int repeat = -count; - int indent = TextDocumentLayout::foldingIndent(block); - block = block.previous(); - while (block.isValid()) { - int newIndent = TextDocumentLayout::foldingIndent(block); - if (current ? indent > newIndent : indent < newIndent) { - while (block.isValid() && !block.isVisible()) - block = block.previous(); - pos = block.position(); - if (--repeat <= 0) - break; - } - if (!current) - indent = newIndent; - block = block.previous(); - } - } - - if (pos != -1) { - tc.setPosition(pos, QTextCursor::KeepAnchor); - handler->setTextCursor(tc); - } -} - -void FakeVimPluginPrivate::jumpToGlobalMark(FakeVimHandler *, - QChar mark, bool backTickMode, const QString &fileName) -{ - IEditor *iedit = EditorManager::openEditor(fileName); - if (!iedit) - return; - FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr); - if (handler) - handler->jumpToLocalMark(mark, backTickMode); -} - // This class defers deletion of a child FakeVimHandler using deleteLater(). class DeferredDeleter : public QObject { @@ -1683,6 +1530,8 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) if (!qobject_cast<QTextEdit *>(widget) && !qobject_cast<QPlainTextEdit *>(widget)) return; + TextEditorWidget *tew = qobject_cast<TextEditorWidget *>(widget); + //qDebug() << "OPENING: " << editor << editor->widget() // << "MODE: " << theFakeVimSetting(ConfigUseFakeVim)->value(); @@ -1692,59 +1541,271 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) new DeferredDeleter(widget, handler); m_editorToHandler[editor] = handler; - connect(handler, &FakeVimHandler::extraInformationChanged, - this, &FakeVimPluginPrivate::showExtraInformation); - connect(handler, &FakeVimHandler::commandBufferChanged, - this, &FakeVimPluginPrivate::showCommandBuffer); - connect(handler, &FakeVimHandler::selectionChanged, - this, &FakeVimPluginPrivate::changeSelection); - connect(handler, &FakeVimHandler::highlightMatches, - this, &FakeVimPluginPrivate::highlightMatches); - connect(handler, &FakeVimHandler::moveToMatchingParenthesis, - this, &FakeVimPluginPrivate::moveToMatchingParenthesis, Qt::DirectConnection); - connect(handler, &FakeVimHandler::indentRegion, - this, &FakeVimPluginPrivate::indentRegion); - connect(handler, &FakeVimHandler::checkForElectricCharacter, - this, &FakeVimPluginPrivate::checkForElectricCharacter, Qt::DirectConnection); - connect(handler, &FakeVimHandler::requestDisableBlockSelection, - this, &FakeVimPluginPrivate::disableBlockSelection); - connect(handler, &FakeVimHandler::requestSetBlockSelection, - this, &FakeVimPluginPrivate::setBlockSelection); - connect(handler, &FakeVimHandler::requestBlockSelection, - this, &FakeVimPluginPrivate::blockSelection, Qt::DirectConnection); - connect(handler, &FakeVimHandler::requestHasBlockSelection, - this, &FakeVimPluginPrivate::hasBlockSelection, Qt::DirectConnection); - connect(handler, &FakeVimHandler::completionRequested, - this, &FakeVimPluginPrivate::triggerCompletions); - connect(handler, &FakeVimHandler::simpleCompletionRequested, - this, &FakeVimPluginPrivate::triggerSimpleCompletions); - connect(handler, &FakeVimHandler::windowCommandRequested, - this, &FakeVimPluginPrivate::windowCommand); - connect(handler, &FakeVimHandler::findRequested, - this, &FakeVimPluginPrivate::find); - connect(handler, &FakeVimHandler::findNextRequested, - this, &FakeVimPluginPrivate::findNext); - connect(handler, &FakeVimHandler::foldToggle, - this, &FakeVimPluginPrivate::foldToggle); - connect(handler, &FakeVimHandler::foldAll, - this, &FakeVimPluginPrivate::foldAll); - connect(handler, &FakeVimHandler::fold, - this, &FakeVimPluginPrivate::fold); - connect(handler, &FakeVimHandler::foldGoTo, - this, &FakeVimPluginPrivate::foldGoTo); - connect(handler, &FakeVimHandler::jumpToGlobalMark, - this, &FakeVimPluginPrivate::jumpToGlobalMark); - - connect(handler, &FakeVimHandler::handleExCommandRequested, - this, &FakeVimPluginPrivate::handleExCommand, Qt::DirectConnection); + handler->extraInformationChanged.connect([this](const QString &text) { + EditorManager::splitSideBySide(); + QString title = "stdout.txt"; + IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8()); + EditorManager::activateEditor(iedit); + FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr); + QTC_ASSERT(handler, return); + handler->handleCommand("0"); + }); + + handler->commandBufferChanged + .connect([this, handler](const QString &contents, int cursorPos, int anchorPos, int messageLevel) { + showCommandBuffer(handler, contents, cursorPos, anchorPos, messageLevel); + }); + + handler->selectionChanged.connect([handler, tew](const QList<QTextEdit::ExtraSelection> &selection) { + if (tew) + tew->setExtraSelections(TextEditorWidget::FakeVimSelection, selection); + }); + + handler->highlightMatches.connect([](const QString &needle) { + for (IEditor *editor : EditorManager::visibleEditors()) { + QWidget *w = editor->widget(); + IFindSupport *find = Aggregation::query<IFindSupport>(w); + if (find != 0) + find->highlightAll(needle, FindRegularExpression | FindCaseSensitively); + } + }); + + handler->moveToMatchingParenthesis.connect([](bool *moved, bool *forward, QTextCursor *cursor) { + *moved = false; + + bool undoFakeEOL = false; + if (cursor->atBlockEnd() && cursor->block().length() > 1) { + cursor->movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1); + undoFakeEOL = true; + } + TextBlockUserData::MatchType match = TextBlockUserData::matchCursorForward(cursor); + if (match == TextBlockUserData::Match) { + *moved = true; + *forward = true; + } else { + if (undoFakeEOL) + cursor->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1); + if (match == TextBlockUserData::NoMatch) { + // Backward matching is according to the character before the cursor. + bool undoMove = false; + if (!cursor->atBlockEnd()) { + cursor->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1); + undoMove = true; + } + match = TextBlockUserData::matchCursorBackward(cursor); + if (match == TextBlockUserData::Match) { + *moved = true; + *forward = false; + } else if (undoMove) { + cursor->movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1); + } + } + } + }); + + handler->indentRegion.connect([this, tew](int beginBlock, int endBlock, QChar typedChar) { + if (!tew) + return; + + TabSettings tabSettings; + tabSettings.m_indentSize = theFakeVimSetting(ConfigShiftWidth)->value().toInt(); + tabSettings.m_tabSize = theFakeVimSetting(ConfigTabStop)->value().toInt(); + tabSettings.m_tabPolicy = theFakeVimSetting(ConfigExpandTab)->value().toBool() + ? TabSettings::SpacesOnlyTabPolicy : TabSettings::TabsOnlyTabPolicy; + + QTextDocument *doc = tew->document(); + QTextBlock startBlock = doc->findBlockByNumber(beginBlock); + + // Record line lenghts for mark adjustments + QVector<int> lineLengths(endBlock - beginBlock + 1); + QTextBlock block = startBlock; + + for (int i = beginBlock; i <= endBlock; ++i) { + lineLengths[i - beginBlock] = block.text().length(); + if (typedChar.unicode() == 0 && block.text().simplified().isEmpty()) { + // clear empty lines + QTextCursor cursor(block); + while (!cursor.atBlockEnd()) + cursor.deleteChar(); + } else { + tew->textDocument()->indenter()->indentBlock(doc, block, typedChar, tabSettings); + } + block = block.next(); + } + }); + + handler->checkForElectricCharacter.connect([this, tew](bool *result, QChar c) { + if (tew) + *result = tew->textDocument()->indenter()->isElectricCharacter(c); + }); + + handler->requestDisableBlockSelection.connect([tew] { + if (tew) + tew->setBlockSelection(false); + }); + + handler->requestSetBlockSelection.connect([tew](const QTextCursor &cursor) { + if (tew) + tew->setBlockSelection(cursor); + }); + + handler->requestBlockSelection.connect([tew](QTextCursor *cursor) { + if (tew && cursor) + *cursor = tew->blockSelection(); + }); + + handler->requestHasBlockSelection.connect([tew](bool *on) { + if (tew && on) + *on = tew->hasBlockSelection(); + }); + + handler->simpleCompletionRequested.connect([this, handler](const QString &needle, bool forward) { + runData->wordProvider.setActive(needle, forward, handler); + }); + + handler->windowCommandRequested.connect([this, handler](const QString &map, int count) { + // normalize mapping + const QString key = map.toUpper(); + + if (key == "C" || key == "<C-C>") + triggerAction(Core::Constants::REMOVE_CURRENT_SPLIT); + else if (key == "N" || key == "<C-N>") + triggerAction(Core::Constants::GOTONEXT); + else if (key == "O" || key == "<C-O>") + keepOnlyWindow(); + else if (key == "P" || key == "<C-P>") + triggerAction(Core::Constants::GOTOPREV); + else if (key == "S" || key == "<C-S>") + triggerAction(Core::Constants::SPLIT); + else if (key == "V" || key == "<C-V>") + triggerAction(Core::Constants::SPLIT_SIDE_BY_SIDE); + else if (key == "W" || key == "<C-W>") + triggerAction(Core::Constants::GOTO_NEXT_SPLIT); + else if (key.contains("RIGHT") || key == "L" || key == "<S-L>") + moveSomewhere(handler, &moveRightWeight, key == "<S-L>" ? -1 : count); + else if (key.contains("LEFT") || key == "H" || key == "<S-H>") + moveSomewhere(handler, &moveLeftWeight, key == "<S-H>" ? -1 : count); + else if (key.contains("UP") || key == "K" || key == "<S-K>") + moveSomewhere(handler, &moveUpWeight, key == "<S-K>" ? -1 : count); + else if (key.contains("DOWN") || key == "J" || key == "<S-J>") + moveSomewhere(handler, &moveDownWeight, key == "<S-J>" ? -1 : count); + else + qDebug() << "UNKNOWN WINDOW COMMAND: <C-W>" << map; + }); + + handler->findRequested.connect([](bool reverse) { + Find::setUseFakeVim(true); + Find::openFindToolBar(reverse ? Find::FindBackwardDirection + : Find::FindForwardDirection); + }); + + handler->findNextRequested.connect([](bool reverse) { + triggerAction(reverse ? Core::Constants::FIND_PREVIOUS : Core::Constants::FIND_NEXT); + }); + + handler->foldToggle.connect([this, handler](int depth) { + QTextBlock block = handler->textCursor().block(); + fold(handler, depth, !TextDocumentLayout::isFolded(block)); + }); + + handler->foldAll.connect([handler](bool fold) { + QTextDocument *document = handler->textCursor().document(); + auto documentLayout = qobject_cast<TextDocumentLayout*>(document->documentLayout()); + QTC_ASSERT(documentLayout != 0, return); + + QTextBlock block = document->firstBlock(); + while (block.isValid()) { + TextDocumentLayout::doFoldOrUnfold(block, !fold); + block = block.next(); + } + + documentLayout->requestUpdate(); + documentLayout->emitDocumentSizeChanged(); + }); + + handler->fold.connect([this, handler](int depth, bool dofold) { + fold(handler, depth, dofold); + }); + + handler->foldGoTo.connect([this, handler](int count, bool current) { + QTextCursor tc = handler->textCursor(); + QTextBlock block = tc.block(); + + int pos = -1; + if (count > 0) { + int repeat = count; + block = block.next(); + QTextBlock prevBlock = block; + int indent = TextDocumentLayout::foldingIndent(block); + block = block.next(); + while (block.isValid()) { + int newIndent = TextDocumentLayout::foldingIndent(block); + if (current ? indent > newIndent : indent < newIndent) { + if (prevBlock.isVisible()) { + pos = prevBlock.position(); + if (--repeat <= 0) + break; + } else if (current) { + indent = newIndent; + } + } + if (!current) + indent = newIndent; + prevBlock = block; + block = block.next(); + } + } else if (count < 0) { + int repeat = -count; + int indent = TextDocumentLayout::foldingIndent(block); + block = block.previous(); + while (block.isValid()) { + int newIndent = TextDocumentLayout::foldingIndent(block); + if (current ? indent > newIndent : indent < newIndent) { + while (block.isValid() && !block.isVisible()) + block = block.previous(); + pos = block.position(); + if (--repeat <= 0) + break; + } + if (!current) + indent = newIndent; + block = block.previous(); + } + } + + if (pos != -1) { + tc.setPosition(pos, QTextCursor::KeepAnchor); + handler->setTextCursor(tc); + } + }); + + handler->requestJumpToGlobalMark.connect([this](QChar mark, bool backTickMode, const QString &fileName) { + if (IEditor *iedit = EditorManager::openEditor(fileName)) { + if (FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr)) + handler->jumpToLocalMark(mark, backTickMode); + } + }); + + handler->handleExCommandRequested.connect([this, handler](bool *handled, const ExCommand &cmd) { + handleExCommand(handler, handled, cmd); + }); + + handler->tabNextRequested.connect([this] { + triggerAction(Core::Constants::GOTONEXTINHISTORY); + }); + + handler->tabPreviousRequested.connect([this] { + triggerAction(Core::Constants::GOTOPREVINHISTORY); + }); + + handler->completionRequested.connect([this, tew] { + if (tew) + tew->invokeAssist(Completion, &runData->wordProvider); + }); connect(ICore::instance(), &ICore::saveSettingsRequested, this, &FakeVimPluginPrivate::writeSettings); - connect(handler, &FakeVimHandler::tabNextRequested, - this, [this] { triggerAction(Core::Constants::GOTONEXTINHISTORY); }); - connect(handler, &FakeVimHandler::tabPreviousRequested, - this, [this] { triggerAction(Core::Constants::GOTOPREVINHISTORY); }); handler->setCurrentFileName(editor->document()->filePath().toString()); handler->installEventFilter(); @@ -1820,49 +1881,6 @@ void FakeVimPluginPrivate::setUseFakeVimInternal(bool on) } } -void FakeVimPluginPrivate::triggerCompletions(FakeVimHandler *handler) -{ - QTC_ASSERT(handler, return); - if (TextEditorWidget *editor = qobject_cast<TextEditorWidget *>(handler->widget())) - editor->invokeAssist(Completion, &runData->wordProvider); -// CompletionSupport::instance()->complete(editor->editor(), TextCompletion, false); -} - -void FakeVimPluginPrivate::triggerSimpleCompletions(FakeVimHandler *handler, const QString &needle, bool forward) -{ - QTC_ASSERT(handler, return); - runData->wordProvider.setActive(needle, forward, handler); -} - -void FakeVimPluginPrivate::disableBlockSelection(FakeVimHandler *handler) -{ - QTC_ASSERT(handler, return); - if (TextEditorWidget *bt = qobject_cast<TextEditorWidget *>(handler->widget())) - bt->setBlockSelection(false); -} - -void FakeVimPluginPrivate::setBlockSelection(FakeVimHandler *handler, const QTextCursor &cursor) -{ - QTC_ASSERT(handler, return); - if (TextEditorWidget *bt = qobject_cast<TextEditorWidget *>(handler->widget())) - bt->setBlockSelection(cursor); -} - -void FakeVimPluginPrivate::blockSelection(FakeVimHandler *handler, QTextCursor *cursor) -{ - QTC_ASSERT(handler, return); - if (TextEditorWidget *bt = qobject_cast<TextEditorWidget *>(handler->widget())) - if (cursor) - *cursor = bt->blockSelection(); -} - -void FakeVimPluginPrivate::hasBlockSelection(FakeVimHandler *handler, bool *on) -{ - QTC_ASSERT(handler, return); - if (TextEditorWidget *bt = qobject_cast<TextEditorWidget *>(handler->widget())) - *on = bt->hasBlockSelection(); -} - void FakeVimPluginPrivate::setShowRelativeLineNumbers(const QVariant &value) { if (value.toBool() && theFakeVimSetting(ConfigUseFakeVim)->value().toBool()) { @@ -1871,13 +1889,6 @@ void FakeVimPluginPrivate::setShowRelativeLineNumbers(const QVariant &value) } } -void FakeVimPluginPrivate::checkForElectricCharacter(FakeVimHandler *handler, bool *result, QChar c) -{ - QTC_ASSERT(handler, return); - if (TextEditorWidget *bt = qobject_cast<TextEditorWidget *>(handler->widget())) - *result = bt->textDocument()->indenter()->isElectricCharacter(c); -} - void FakeVimPluginPrivate::handleExCommand(FakeVimHandler *handler, bool *handled, const ExCommand &cmd) { QTC_ASSERT(handler, return); @@ -2001,78 +2012,6 @@ void FakeVimPluginPrivate::handleDelayedQuitAll(bool forced) EditorManager::closeAllEditors(!forced); } -void FakeVimPluginPrivate::moveToMatchingParenthesis(FakeVimHandler *, bool *moved, bool *forward, - QTextCursor *cursor) -{ - *moved = false; - - bool undoFakeEOL = false; - if (cursor->atBlockEnd() && cursor->block().length() > 1) { - cursor->movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1); - undoFakeEOL = true; - } - TextBlockUserData::MatchType match - = TextBlockUserData::matchCursorForward(cursor); - if (match == TextBlockUserData::Match) { - *moved = true; - *forward = true; - } else { - if (undoFakeEOL) - cursor->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1); - if (match == TextBlockUserData::NoMatch) { - // Backward matching is according to the character before the cursor. - bool undoMove = false; - if (!cursor->atBlockEnd()) { - cursor->movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 1); - undoMove = true; - } - match = TextBlockUserData::matchCursorBackward(cursor); - if (match == TextBlockUserData::Match) { - *moved = true; - *forward = false; - } else if (undoMove) { - cursor->movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 1); - } - } - } -} - -void FakeVimPluginPrivate::indentRegion(FakeVimHandler *handler, - int beginBlock, int endBlock, QChar typedChar) -{ - QTC_ASSERT(handler, return); - - TextEditorWidget *bt = qobject_cast<TextEditorWidget *>(handler->widget()); - if (!bt) - return; - - TabSettings tabSettings; - tabSettings.m_indentSize = theFakeVimSetting(ConfigShiftWidth)->value().toInt(); - tabSettings.m_tabSize = theFakeVimSetting(ConfigTabStop)->value().toInt(); - tabSettings.m_tabPolicy = theFakeVimSetting(ConfigExpandTab)->value().toBool() - ? TabSettings::SpacesOnlyTabPolicy : TabSettings::TabsOnlyTabPolicy; - - QTextDocument *doc = bt->document(); - QTextBlock startBlock = doc->findBlockByNumber(beginBlock); - - // Record line lenghts for mark adjustments - QVector<int> lineLengths(endBlock - beginBlock + 1); - QTextBlock block = startBlock; - - for (int i = beginBlock; i <= endBlock; ++i) { - lineLengths[i - beginBlock] = block.text().length(); - if (typedChar.unicode() == 0 && block.text().simplified().isEmpty()) { - // clear empty lines - QTextCursor cursor(block); - while (!cursor.atBlockEnd()) - cursor.deleteChar(); - } else { - bt->textDocument()->indenter()->indentBlock(doc, block, typedChar, tabSettings); - } - block = block.next(); - } -} - void FakeVimPluginPrivate::quitFakeVim() { theFakeVimSetting(ConfigUseFakeVim)->setValue(false); @@ -2091,34 +2030,6 @@ void FakeVimPluginPrivate::showCommandBuffer(FakeVimHandler *handler, const QStr m_miniBuffer->setContents(contents, cursorPos, anchorPos, messageLevel, handler); } -void FakeVimPluginPrivate::showExtraInformation(FakeVimHandler *, const QString &text) -{ - EditorManager::splitSideBySide(); - QString title = "stdout.txt"; - IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8()); - EditorManager::activateEditor(iedit); - FakeVimHandler *handler = m_editorToHandler.value(iedit, 0); - QTC_ASSERT(handler, return); - handler->handleCommand("0"); -} - -void FakeVimPluginPrivate::changeSelection(FakeVimHandler *handler, const QList<QTextEdit::ExtraSelection> &selection) -{ - QTC_ASSERT(handler, return); - if (TextEditorWidget *bt = qobject_cast<TextEditorWidget *>(handler->widget())) - bt->setExtraSelections(TextEditorWidget::FakeVimSelection, selection); -} - -void FakeVimPluginPrivate::highlightMatches(FakeVimHandler *, const QString &needle) -{ - foreach (IEditor *editor, EditorManager::visibleEditors()) { - QWidget *w = editor->widget(); - IFindSupport *find = Aggregation::query<IFindSupport>(w); - if (find != 0) - find->highlightAll(needle, FindRegularExpression | FindCaseSensitively); - } -} - int FakeVimPluginPrivate::currentFile() const { IEditor *editor = EditorManager::currentEditor(); |