forked from qt-creator/qt-creator
FakeVim: Experiment with hand-written signals
Change-Id: If76c68d3abb42240a279c15cf4b3d4b9e04460bd Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -1872,7 +1872,7 @@ public:
|
|||||||
m_cursor.movePosition(Right, KeepAnchor, n);
|
m_cursor.movePosition(Right, KeepAnchor, n);
|
||||||
}
|
}
|
||||||
if (atEndOfLine())
|
if (atEndOfLine())
|
||||||
emit q->fold(q, 1, false);
|
q->fold(1, false);
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
}
|
}
|
||||||
void moveLeft(int n = 1) {
|
void moveLeft(int n = 1) {
|
||||||
@@ -2516,7 +2516,7 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
|
|||||||
//m_tc = m_cursor;
|
//m_tc = m_cursor;
|
||||||
|
|
||||||
//bool hasBlock = false;
|
//bool hasBlock = false;
|
||||||
//emit q->requestHasBlockSelection(&hasBlock);
|
//q->requestHasBlockSelection(&hasBlock);
|
||||||
//qDebug() << "IMPORT BLOCK 2:" << hasBlock;
|
//qDebug() << "IMPORT BLOCK 2:" << hasBlock;
|
||||||
|
|
||||||
//if (0 && hasBlock) {
|
//if (0 && hasBlock) {
|
||||||
@@ -3189,9 +3189,9 @@ void FakeVimHandler::Private::commitCursor()
|
|||||||
updateCursorShape();
|
updateCursorShape();
|
||||||
|
|
||||||
if (isVisualBlockMode()) {
|
if (isVisualBlockMode()) {
|
||||||
emit q->requestSetBlockSelection(q, tc);
|
q->requestSetBlockSelection(tc);
|
||||||
} else {
|
} else {
|
||||||
emit q->requestDisableBlockSelection(q);
|
q->requestDisableBlockSelection();
|
||||||
if (editor())
|
if (editor())
|
||||||
EDITOR(setTextCursor(tc));
|
EDITOR(setTextCursor(tc));
|
||||||
}
|
}
|
||||||
@@ -3207,10 +3207,10 @@ void FakeVimHandler::Private::pullCursor()
|
|||||||
QTextCursor oldCursor = m_cursor;
|
QTextCursor oldCursor = m_cursor;
|
||||||
|
|
||||||
bool visualBlockMode = false;
|
bool visualBlockMode = false;
|
||||||
emit q->requestHasBlockSelection(q, &visualBlockMode);
|
q->requestHasBlockSelection(&visualBlockMode);
|
||||||
|
|
||||||
if (visualBlockMode)
|
if (visualBlockMode)
|
||||||
q->requestBlockSelection(q, &m_cursor);
|
q->requestBlockSelection(&m_cursor);
|
||||||
else if (editor())
|
else if (editor())
|
||||||
m_cursor = editorCursor();
|
m_cursor = editorCursor();
|
||||||
|
|
||||||
@@ -3327,7 +3327,7 @@ void FakeVimHandler::Private::moveToEndOfLineVisually(QTextCursor *tc)
|
|||||||
|
|
||||||
void FakeVimHandler::Private::moveBehindEndOfLine()
|
void FakeVimHandler::Private::moveBehindEndOfLine()
|
||||||
{
|
{
|
||||||
emit q->fold(q, 1, false);
|
q->fold(1, false);
|
||||||
int pos = qMin(block().position() + block().length() - 1,
|
int pos = qMin(block().position() + block().length() - 1,
|
||||||
lastPositionInDocument() + 1);
|
lastPositionInDocument() + 1);
|
||||||
setPosition(pos);
|
setPosition(pos);
|
||||||
@@ -3601,7 +3601,7 @@ void FakeVimHandler::Private::updateSelection()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//qDebug() << "SELECTION: " << selections;
|
//qDebug() << "SELECTION: " << selections;
|
||||||
emit q->selectionChanged(q, selections);
|
q->selectionChanged(selections);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::updateHighlights()
|
void FakeVimHandler::Private::updateHighlights()
|
||||||
@@ -3616,7 +3616,7 @@ void FakeVimHandler::Private::updateHighlights()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit q->highlightMatches(q, m_highlighted);
|
q->highlightMatches(m_highlighted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::updateMiniBuffer()
|
void FakeVimHandler::Private::updateMiniBuffer()
|
||||||
@@ -3684,7 +3684,7 @@ void FakeVimHandler::Private::updateMiniBuffer()
|
|||||||
if (g.isRecording && msg.startsWith("--"))
|
if (g.isRecording && msg.startsWith("--"))
|
||||||
msg.append(' ').append("Recording");
|
msg.append(' ').append("Recording");
|
||||||
|
|
||||||
emit q->commandBufferChanged(q, msg, cursorPos, anchorPos, messageLevel);
|
q->commandBufferChanged(msg, cursorPos, anchorPos, messageLevel);
|
||||||
|
|
||||||
int linesInDoc = linesInDocument();
|
int linesInDoc = linesInDocument();
|
||||||
int l = cursorLine();
|
int l = cursorLine();
|
||||||
@@ -3696,7 +3696,7 @@ void FakeVimHandler::Private::updateMiniBuffer()
|
|||||||
status = Tr::tr("%1%2%").arg(pos, -10).arg(l * 100 / linesInDoc, 4);
|
status = Tr::tr("%1%2%").arg(pos, -10).arg(l * 100 / linesInDoc, 4);
|
||||||
else
|
else
|
||||||
status = Tr::tr("%1All").arg(pos, -10);
|
status = Tr::tr("%1All").arg(pos, -10);
|
||||||
emit q->statusDataChanged(q, status);
|
q->statusDataChanged(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::showMessage(MessageLevel level, const QString &msg)
|
void FakeVimHandler::Private::showMessage(MessageLevel level, const QString &msg)
|
||||||
@@ -3778,7 +3778,7 @@ bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input)
|
|||||||
handled = false;
|
handled = false;
|
||||||
if (input.is('j') || input.is('k')) {
|
if (input.is('j') || input.is('k')) {
|
||||||
int pos = position();
|
int pos = position();
|
||||||
emit q->foldGoTo(q, input.is('j') ? count() : -count(), false);
|
q->foldGoTo(input.is('j') ? count() : -count(), false);
|
||||||
if (pos != position()) {
|
if (pos != position()) {
|
||||||
handled = true;
|
handled = true;
|
||||||
finishMovement(QString("%1z%2")
|
finishMovement(QString("%1z%2")
|
||||||
@@ -3805,7 +3805,7 @@ bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input)
|
|||||||
else if (input.is(']') && g.subsubmode == CloseSquareSubSubMode)
|
else if (input.is(']') && g.subsubmode == CloseSquareSubSubMode)
|
||||||
bracketSearchForward(&m_cursor, "^\\{", count(), g.submode != NoSubMode);
|
bracketSearchForward(&m_cursor, "^\\{", count(), g.submode != NoSubMode);
|
||||||
else if (input.is('z'))
|
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();
|
handled = pos != position();
|
||||||
if (handled) {
|
if (handled) {
|
||||||
if (lineForPosition(pos) != lineForPosition(position()))
|
if (lineForPosition(pos) != lineForPosition(position()))
|
||||||
@@ -3872,7 +3872,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input)
|
|||||||
m_findStartPosition = position();
|
m_findStartPosition = position();
|
||||||
g.movetype = MoveExclusive;
|
g.movetype = MoveExclusive;
|
||||||
setAnchor(); // clear selection: otherwise, search is restricted to selection
|
setAnchor(); // clear selection: otherwise, search is restricted to selection
|
||||||
emit q->findRequested(q, !g.lastSearchForward);
|
q->findRequested(!g.lastSearchForward);
|
||||||
} else {
|
} else {
|
||||||
// FIXME: make core find dialog sufficiently flexible to
|
// FIXME: make core find dialog sufficiently flexible to
|
||||||
// produce the "default vi" behaviour too. For now, roll our own.
|
// 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)) {
|
if (hasConfig(ConfigUseCoreSearch)) {
|
||||||
bool forward = (input.is('n')) ? g.lastSearchForward : !g.lastSearchForward;
|
bool forward = (input.is('n')) ? g.lastSearchForward : !g.lastSearchForward;
|
||||||
int pos = position();
|
int pos = position();
|
||||||
emit q->findNextRequested(q, !forward);
|
q->findNextRequested(!forward);
|
||||||
if (forward && pos == m_cursor.selectionStart()) {
|
if (forward && pos == m_cursor.selectionStart()) {
|
||||||
// if cursor is already positioned at the start of a find result, this is returned
|
// 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());
|
setPosition(m_cursor.selectionStart());
|
||||||
} else {
|
} else {
|
||||||
@@ -4385,7 +4385,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
if (block().blockNumber() > 0) {
|
if (block().blockNumber() > 0) {
|
||||||
moveUp();
|
moveUp();
|
||||||
if (line != lineNumber(block()))
|
if (line != lineNumber(block()))
|
||||||
emit q->fold(q, 1, true);
|
q->fold(1, true);
|
||||||
moveDown();
|
moveDown();
|
||||||
}
|
}
|
||||||
} else if (input.isControl('o')) {
|
} else if (input.isControl('o')) {
|
||||||
@@ -4662,7 +4662,7 @@ bool FakeVimHandler::Private::handleWindowSubMode(const Input &input)
|
|||||||
|
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
leaveCurrentMode();
|
leaveCurrentMode();
|
||||||
emit q->windowCommandRequested(q, input.toString(), count());
|
q->windowCommandRequested(input.toString(), count());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -4688,21 +4688,21 @@ bool FakeVimHandler::Private::handleZSubMode(const Input &input)
|
|||||||
} else if (input.is('o') || input.is('c')) {
|
} else if (input.is('o') || input.is('c')) {
|
||||||
// Open/close current fold.
|
// Open/close current fold.
|
||||||
foldMaybeClosed = input.is('c');
|
foldMaybeClosed = input.is('c');
|
||||||
emit q->fold(q, count(), foldMaybeClosed);
|
q->fold(count(), foldMaybeClosed);
|
||||||
} else if (input.is('O') || input.is('C')) {
|
} else if (input.is('O') || input.is('C')) {
|
||||||
// Recursively open/close current fold.
|
// Recursively open/close current fold.
|
||||||
foldMaybeClosed = input.is('C');
|
foldMaybeClosed = input.is('C');
|
||||||
emit q->fold(q, -1, foldMaybeClosed);
|
q->fold(-1, foldMaybeClosed);
|
||||||
} else if (input.is('a') || input.is('A')) {
|
} else if (input.is('a') || input.is('A')) {
|
||||||
// Toggle current fold.
|
// Toggle current fold.
|
||||||
foldMaybeClosed = true;
|
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')) {
|
} else if (input.is('R') || input.is('M')) {
|
||||||
// Open/close all folds in document.
|
// Open/close all folds in document.
|
||||||
foldMaybeClosed = input.is('M');
|
foldMaybeClosed = input.is('M');
|
||||||
emit q->foldAll(q, foldMaybeClosed);
|
q->foldAll(foldMaybeClosed);
|
||||||
} else if (input.is('j') || input.is('k')) {
|
} 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 {
|
} else {
|
||||||
handled = false;
|
handled = false;
|
||||||
}
|
}
|
||||||
@@ -5081,7 +5081,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
moveToNextWordStart(1, false, false);
|
moveToNextWordStart(1, false, false);
|
||||||
QString str = selectText(Range(position(), tc.position()));
|
QString str = selectText(Range(position(), tc.position()));
|
||||||
m_cursor = tc;
|
m_cursor = tc;
|
||||||
emit q->simpleCompletionRequested(q, str, input.isControl('n'));
|
q->simpleCompletionRequested(str, input.isControl('n'));
|
||||||
} else if (input.isShift(Qt::Key_Insert)) {
|
} else if (input.isShift(Qt::Key_Insert)) {
|
||||||
// Insert text from clipboard.
|
// Insert text from clipboard.
|
||||||
QClipboard *clipboard = QApplication::clipboard();
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
@@ -5568,7 +5568,7 @@ bool FakeVimHandler::Private::handleExTabNextCommand(const ExCommand &cmd)
|
|||||||
if (!cmd.matches("tabn", "tabnext"))
|
if (!cmd.matches("tabn", "tabnext"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
emit q->tabNextRequested(q);
|
q->tabNextRequested();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5577,7 +5577,7 @@ bool FakeVimHandler::Private::handleExTabPreviousCommand(const ExCommand &cmd)
|
|||||||
if (!cmd.matches("tabp", "tabprevious"))
|
if (!cmd.matches("tabp", "tabprevious"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
emit q->tabPreviousRequested(q);
|
q->tabPreviousRequested();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5688,7 +5688,7 @@ bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd)
|
|||||||
++i;
|
++i;
|
||||||
info += QString("%1 %2\n").arg(i, -8).arg(item);
|
info += QString("%1 %2\n").arg(i, -8).arg(item);
|
||||||
}
|
}
|
||||||
emit q->extraInformationChanged(q, info);
|
q->extraInformationChanged(info);
|
||||||
} else {
|
} else {
|
||||||
notImplementedYet();
|
notImplementedYet();
|
||||||
}
|
}
|
||||||
@@ -5718,7 +5718,7 @@ bool FakeVimHandler::Private::handleExRegisterCommand(const ExCommand &cmd)
|
|||||||
QString value = quoteUnprintable(registerContents(reg));
|
QString value = quoteUnprintable(registerContents(reg));
|
||||||
info += QString("\"%1 %2\n").arg(reg).arg(value);
|
info += QString("\"%1 %2\n").arg(reg).arg(value);
|
||||||
}
|
}
|
||||||
emit q->extraInformationChanged(q, info);
|
q->extraInformationChanged(info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -6037,7 +6037,7 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :!
|
|||||||
showMessage(MessageInfo, Tr::tr("%n lines filtered.", 0,
|
showMessage(MessageInfo, Tr::tr("%n lines filtered.", 0,
|
||||||
input.count('\n')));
|
input.count('\n')));
|
||||||
} else if (!result.isEmpty()) {
|
} else if (!result.isEmpty()) {
|
||||||
emit q->extraInformationChanged(q, result);
|
q->extraInformationChanged(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -6243,7 +6243,7 @@ bool FakeVimHandler::Private::handleExPluginCommand(const ExCommand &cmd)
|
|||||||
bool handled = false;
|
bool handled = false;
|
||||||
int pos = m_cursor.position();
|
int pos = m_cursor.position();
|
||||||
commitCursor();
|
commitCursor();
|
||||||
emit q->handleExCommandRequested(q, &handled, cmd);
|
q->handleExCommandRequested(&handled, cmd);
|
||||||
//qDebug() << "HANDLER REQUEST: " << cmd.cmd << handled;
|
//qDebug() << "HANDLER REQUEST: " << cmd.cmd << handled;
|
||||||
if (handled && (m_textedit || m_plaintextedit)) {
|
if (handled && (m_textedit || m_plaintextedit)) {
|
||||||
pullCursor();
|
pullCursor();
|
||||||
@@ -6457,14 +6457,14 @@ void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar)
|
|||||||
|
|
||||||
// Don't remember current indentation in last text insertion.
|
// Don't remember current indentation in last text insertion.
|
||||||
const QString lastInsertion = m_buffer->lastInsertion;
|
const QString lastInsertion = m_buffer->lastInsertion;
|
||||||
emit q->indentRegion(q, beginBlock, endBlock, typedChar);
|
q->indentRegion(beginBlock, endBlock, typedChar);
|
||||||
m_buffer->lastInsertion = lastInsertion;
|
m_buffer->lastInsertion = lastInsertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::isElectricCharacter(QChar c) const
|
bool FakeVimHandler::Private::isElectricCharacter(QChar c) const
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
emit q->checkForElectricCharacter(q, &result, c);
|
q->checkForElectricCharacter(&result, c);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6588,7 +6588,7 @@ void FakeVimHandler::Private::miniBufferTextEdited(const QString &text, int curs
|
|||||||
// update command/search buffer
|
// update command/search buffer
|
||||||
cmdBuf.setContents(buffer.mid(1), pos - 1, anchor - 1);
|
cmdBuf.setContents(buffer.mid(1), pos - 1, anchor - 1);
|
||||||
if (pos != cursorPos || anchor != anchorPos || buffer != text)
|
if (pos != cursorPos || anchor != anchorPos || buffer != text)
|
||||||
emit q->commandBufferChanged(q, buffer, pos, anchor, 0);
|
q->commandBufferChanged(buffer, pos, anchor, 0);
|
||||||
// update search expression
|
// update search expression
|
||||||
if (g.subsubmode == SearchSubSubMode) {
|
if (g.subsubmode == SearchSubSubMode) {
|
||||||
updateFind(false);
|
updateFind(false);
|
||||||
@@ -6775,7 +6775,7 @@ void FakeVimHandler::Private::moveToMatchingParanthesis()
|
|||||||
if (tc.atBlockEnd())
|
if (tc.atBlockEnd())
|
||||||
tc = m_cursor;
|
tc = m_cursor;
|
||||||
|
|
||||||
emit q->moveToMatchingParenthesis(q, &moved, &forward, &tc);
|
q->moveToMatchingParenthesis(&moved, &forward, &tc);
|
||||||
if (moved) {
|
if (moved) {
|
||||||
if (forward)
|
if (forward)
|
||||||
tc.movePosition(Left, KeepAnchor, 1);
|
tc.movePosition(Left, KeepAnchor, 1);
|
||||||
@@ -7342,7 +7342,7 @@ bool FakeVimHandler::Private::handleInsertInEditor(const Input &input)
|
|||||||
bool FakeVimHandler::Private::passEventToEditor(QEvent &event, QTextCursor &tc)
|
bool FakeVimHandler::Private::passEventToEditor(QEvent &event, QTextCursor &tc)
|
||||||
{
|
{
|
||||||
removeEventFilter();
|
removeEventFilter();
|
||||||
emit q->requestDisableBlockSelection(q);
|
q->requestDisableBlockSelection();
|
||||||
|
|
||||||
setThinCursor();
|
setThinCursor();
|
||||||
EDITOR(setTextCursor(tc));
|
EDITOR(setTextCursor(tc));
|
||||||
@@ -7685,7 +7685,7 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!m_highlighted.isEmpty())
|
if (!m_highlighted.isEmpty())
|
||||||
emit q->highlightMatches(q, m_highlighted);
|
q->highlightMatches(m_highlighted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::onCursorPositionChanged()
|
void FakeVimHandler::Private::onCursorPositionChanged()
|
||||||
@@ -8451,7 +8451,7 @@ bool FakeVimHandler::Private::jumpToMark(QChar mark, bool backTickMode)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m.isLocal(m_currentFileName)) {
|
if (!m.isLocal(m_currentFileName)) {
|
||||||
emit q->jumpToGlobalMark(q, mark, backTickMode, m.fileName());
|
q->requestJumpToGlobalMark(mark, backTickMode, m.fileName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8633,7 +8633,7 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev)
|
|||||||
KEY_DEBUG("KEYPRESS" << kev->key() << kev->text() << QChar(kev->key()));
|
KEY_DEBUG("KEYPRESS" << kev->key() << kev->text() << QChar(kev->key()));
|
||||||
EventResult res = d->handleEvent(kev);
|
EventResult res = d->handleEvent(kev);
|
||||||
//if (Private::g.mode == InsertMode)
|
//if (Private::g.mode == InsertMode)
|
||||||
// emit completionRequested();
|
// completionRequested();
|
||||||
// returning false core the app see it
|
// returning false core the app see it
|
||||||
//KEY_DEBUG("HANDLED CODE:" << res);
|
//KEY_DEBUG("HANDLED CODE:" << res);
|
||||||
//return res != EventPassedToCore;
|
//return res != EventPassedToCore;
|
||||||
|
|||||||
@@ -28,6 +28,9 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace FakeVim {
|
namespace FakeVim {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -80,6 +83,25 @@ enum MessageLevel
|
|||||||
MessageShowCmd // partial command
|
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
|
class FakeVimHandler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -131,34 +153,33 @@ public:
|
|||||||
|
|
||||||
bool eventFilter(QObject *ob, QEvent *ev);
|
bool eventFilter(QObject *ob, QEvent *ev);
|
||||||
|
|
||||||
signals:
|
Signal<void(const QString &msg, int cursorPos, int anchorPos, int messageLevel)> commandBufferChanged;
|
||||||
void commandBufferChanged(FakeVimHandler *self, const QString &msg, int cursorPos, int anchorPos,
|
Signal<void(const QString &msg)> statusDataChanged;
|
||||||
int messageLevel);
|
Signal<void(const QString &msg)> extraInformationChanged;
|
||||||
void statusDataChanged(FakeVimHandler *self, const QString &msg);
|
Signal<void(const QList<QTextEdit::ExtraSelection> &selection)> selectionChanged;
|
||||||
void extraInformationChanged(FakeVimHandler *self, const QString &msg);
|
Signal<void(const QString &needle)> highlightMatches;
|
||||||
void selectionChanged(FakeVimHandler *self, const QList<QTextEdit::ExtraSelection> &selection);
|
Signal<void(QString *error)> writeAllRequested;
|
||||||
void highlightMatches(FakeVimHandler *self, const QString &needle);
|
Signal<void(bool *moved, bool *forward, QTextCursor *cursor)> moveToMatchingParenthesis;
|
||||||
void writeAllRequested(FakeVimHandler *self, QString *error);
|
Signal<void(bool *result, QChar c)> checkForElectricCharacter;
|
||||||
void moveToMatchingParenthesis(FakeVimHandler *self, bool *moved, bool *forward, QTextCursor *cursor);
|
Signal<void(int beginLine, int endLine, QChar typedChar)> indentRegion;
|
||||||
void checkForElectricCharacter(FakeVimHandler *self, bool *result, QChar c);
|
Signal<void(const QString &needle, bool forward)> simpleCompletionRequested;
|
||||||
void indentRegion(FakeVimHandler *self, int beginLine, int endLine, QChar typedChar);
|
Signal<void(const QString &key, int count)> windowCommandRequested;
|
||||||
void completionRequested(FakeVimHandler *self);
|
Signal<void(bool reverse)> findRequested;
|
||||||
void simpleCompletionRequested(FakeVimHandler *self, const QString &needle, bool forward);
|
Signal<void(bool reverse)> findNextRequested;
|
||||||
void windowCommandRequested(FakeVimHandler *self, const QString &key, int count);
|
Signal<void(bool *handled, const ExCommand &cmd)> handleExCommandRequested;
|
||||||
void findRequested(FakeVimHandler *self, bool reverse);
|
Signal<void()> requestDisableBlockSelection;
|
||||||
void findNextRequested(FakeVimHandler *self, bool reverse);
|
Signal<void(const QTextCursor &cursor)> requestSetBlockSelection;
|
||||||
void handleExCommandRequested(FakeVimHandler *self, bool *handled, const ExCommand &cmd);
|
Signal<void(QTextCursor *cursor)> requestBlockSelection;
|
||||||
void requestDisableBlockSelection(FakeVimHandler *self);
|
Signal<void(bool *on)> requestHasBlockSelection;
|
||||||
void requestSetBlockSelection(FakeVimHandler *self, const QTextCursor &cursor);
|
Signal<void(int depth)> foldToggle;
|
||||||
void requestBlockSelection(FakeVimHandler *self, QTextCursor *cursor);
|
Signal<void(bool fold)> foldAll;
|
||||||
void requestHasBlockSelection(FakeVimHandler *self, bool *on);
|
Signal<void(int depth, bool dofold)> fold;
|
||||||
void foldToggle(FakeVimHandler *self, int depth);
|
Signal<void(int count, bool current)> foldGoTo;
|
||||||
void foldAll(FakeVimHandler *self, bool fold);
|
Signal<void(QChar mark, bool backTickMode, const QString &fileName)> requestJumpToLocalMark;
|
||||||
void fold(FakeVimHandler *self, int depth, bool fold);
|
Signal<void(QChar mark, bool backTickMode, const QString &fileName)> requestJumpToGlobalMark;
|
||||||
void foldGoTo(FakeVimHandler *self, int count, bool current);
|
Signal<void()> completionRequested;
|
||||||
void jumpToGlobalMark(FakeVimHandler *handler, QChar mark, bool backTickMode, const QString &fileName);
|
Signal<void()> tabPreviousRequested;
|
||||||
void tabNextRequested(FakeVimHandler *self);
|
Signal<void()> tabNextRequested;
|
||||||
void tabPreviousRequested(FakeVimHandler *self);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Private;
|
class Private;
|
||||||
|
|||||||
@@ -97,6 +97,8 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
@@ -524,32 +526,13 @@ public:
|
|||||||
void setUseFakeVim(const QVariant &value);
|
void setUseFakeVim(const QVariant &value);
|
||||||
void setUseFakeVimInternal(bool on);
|
void setUseFakeVimInternal(bool on);
|
||||||
void quitFakeVim();
|
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 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 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 setShowRelativeLineNumbers(const QVariant &value);
|
||||||
|
|
||||||
void resetCommandBuffer();
|
void resetCommandBuffer();
|
||||||
void showCommandBuffer(FakeVimHandler *handler, const QString &contents,
|
void showCommandBuffer(FakeVimHandler *handler, const QString &contents,
|
||||||
int cursorPos, int anchorPos, int messageLevel);
|
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 handleExCommand(FakeVimHandler *handler, bool *handled, const ExCommand &cmd);
|
||||||
|
|
||||||
void writeSettings();
|
void writeSettings();
|
||||||
@@ -571,7 +554,6 @@ signals:
|
|||||||
public:
|
public:
|
||||||
QHash<IEditor *, FakeVimHandler *> m_editorToHandler;
|
QHash<IEditor *, FakeVimHandler *> m_editorToHandler;
|
||||||
|
|
||||||
void triggerAction(Id id);
|
|
||||||
void setActionChecked(Id id, bool check);
|
void setActionChecked(Id id, bool check);
|
||||||
|
|
||||||
typedef int (*DistFunction)(const QRect &cursor, const QRect &other);
|
typedef int (*DistFunction)(const QRect &cursor, const QRect &other);
|
||||||
@@ -1344,7 +1326,7 @@ void FakeVimPluginPrivate::maybeReadVimRc()
|
|||||||
//qDebug() << theFakeVimSetting(ConfigShiftWidth)->value();
|
//qDebug() << theFakeVimSetting(ConfigShiftWidth)->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimPluginPrivate::triggerAction(Id id)
|
static void triggerAction(Id id)
|
||||||
{
|
{
|
||||||
Command *cmd = ActionManager::command(id);
|
Command *cmd = ActionManager::command(id);
|
||||||
QTC_ASSERT(cmd, qDebug() << "UNKNOWN CODE: " << id.name(); return);
|
QTC_ASSERT(cmd, qDebug() << "UNKNOWN CODE: " << id.name(); return);
|
||||||
@@ -1404,37 +1386,6 @@ static int moveDownWeight(const QRect &cursor, const QRect &other)
|
|||||||
return w;
|
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)
|
void FakeVimPluginPrivate::moveSomewhere(FakeVimHandler *handler, DistFunction f, int count)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(handler, return);
|
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)
|
void FakeVimPluginPrivate::fold(FakeVimHandler *handler, int depth, bool fold)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(handler, return);
|
QTC_ASSERT(handler, return);
|
||||||
@@ -1583,9 +1495,239 @@ void FakeVimPluginPrivate::fold(FakeVimHandler *handler, int depth, bool fold)
|
|||||||
documentLayout->emitDocumentSizeChanged();
|
documentLayout->emitDocumentSizeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimPluginPrivate::foldGoTo(FakeVimHandler *handler, int count, bool current)
|
// This class defers deletion of a child FakeVimHandler using deleteLater().
|
||||||
|
class DeferredDeleter : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
FakeVimHandler *m_handler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeferredDeleter(QObject *parent, FakeVimHandler *handler)
|
||||||
|
: QObject(parent), m_handler(handler)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~DeferredDeleter()
|
||||||
|
{
|
||||||
|
if (m_handler) {
|
||||||
|
m_handler->disconnectFromEditor();
|
||||||
|
m_handler->deleteLater();
|
||||||
|
m_handler = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
||||||
|
{
|
||||||
|
if (!editor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QWidget *widget = editor->widget();
|
||||||
|
if (!widget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// we can only handle QTextEdit and QPlainTextEdit
|
||||||
|
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();
|
||||||
|
|
||||||
|
auto handler = new FakeVimHandler(widget, 0);
|
||||||
|
// the handler might have triggered the deletion of the editor:
|
||||||
|
// make sure that it can return before being deleted itself
|
||||||
|
new DeferredDeleter(widget, handler);
|
||||||
|
m_editorToHandler[editor] = handler;
|
||||||
|
|
||||||
|
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);
|
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();
|
QTextCursor tc = handler->textCursor();
|
||||||
QTextBlock block = tc.block();
|
QTextBlock block = tc.block();
|
||||||
|
|
||||||
@@ -1635,116 +1777,35 @@ void FakeVimPluginPrivate::foldGoTo(FakeVimHandler *handler, int count, bool cur
|
|||||||
tc.setPosition(pos, QTextCursor::KeepAnchor);
|
tc.setPosition(pos, QTextCursor::KeepAnchor);
|
||||||
handler->setTextCursor(tc);
|
handler->setTextCursor(tc);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
void FakeVimPluginPrivate::jumpToGlobalMark(FakeVimHandler *,
|
handler->requestJumpToGlobalMark.connect([this](QChar mark, bool backTickMode, const QString &fileName) {
|
||||||
QChar mark, bool backTickMode, const QString &fileName)
|
if (IEditor *iedit = EditorManager::openEditor(fileName)) {
|
||||||
{
|
if (FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr))
|
||||||
IEditor *iedit = EditorManager::openEditor(fileName);
|
|
||||||
if (!iedit)
|
|
||||||
return;
|
|
||||||
FakeVimHandler *handler = m_editorToHandler.value(iedit, nullptr);
|
|
||||||
if (handler)
|
|
||||||
handler->jumpToLocalMark(mark, backTickMode);
|
handler->jumpToLocalMark(mark, backTickMode);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// This class defers deletion of a child FakeVimHandler using deleteLater().
|
handler->handleExCommandRequested.connect([this, handler](bool *handled, const ExCommand &cmd) {
|
||||||
class DeferredDeleter : public QObject
|
handleExCommand(handler, handled, cmd);
|
||||||
{
|
});
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
FakeVimHandler *m_handler;
|
handler->tabNextRequested.connect([this] {
|
||||||
|
triggerAction(Core::Constants::GOTONEXTINHISTORY);
|
||||||
|
});
|
||||||
|
|
||||||
public:
|
handler->tabPreviousRequested.connect([this] {
|
||||||
DeferredDeleter(QObject *parent, FakeVimHandler *handler)
|
triggerAction(Core::Constants::GOTOPREVINHISTORY);
|
||||||
: QObject(parent), m_handler(handler)
|
});
|
||||||
{}
|
|
||||||
|
|
||||||
~DeferredDeleter()
|
handler->completionRequested.connect([this, tew] {
|
||||||
{
|
if (tew)
|
||||||
if (m_handler) {
|
tew->invokeAssist(Completion, &runData->wordProvider);
|
||||||
m_handler->disconnectFromEditor();
|
});
|
||||||
m_handler->deleteLater();
|
|
||||||
m_handler = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void FakeVimPluginPrivate::editorOpened(IEditor *editor)
|
|
||||||
{
|
|
||||||
if (!editor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QWidget *widget = editor->widget();
|
|
||||||
if (!widget)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// we can only handle QTextEdit and QPlainTextEdit
|
|
||||||
if (!qobject_cast<QTextEdit *>(widget) && !qobject_cast<QPlainTextEdit *>(widget))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//qDebug() << "OPENING: " << editor << editor->widget()
|
|
||||||
// << "MODE: " << theFakeVimSetting(ConfigUseFakeVim)->value();
|
|
||||||
|
|
||||||
auto handler = new FakeVimHandler(widget, 0);
|
|
||||||
// the handler might have triggered the deletion of the editor:
|
|
||||||
// make sure that it can return before being deleted itself
|
|
||||||
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);
|
|
||||||
|
|
||||||
connect(ICore::instance(), &ICore::saveSettingsRequested,
|
connect(ICore::instance(), &ICore::saveSettingsRequested,
|
||||||
this, &FakeVimPluginPrivate::writeSettings);
|
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->setCurrentFileName(editor->document()->filePath().toString());
|
||||||
handler->installEventFilter();
|
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)
|
void FakeVimPluginPrivate::setShowRelativeLineNumbers(const QVariant &value)
|
||||||
{
|
{
|
||||||
if (value.toBool() && theFakeVimSetting(ConfigUseFakeVim)->value().toBool()) {
|
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)
|
void FakeVimPluginPrivate::handleExCommand(FakeVimHandler *handler, bool *handled, const ExCommand &cmd)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(handler, return);
|
QTC_ASSERT(handler, return);
|
||||||
@@ -2001,78 +2012,6 @@ void FakeVimPluginPrivate::handleDelayedQuitAll(bool forced)
|
|||||||
EditorManager::closeAllEditors(!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()
|
void FakeVimPluginPrivate::quitFakeVim()
|
||||||
{
|
{
|
||||||
theFakeVimSetting(ConfigUseFakeVim)->setValue(false);
|
theFakeVimSetting(ConfigUseFakeVim)->setValue(false);
|
||||||
@@ -2091,34 +2030,6 @@ void FakeVimPluginPrivate::showCommandBuffer(FakeVimHandler *handler, const QStr
|
|||||||
m_miniBuffer->setContents(contents, cursorPos, anchorPos, messageLevel, handler);
|
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
|
int FakeVimPluginPrivate::currentFile() const
|
||||||
{
|
{
|
||||||
IEditor *editor = EditorManager::currentEditor();
|
IEditor *editor = EditorManager::currentEditor();
|
||||||
|
|||||||
@@ -74,33 +74,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Proxy : public QObject
|
static void highlightMatches(QWidget *widget, const QString &pattern)
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
Proxy(QMainWindow *mw)
|
|
||||||
: m_mainWindow(mw)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void changeSelection(FakeVimHandler *handler, const QList<QTextEdit::ExtraSelection> &s)
|
|
||||||
{
|
|
||||||
QWidget *widget = handler->widget();
|
|
||||||
if (auto ed = qobject_cast<QPlainTextEdit *>(widget))
|
|
||||||
ed->setExtraSelections(s);
|
|
||||||
else if (auto ed = qobject_cast<QTextEdit *>(widget))
|
|
||||||
ed->setExtraSelections(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeStatusData(FakeVimHandler *, const QString &info)
|
|
||||||
{
|
|
||||||
m_statusData = info;
|
|
||||||
updateStatusBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
void highlightMatches(FakeVimHandler *handler, const QString &pattern)
|
|
||||||
{
|
|
||||||
QWidget *widget = handler->widget();
|
|
||||||
auto ed = qobject_cast<QTextEdit *>(widget);
|
auto ed = qobject_cast<QTextEdit *>(widget);
|
||||||
if (!ed)
|
if (!ed)
|
||||||
return;
|
return;
|
||||||
@@ -137,42 +112,31 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeStatusMessage(FakeVimHandler *, const QString &contents, int cursorPos)
|
class StatusData
|
||||||
{
|
{
|
||||||
m_statusMessage = cursorPos == -1 ? contents
|
public:
|
||||||
: contents.left(cursorPos) + QChar(10073) + contents.mid(cursorPos);
|
void setStatusMessage(const QString &msg, int pos)
|
||||||
updateStatusBar();
|
{
|
||||||
|
m_statusMessage = pos == -1 ? msg : msg.left(pos) + QChar(10073) + msg.mid(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeExtraInformation(FakeVimHandler *handler, const QString &info)
|
void setStatusInfo(const QString &info)
|
||||||
{
|
{
|
||||||
QMessageBox::information(handler->widget(), tr("Information"), info);
|
m_statusData = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateStatusBar()
|
QString currentStatusLine() const
|
||||||
{
|
{
|
||||||
int slack = 80 - m_statusMessage.size() - m_statusData.size();
|
const int slack = 80 - m_statusMessage.size() - m_statusData.size();
|
||||||
QString msg = m_statusMessage + QString(slack, ' ') + m_statusData;
|
return m_statusMessage + QString(slack, ' ') + m_statusData;
|
||||||
m_mainWindow->statusBar()->showMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleExCommand(FakeVimHandler *, bool *handled, const ExCommand &cmd)
|
|
||||||
{
|
|
||||||
if (cmd.matches("q", "quit") || cmd.matches("qa", "qall")) {
|
|
||||||
QApplication::quit();
|
|
||||||
*handled = true;
|
|
||||||
} else {
|
|
||||||
*handled = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMainWindow *m_mainWindow;
|
|
||||||
QString m_statusMessage;
|
QString m_statusMessage;
|
||||||
QString m_statusData;
|
QString m_statusData;
|
||||||
};
|
};
|
||||||
|
|
||||||
QWidget *createEditorWidget(bool usePlainTextEdit)
|
static QWidget *createEditorWidget(bool usePlainTextEdit)
|
||||||
{
|
{
|
||||||
QWidget *editor = 0;
|
QWidget *editor = 0;
|
||||||
if (usePlainTextEdit)
|
if (usePlainTextEdit)
|
||||||
@@ -185,7 +149,7 @@ QWidget *createEditorWidget(bool usePlainTextEdit)
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initHandler(FakeVimHandler &handler)
|
static void initHandler(FakeVimHandler &handler)
|
||||||
{
|
{
|
||||||
// Set some Vim options.
|
// Set some Vim options.
|
||||||
handler.handleCommand("set expandtab");
|
handler.handleCommand("set expandtab");
|
||||||
@@ -200,7 +164,7 @@ void initHandler(FakeVimHandler &handler)
|
|||||||
handler.setupWidget();
|
handler.setupWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initMainWindow(QMainWindow &mainWindow, QWidget *centralWidget, const QString &title)
|
static void initMainWindow(QMainWindow &mainWindow, QWidget *centralWidget, const QString &title)
|
||||||
{
|
{
|
||||||
mainWindow.setWindowTitle(QString("FakeVim (%1)").arg(title));
|
mainWindow.setWindowTitle(QString("FakeVim (%1)").arg(title));
|
||||||
mainWindow.setCentralWidget(centralWidget);
|
mainWindow.setCentralWidget(centralWidget);
|
||||||
@@ -220,22 +184,6 @@ void readFile(FakeVimHandler &handler, const QString &editFileName)
|
|||||||
handler.handleCommand("r " + editFileName);
|
handler.handleCommand("r " + editFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void connectSignals(FakeVimHandler &handler, Proxy &proxy)
|
|
||||||
{
|
|
||||||
QObject::connect(&handler, &FakeVimHandler::commandBufferChanged,
|
|
||||||
&proxy, &Proxy::changeStatusMessage);
|
|
||||||
QObject::connect(&handler, &FakeVimHandler::selectionChanged,
|
|
||||||
&proxy, &Proxy::changeSelection);
|
|
||||||
QObject::connect(&handler, &FakeVimHandler::extraInformationChanged,
|
|
||||||
&proxy, &Proxy::changeExtraInformation);
|
|
||||||
QObject::connect(&handler, &FakeVimHandler::statusDataChanged,
|
|
||||||
&proxy, &Proxy::changeStatusData);
|
|
||||||
QObject::connect(&handler, &FakeVimHandler::highlightMatches,
|
|
||||||
&proxy, &Proxy::highlightMatches);
|
|
||||||
QObject::connect(&handler, &FakeVimHandler::handleExCommandRequested,
|
|
||||||
&proxy, &Proxy::handleExCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
@@ -250,16 +198,51 @@ int main(int argc, char *argv[])
|
|||||||
// Create editor widget.
|
// Create editor widget.
|
||||||
QWidget *editor = createEditorWidget(usePlainTextEdit);
|
QWidget *editor = createEditorWidget(usePlainTextEdit);
|
||||||
|
|
||||||
// Create FakeVimHandler instance which will emulate Vim behavior in editor widget.
|
|
||||||
FakeVimHandler handler(editor, nullptr);
|
|
||||||
|
|
||||||
// Create main window.
|
// Create main window.
|
||||||
QMainWindow mainWindow;
|
QMainWindow mainWindow;
|
||||||
initMainWindow(mainWindow, editor, usePlainTextEdit ? "QPlainTextEdit" : "QTextEdit");
|
initMainWindow(mainWindow, editor, usePlainTextEdit ? "QPlainTextEdit" : "QTextEdit");
|
||||||
|
|
||||||
// Connect slots to FakeVimHandler signals.
|
// Keep track of status line related data.
|
||||||
Proxy proxy(&mainWindow);
|
StatusData statusData;
|
||||||
connectSignals(handler, proxy);
|
|
||||||
|
// Create FakeVimHandler instance which will emulate Vim behavior in editor widget.
|
||||||
|
FakeVimHandler handler(editor, nullptr);
|
||||||
|
|
||||||
|
handler.commandBufferChanged.connect([&](const QString &msg, int cursorPos, int, int) {
|
||||||
|
statusData.setStatusMessage(msg, cursorPos);
|
||||||
|
mainWindow.statusBar()->showMessage(statusData.currentStatusLine());
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.selectionChanged.connect([&handler](const QList<QTextEdit::ExtraSelection> &s) {
|
||||||
|
QWidget *widget = handler.widget();
|
||||||
|
if (auto ed = qobject_cast<QPlainTextEdit *>(widget))
|
||||||
|
ed->setExtraSelections(s);
|
||||||
|
else if (auto ed = qobject_cast<QTextEdit *>(widget))
|
||||||
|
ed->setExtraSelections(s);
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.extraInformationChanged.connect([&](const QString &info) {
|
||||||
|
statusData.setStatusInfo(info);
|
||||||
|
mainWindow.statusBar()->showMessage(statusData.currentStatusLine());
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.statusDataChanged.connect([&](const QString &info) {
|
||||||
|
statusData.setStatusInfo(info);
|
||||||
|
mainWindow.statusBar()->showMessage(statusData.currentStatusLine());
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.highlightMatches.connect([&](const QString &needle) {
|
||||||
|
highlightMatches(handler.widget(), needle);
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.handleExCommandRequested.connect([](bool *handled, const ExCommand &cmd) {
|
||||||
|
if (cmd.matches("q", "quit") || cmd.matches("qa", "qall")) {
|
||||||
|
QApplication::quit();
|
||||||
|
*handled = true;
|
||||||
|
} else {
|
||||||
|
*handled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize FakeVimHandler.
|
// Initialize FakeVimHandler.
|
||||||
initHandler(handler);
|
initHandler(handler);
|
||||||
@@ -269,5 +252,3 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "main.moc"
|
|
||||||
|
|||||||
Reference in New Issue
Block a user