forked from qt-creator/qt-creator
FakeVim: Share some data among editors with same document
Task-number: QTCREATORBUG-12140 Change-Id: Ieabb331745395c7bb012c9c26ef18c14bcba7cc4 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -87,6 +87,7 @@
|
|||||||
#include <QTextDocumentFragment>
|
#include <QTextDocumentFragment>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
@@ -101,7 +102,7 @@
|
|||||||
|
|
||||||
//#define DEBUG_UNDO 1
|
//#define DEBUG_UNDO 1
|
||||||
#if DEBUG_UNDO
|
#if DEBUG_UNDO
|
||||||
# define UNDO_DEBUG(s) qDebug() << << revision() << s
|
# define UNDO_DEBUG(s) qDebug() << "REV" << revision() << s
|
||||||
#else
|
#else
|
||||||
# define UNDO_DEBUG(s)
|
# define UNDO_DEBUG(s)
|
||||||
#endif
|
#endif
|
||||||
@@ -279,6 +280,11 @@ struct CursorPosition
|
|||||||
int column; // Position on line.
|
int column; // Position on line.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug ts, const CursorPosition &pos)
|
||||||
|
{
|
||||||
|
return ts << "(line: " << pos.line << ", column: " << pos.column << ")";
|
||||||
|
}
|
||||||
|
|
||||||
class Mark
|
class Mark
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1831,12 +1837,11 @@ public:
|
|||||||
QChar characterAtCursor() const
|
QChar characterAtCursor() const
|
||||||
{ return document()->characterAt(position()); }
|
{ return document()->characterAt(position()); }
|
||||||
|
|
||||||
int m_editBlockLevel; // current level of edit blocks
|
|
||||||
void joinPreviousEditBlock();
|
void joinPreviousEditBlock();
|
||||||
void beginEditBlock(bool largeEditBlock = false);
|
void beginEditBlock(bool largeEditBlock = false);
|
||||||
void beginLargeEditBlock() { beginEditBlock(true); }
|
void beginLargeEditBlock() { beginEditBlock(true); }
|
||||||
void endEditBlock();
|
void endEditBlock();
|
||||||
void breakEditBlock() { m_breakEditBlock = true; }
|
void breakEditBlock() { m_buffer->breakEditBlock = true; }
|
||||||
|
|
||||||
Q_SLOT void onContentsChanged(int position, int charsRemoved, int charsAdded);
|
Q_SLOT void onContentsChanged(int position, int charsRemoved, int charsAdded);
|
||||||
Q_SLOT void onUndoCommandAdded();
|
Q_SLOT void onUndoCommandAdded();
|
||||||
@@ -1903,19 +1908,6 @@ public:
|
|||||||
int m_register;
|
int m_register;
|
||||||
BlockInsertMode m_visualBlockInsert;
|
BlockInsertMode m_visualBlockInsert;
|
||||||
|
|
||||||
// Insert state to get last inserted text.
|
|
||||||
struct InsertState {
|
|
||||||
int pos1;
|
|
||||||
int pos2;
|
|
||||||
int backspaces;
|
|
||||||
int deletes;
|
|
||||||
QSet<int> spaces;
|
|
||||||
bool insertingSpaces;
|
|
||||||
QString textBeforeCursor;
|
|
||||||
bool newLineBefore;
|
|
||||||
bool newLineAfter;
|
|
||||||
} m_insertState;
|
|
||||||
|
|
||||||
bool m_fakeEnd;
|
bool m_fakeEnd;
|
||||||
bool m_anchorPastEnd;
|
bool m_anchorPastEnd;
|
||||||
bool m_positionPastEnd; // '$' & 'l' in visual mode can move past eol
|
bool m_positionPastEnd; // '$' & 'l' in visual mode can move past eol
|
||||||
@@ -1923,9 +1915,6 @@ public:
|
|||||||
QString m_currentFileName;
|
QString m_currentFileName;
|
||||||
|
|
||||||
int m_findStartPosition;
|
int m_findStartPosition;
|
||||||
QString m_lastInsertion;
|
|
||||||
|
|
||||||
bool m_breakEditBlock;
|
|
||||||
|
|
||||||
int anchor() const { return m_cursor.anchor(); }
|
int anchor() const { return m_cursor.anchor(); }
|
||||||
int position() const { return m_cursor.position(); }
|
int position() const { return m_cursor.position(); }
|
||||||
@@ -1981,11 +1970,6 @@ public:
|
|||||||
void undo();
|
void undo();
|
||||||
void redo();
|
void redo();
|
||||||
void pushUndoState(bool overwrite = true);
|
void pushUndoState(bool overwrite = true);
|
||||||
// revision -> state
|
|
||||||
QStack<State> m_undo;
|
|
||||||
QStack<State> m_redo;
|
|
||||||
State m_undoState;
|
|
||||||
int m_lastRevision;
|
|
||||||
|
|
||||||
// extra data for '.'
|
// extra data for '.'
|
||||||
void replay(const QString &text, int repeat = 1);
|
void replay(const QString &text, int repeat = 1);
|
||||||
@@ -1996,8 +1980,6 @@ public:
|
|||||||
// visual modes
|
// visual modes
|
||||||
void toggleVisualMode(VisualMode visualMode);
|
void toggleVisualMode(VisualMode visualMode);
|
||||||
void leaveVisualMode();
|
void leaveVisualMode();
|
||||||
VisualMode m_lastVisualMode;
|
|
||||||
bool m_lastVisualModeInverted;
|
|
||||||
|
|
||||||
// marks
|
// marks
|
||||||
Mark mark(QChar code) const;
|
Mark mark(QChar code) const;
|
||||||
@@ -2006,7 +1988,6 @@ public:
|
|||||||
bool jumpToMark(QChar mark, bool backTickMode);
|
bool jumpToMark(QChar mark, bool backTickMode);
|
||||||
// update marks on undo/redo
|
// update marks on undo/redo
|
||||||
void updateMarks(const Marks &newMarks);
|
void updateMarks(const Marks &newMarks);
|
||||||
Marks m_marks; // local marks
|
|
||||||
CursorPosition markLessPosition() const { return mark(QLatin1Char('<')).position(document()); }
|
CursorPosition markLessPosition() const { return mark(QLatin1Char('<')).position(document()); }
|
||||||
CursorPosition markGreaterPosition() const { return mark(QLatin1Char('>')).position(document()); }
|
CursorPosition markGreaterPosition() const { return mark(QLatin1Char('>')).position(document()); }
|
||||||
|
|
||||||
@@ -2035,9 +2016,6 @@ public:
|
|||||||
|
|
||||||
void recordJump(int position = -1);
|
void recordJump(int position = -1);
|
||||||
void jump(int distance);
|
void jump(int distance);
|
||||||
QStack<CursorPosition> m_jumpListUndo;
|
|
||||||
QStack<CursorPosition> m_jumpListRedo;
|
|
||||||
CursorPosition m_lastChangePosition;
|
|
||||||
|
|
||||||
QList<QTextEdit::ExtraSelection> m_extraSelections;
|
QList<QTextEdit::ExtraSelection> m_extraSelections;
|
||||||
QTextCursor m_searchCursor;
|
QTextCursor m_searchCursor;
|
||||||
@@ -2079,6 +2057,54 @@ public:
|
|||||||
|
|
||||||
void miniBufferTextEdited(const QString &text, int cursorPos, int anchorPos);
|
void miniBufferTextEdited(const QString &text, int cursorPos, int anchorPos);
|
||||||
|
|
||||||
|
// Data shared among editors with same document.
|
||||||
|
struct BufferData
|
||||||
|
{
|
||||||
|
BufferData()
|
||||||
|
: lastRevision(0)
|
||||||
|
, editBlockLevel(0)
|
||||||
|
, breakEditBlock(false)
|
||||||
|
, lastVisualMode(NoVisualMode)
|
||||||
|
, lastVisualModeInverted(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QStack<State> undo;
|
||||||
|
QStack<State> redo;
|
||||||
|
State undoState;
|
||||||
|
int lastRevision;
|
||||||
|
|
||||||
|
int editBlockLevel; // current level of edit blocks
|
||||||
|
bool breakEditBlock; // if true, joinPreviousEditBlock() starts new edit block
|
||||||
|
|
||||||
|
QStack<CursorPosition> jumpListUndo;
|
||||||
|
QStack<CursorPosition> jumpListRedo;
|
||||||
|
CursorPosition lastChangePosition;
|
||||||
|
|
||||||
|
VisualMode lastVisualMode;
|
||||||
|
bool lastVisualModeInverted;
|
||||||
|
|
||||||
|
Marks marks;
|
||||||
|
|
||||||
|
// Insert state to get last inserted text.
|
||||||
|
struct InsertState {
|
||||||
|
int pos1;
|
||||||
|
int pos2;
|
||||||
|
int backspaces;
|
||||||
|
int deletes;
|
||||||
|
QSet<int> spaces;
|
||||||
|
bool insertingSpaces;
|
||||||
|
QString textBeforeCursor;
|
||||||
|
bool newLineBefore;
|
||||||
|
bool newLineAfter;
|
||||||
|
} insertState;
|
||||||
|
|
||||||
|
QString lastInsertion;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QSharedPointer<BufferData> BufferDataPtr;
|
||||||
|
void pullOrCreateBufferData();
|
||||||
|
BufferDataPtr m_buffer;
|
||||||
|
|
||||||
// Data shared among all editors.
|
// Data shared among all editors.
|
||||||
static struct GlobalData
|
static struct GlobalData
|
||||||
{
|
{
|
||||||
@@ -2191,7 +2217,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
|
|||||||
connect(EDITOR(document()), SIGNAL(contentsChange(int,int,int)),
|
connect(EDITOR(document()), SIGNAL(contentsChange(int,int,int)),
|
||||||
SLOT(onContentsChanged(int,int,int)));
|
SLOT(onContentsChanged(int,int,int)));
|
||||||
connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded()));
|
connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded()));
|
||||||
m_lastRevision = revision();
|
m_buffer->lastRevision = revision();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2204,8 +2230,6 @@ void FakeVimHandler::Private::init()
|
|||||||
m_positionPastEnd = false;
|
m_positionPastEnd = false;
|
||||||
m_anchorPastEnd = false;
|
m_anchorPastEnd = false;
|
||||||
m_register = '"';
|
m_register = '"';
|
||||||
m_lastVisualMode = NoVisualMode;
|
|
||||||
m_lastVisualModeInverted = false;
|
|
||||||
m_targetColumn = 0;
|
m_targetColumn = 0;
|
||||||
m_visualTargetColumn = 0;
|
m_visualTargetColumn = 0;
|
||||||
m_targetColumnWrapped = 0;
|
m_targetColumnWrapped = 0;
|
||||||
@@ -2213,16 +2237,14 @@ void FakeVimHandler::Private::init()
|
|||||||
m_oldInternalPosition = -1;
|
m_oldInternalPosition = -1;
|
||||||
m_oldExternalAnchor = -1;
|
m_oldExternalAnchor = -1;
|
||||||
m_oldExternalPosition = -1;
|
m_oldExternalPosition = -1;
|
||||||
m_insertState = InsertState();
|
|
||||||
m_breakEditBlock = false;
|
|
||||||
m_searchStartPosition = 0;
|
m_searchStartPosition = 0;
|
||||||
m_searchFromScreenLine = 0;
|
m_searchFromScreenLine = 0;
|
||||||
m_editBlockLevel = 0;
|
|
||||||
m_firstVisibleLine = 0;
|
m_firstVisibleLine = 0;
|
||||||
m_ctrlVAccumulator = 0;
|
m_ctrlVAccumulator = 0;
|
||||||
m_ctrlVLength = 0;
|
m_ctrlVLength = 0;
|
||||||
m_ctrlVBase = 0;
|
m_ctrlVBase = 0;
|
||||||
|
|
||||||
|
pullOrCreateBufferData();
|
||||||
setupCharClass();
|
setupCharClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2263,6 +2285,8 @@ void FakeVimHandler::Private::enterFakeVim()
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(!m_inFakeVim, qDebug() << "enterFakeVim() shouldn't be called recursively!"; return);
|
QTC_ASSERT(!m_inFakeVim, qDebug() << "enterFakeVim() shouldn't be called recursively!"; return);
|
||||||
|
|
||||||
|
pullOrCreateBufferData();
|
||||||
|
|
||||||
pullCursor();
|
pullCursor();
|
||||||
if (m_cursor.isNull())
|
if (m_cursor.isNull())
|
||||||
m_cursor = QTextCursor(document());
|
m_cursor = QTextCursor(document());
|
||||||
@@ -2525,57 +2549,61 @@ void FakeVimHandler::Private::commitInsertState()
|
|||||||
if (!isInsertStateValid())
|
if (!isInsertStateValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
QString &lastInsertion = m_buffer->lastInsertion;
|
||||||
|
BufferData::InsertState &insertState = m_buffer->insertState;
|
||||||
|
|
||||||
// Get raw inserted text.
|
// Get raw inserted text.
|
||||||
m_lastInsertion = textAt(m_insertState.pos1, m_insertState.pos2);
|
lastInsertion = textAt(insertState.pos1, insertState.pos2);
|
||||||
|
|
||||||
// Escape special characters and spaces inserted by user (not by auto-indentation).
|
// Escape special characters and spaces inserted by user (not by auto-indentation).
|
||||||
for (int i = m_lastInsertion.size() - 1; i >= 0; --i) {
|
for (int i = lastInsertion.size() - 1; i >= 0; --i) {
|
||||||
const int pos = m_insertState.pos1 + i;
|
const int pos = insertState.pos1 + i;
|
||||||
const ushort c = document()->characterAt(pos).unicode();
|
const ushort c = document()->characterAt(pos).unicode();
|
||||||
if (c == '<')
|
if (c == '<')
|
||||||
m_lastInsertion.replace(i, 1, _("<LT>"));
|
lastInsertion.replace(i, 1, _("<LT>"));
|
||||||
else if ((c == ' ' || c == '\t') && m_insertState.spaces.contains(pos))
|
else if ((c == ' ' || c == '\t') && insertState.spaces.contains(pos))
|
||||||
m_lastInsertion.replace(i, 1, _(c == ' ' ? "<SPACE>" : "<TAB>"));
|
lastInsertion.replace(i, 1, _(c == ' ' ? "<SPACE>" : "<TAB>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove unnecessary backspaces.
|
// Remove unnecessary backspaces.
|
||||||
while (m_insertState.backspaces > 0 && !m_lastInsertion.isEmpty() && m_lastInsertion[0].isSpace())
|
while (insertState.backspaces > 0 && !lastInsertion.isEmpty() && lastInsertion[0].isSpace())
|
||||||
--m_insertState.backspaces;
|
--insertState.backspaces;
|
||||||
|
|
||||||
// backspaces in front of inserted text
|
// backspaces in front of inserted text
|
||||||
m_lastInsertion.prepend(QString(_("<BS>")).repeated(m_insertState.backspaces));
|
lastInsertion.prepend(QString(_("<BS>")).repeated(insertState.backspaces));
|
||||||
// deletes after inserted text
|
// deletes after inserted text
|
||||||
m_lastInsertion.prepend(QString(_("<DELETE>")).repeated(m_insertState.deletes));
|
lastInsertion.prepend(QString(_("<DELETE>")).repeated(insertState.deletes));
|
||||||
|
|
||||||
// Remove indentation.
|
// Remove indentation.
|
||||||
m_lastInsertion.replace(QRegExp(_("(^|\n)[\\t ]+")), _("\\1"));
|
lastInsertion.replace(QRegExp(_("(^|\n)[\\t ]+")), _("\\1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::invalidateInsertState()
|
void FakeVimHandler::Private::invalidateInsertState()
|
||||||
{
|
{
|
||||||
m_oldInternalPosition = position();
|
m_oldInternalPosition = position();
|
||||||
m_insertState.pos1 = -1;
|
BufferData::InsertState &insertState = m_buffer->insertState;
|
||||||
m_insertState.pos2 = m_oldInternalPosition;
|
insertState.pos1 = -1;
|
||||||
m_insertState.backspaces = 0;
|
insertState.pos2 = m_oldInternalPosition;
|
||||||
m_insertState.deletes = 0;
|
insertState.backspaces = 0;
|
||||||
m_insertState.spaces.clear();
|
insertState.deletes = 0;
|
||||||
m_insertState.insertingSpaces = false;
|
insertState.spaces.clear();
|
||||||
m_insertState.textBeforeCursor = textAt(document()->findBlock(m_oldInternalPosition).position(),
|
insertState.insertingSpaces = false;
|
||||||
|
insertState.textBeforeCursor = textAt(document()->findBlock(m_oldInternalPosition).position(),
|
||||||
m_oldInternalPosition);
|
m_oldInternalPosition);
|
||||||
m_insertState.newLineBefore = false;
|
insertState.newLineBefore = false;
|
||||||
m_insertState.newLineAfter = false;
|
insertState.newLineAfter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::isInsertStateValid() const
|
bool FakeVimHandler::Private::isInsertStateValid() const
|
||||||
{
|
{
|
||||||
return m_insertState.pos1 != -1;
|
return m_buffer->insertState.pos1 != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::clearLastInsertion()
|
void FakeVimHandler::Private::clearLastInsertion()
|
||||||
{
|
{
|
||||||
invalidateInsertState();
|
invalidateInsertState();
|
||||||
m_lastInsertion.clear();
|
m_buffer->lastInsertion.clear();
|
||||||
m_insertState.pos1 = m_insertState.pos2;
|
m_buffer->insertState.pos1 = m_buffer->insertState.pos2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::ensureCursorVisible()
|
void FakeVimHandler::Private::ensureCursorVisible()
|
||||||
@@ -2634,7 +2662,7 @@ void FakeVimHandler::Private::importSelection()
|
|||||||
g.visualMode = VisualLineMode;
|
g.visualMode = VisualLineMode;
|
||||||
else
|
else
|
||||||
g.visualMode = VisualCharMode;
|
g.visualMode = VisualCharMode;
|
||||||
m_lastVisualMode = g.visualMode;
|
m_buffer->lastVisualMode = g.visualMode;
|
||||||
} else {
|
} else {
|
||||||
g.visualMode = NoVisualMode;
|
g.visualMode = NoVisualMode;
|
||||||
}
|
}
|
||||||
@@ -2767,7 +2795,7 @@ void FakeVimHandler::Private::prependMapping(const Inputs &inputs)
|
|||||||
g.commandBuffer.setHistoryAutoSave(false);
|
g.commandBuffer.setHistoryAutoSave(false);
|
||||||
|
|
||||||
// start new edit block (undo/redo) only if necessary
|
// start new edit block (undo/redo) only if necessary
|
||||||
bool editBlock = m_editBlockLevel == 0 && !(isInsertMode() && isInsertStateValid());
|
bool editBlock = m_buffer->editBlockLevel == 0 && !(isInsertMode() && isInsertStateValid());
|
||||||
if (editBlock)
|
if (editBlock)
|
||||||
beginLargeEditBlock();
|
beginLargeEditBlock();
|
||||||
g.mapStates << MappingState(inputs.noremap(), inputs.silent(), editBlock);
|
g.mapStates << MappingState(inputs.noremap(), inputs.silent(), editBlock);
|
||||||
@@ -2830,7 +2858,7 @@ void FakeVimHandler::Private::clearPendingInput()
|
|||||||
g.mapDepth = 0;
|
g.mapDepth = 0;
|
||||||
|
|
||||||
// Clear all started edit blocks.
|
// Clear all started edit blocks.
|
||||||
while (m_editBlockLevel > 0)
|
while (m_buffer->editBlockLevel > 0)
|
||||||
endEditBlock();
|
endEditBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2959,12 +2987,13 @@ bool FakeVimHandler::Private::isFirstNonBlankOnLine(int pos)
|
|||||||
|
|
||||||
void FakeVimHandler::Private::pushUndoState(bool overwrite)
|
void FakeVimHandler::Private::pushUndoState(bool overwrite)
|
||||||
{
|
{
|
||||||
if (m_editBlockLevel != 0 && m_undoState.isValid())
|
if (m_buffer->editBlockLevel != 0 && m_buffer->undoState.isValid())
|
||||||
return; // No need to save undo state for inner edit blocks.
|
return; // No need to save undo state for inner edit blocks.
|
||||||
|
|
||||||
if (m_undoState.isValid() && !overwrite)
|
if (m_buffer->undoState.isValid() && !overwrite)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
UNDO_DEBUG("PUSH UNDO");
|
||||||
int pos = position();
|
int pos = position();
|
||||||
if (!isInsertMode()) {
|
if (!isInsertMode()) {
|
||||||
if (isVisualMode() || g.submode == DeleteSubMode
|
if (isVisualMode() || g.submode == DeleteSubMode
|
||||||
@@ -2984,14 +3013,14 @@ void FakeVimHandler::Private::pushUndoState(bool overwrite)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_redo.clear();
|
m_buffer->redo.clear();
|
||||||
m_lastChangePosition = CursorPosition(document(), pos);
|
m_buffer->lastChangePosition = CursorPosition(document(), pos);
|
||||||
if (isVisualMode()) {
|
if (isVisualMode()) {
|
||||||
setMark(QLatin1Char('<'), markLessPosition());
|
setMark(QLatin1Char('<'), markLessPosition());
|
||||||
setMark(QLatin1Char('>'), markGreaterPosition());
|
setMark(QLatin1Char('>'), markGreaterPosition());
|
||||||
}
|
}
|
||||||
m_undoState = State(revision(), m_lastChangePosition, m_marks, m_lastVisualMode,
|
m_buffer->undoState = State(revision(), m_buffer->lastChangePosition, m_buffer->marks,
|
||||||
m_lastVisualModeInverted);
|
m_buffer->lastVisualMode, m_buffer->lastVisualModeInverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::moveDown(int n)
|
void FakeVimHandler::Private::moveDown(int n)
|
||||||
@@ -3374,14 +3403,14 @@ void FakeVimHandler::Private::resetCommandMode()
|
|||||||
enterCommandMode();
|
enterCommandMode();
|
||||||
} else {
|
} else {
|
||||||
clearCommandMode();
|
clearCommandMode();
|
||||||
const QString lastInsertion = m_lastInsertion;
|
const QString lastInsertion = m_buffer->lastInsertion;
|
||||||
if (g.returnToMode == InsertMode)
|
if (g.returnToMode == InsertMode)
|
||||||
enterInsertMode();
|
enterInsertMode();
|
||||||
else
|
else
|
||||||
enterReplaceMode();
|
enterReplaceMode();
|
||||||
moveToTargetColumn();
|
moveToTargetColumn();
|
||||||
invalidateInsertState();
|
invalidateInsertState();
|
||||||
m_lastInsertion = lastInsertion;
|
m_buffer->lastInsertion = lastInsertion;
|
||||||
}
|
}
|
||||||
if (isNoVisualMode())
|
if (isNoVisualMode())
|
||||||
setAnchor();
|
setAnchor();
|
||||||
@@ -3403,7 +3432,7 @@ void FakeVimHandler::Private::updateSelection()
|
|||||||
{
|
{
|
||||||
QList<QTextEdit::ExtraSelection> selections = m_extraSelections;
|
QList<QTextEdit::ExtraSelection> selections = m_extraSelections;
|
||||||
if (hasConfig(ConfigShowMarks)) {
|
if (hasConfig(ConfigShowMarks)) {
|
||||||
for (MarksIterator it(m_marks); it.hasNext(); ) {
|
for (MarksIterator it(m_buffer->marks); it.hasNext(); ) {
|
||||||
it.next();
|
it.next();
|
||||||
QTextEdit::ExtraSelection sel;
|
QTextEdit::ExtraSelection sel;
|
||||||
sel.cursor = m_cursor;
|
sel.cursor = m_cursor;
|
||||||
@@ -4282,12 +4311,12 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
setAnchor();
|
setAnchor();
|
||||||
insertNewLine();
|
insertNewLine();
|
||||||
if (appendLine) {
|
if (appendLine) {
|
||||||
m_insertState.newLineBefore = true;
|
m_buffer->insertState.newLineBefore = true;
|
||||||
} else {
|
} else {
|
||||||
moveUp();
|
moveUp();
|
||||||
m_oldInternalPosition = position();
|
m_oldInternalPosition = position();
|
||||||
m_insertState.pos1 = m_oldInternalPosition;
|
m_buffer->insertState.pos1 = m_oldInternalPosition;
|
||||||
m_insertState.newLineAfter = true;
|
m_buffer->insertState.newLineAfter = true;
|
||||||
}
|
}
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
endEditBlock();
|
endEditBlock();
|
||||||
@@ -4366,13 +4395,13 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
handleStartOfLine();
|
handleStartOfLine();
|
||||||
scrollToLine(cursorLine() - sline);
|
scrollToLine(cursorLine() - sline);
|
||||||
} else if (g.gflag && input.is('v')) {
|
} else if (g.gflag && input.is('v')) {
|
||||||
if (m_lastVisualMode != NoVisualMode) {
|
if (m_buffer->lastVisualMode != NoVisualMode) {
|
||||||
CursorPosition from = markLessPosition();
|
CursorPosition from = markLessPosition();
|
||||||
CursorPosition to = markGreaterPosition();
|
CursorPosition to = markGreaterPosition();
|
||||||
toggleVisualMode(m_lastVisualMode);
|
toggleVisualMode(m_buffer->lastVisualMode);
|
||||||
setCursorPosition(m_lastVisualModeInverted ? to : from);
|
setCursorPosition(m_buffer->lastVisualModeInverted ? to : from);
|
||||||
setAnchor();
|
setAnchor();
|
||||||
setCursorPosition(m_lastVisualModeInverted ? from : to);
|
setCursorPosition(m_buffer->lastVisualModeInverted ? from : to);
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
}
|
}
|
||||||
} else if (input.is('v')) {
|
} else if (input.is('v')) {
|
||||||
@@ -4729,7 +4758,7 @@ bool FakeVimHandler::Private::handleMacroExecuteSubMode(const Input &input)
|
|||||||
|
|
||||||
EventResult FakeVimHandler::Private::handleInsertOrReplaceMode(const Input &input)
|
EventResult FakeVimHandler::Private::handleInsertOrReplaceMode(const Input &input)
|
||||||
{
|
{
|
||||||
if (position() < m_insertState.pos1 || position() > m_insertState.pos2) {
|
if (position() < m_buffer->insertState.pos1 || position() > m_buffer->insertState.pos2) {
|
||||||
commitInsertState();
|
commitInsertState();
|
||||||
invalidateInsertState();
|
invalidateInsertState();
|
||||||
}
|
}
|
||||||
@@ -4742,8 +4771,8 @@ EventResult FakeVimHandler::Private::handleInsertOrReplaceMode(const Input &inpu
|
|||||||
if (!m_textedit && !m_plaintextedit)
|
if (!m_textedit && !m_plaintextedit)
|
||||||
return EventHandled;
|
return EventHandled;
|
||||||
|
|
||||||
if (!isInsertMode() || m_breakEditBlock
|
if (!isInsertMode() || m_buffer->breakEditBlock
|
||||||
|| position() < m_insertState.pos1 || position() > m_insertState.pos2) {
|
|| position() < m_buffer->insertState.pos1 || position() > m_buffer->insertState.pos2) {
|
||||||
commitInsertState();
|
commitInsertState();
|
||||||
invalidateInsertState();
|
invalidateInsertState();
|
||||||
breakEditBlock();
|
breakEditBlock();
|
||||||
@@ -4764,7 +4793,7 @@ void FakeVimHandler::Private::handleReplaceMode(const Input &input)
|
|||||||
commitInsertState();
|
commitInsertState();
|
||||||
moveLeft(qMin(1, leftDist()));
|
moveLeft(qMin(1, leftDist()));
|
||||||
enterCommandMode();
|
enterCommandMode();
|
||||||
g.dotCommand.append(m_lastInsertion + _("<ESC>"));
|
g.dotCommand.append(m_buffer->lastInsertion + _("<ESC>"));
|
||||||
} else if (input.isKey(Key_Left)) {
|
} else if (input.isKey(Key_Left)) {
|
||||||
moveLeft();
|
moveLeft();
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
@@ -4795,18 +4824,18 @@ void FakeVimHandler::Private::handleReplaceMode(const Input &input)
|
|||||||
|
|
||||||
void FakeVimHandler::Private::finishInsertMode()
|
void FakeVimHandler::Private::finishInsertMode()
|
||||||
{
|
{
|
||||||
bool newLineAfter = m_insertState.newLineAfter;
|
bool newLineAfter = m_buffer->insertState.newLineAfter;
|
||||||
bool newLineBefore = m_insertState.newLineBefore;
|
bool newLineBefore = m_buffer->insertState.newLineBefore;
|
||||||
|
|
||||||
// Repeat insertion [count] times.
|
// Repeat insertion [count] times.
|
||||||
// One instance was already physically inserted while typing.
|
// One instance was already physically inserted while typing.
|
||||||
if (!m_breakEditBlock && isInsertStateValid()) {
|
if (!m_buffer->breakEditBlock && isInsertStateValid()) {
|
||||||
commitInsertState();
|
commitInsertState();
|
||||||
|
|
||||||
QString text = m_lastInsertion;
|
QString text = m_buffer->lastInsertion;
|
||||||
const QString dotCommand = g.dotCommand;
|
const QString dotCommand = g.dotCommand;
|
||||||
const int repeat = count() - 1;
|
const int repeat = count() - 1;
|
||||||
m_lastInsertion.clear();
|
m_buffer->lastInsertion.clear();
|
||||||
joinPreviousEditBlock();
|
joinPreviousEditBlock();
|
||||||
|
|
||||||
if (newLineAfter) {
|
if (newLineAfter) {
|
||||||
@@ -4829,7 +4858,7 @@ void FakeVimHandler::Private::finishInsertMode()
|
|||||||
CursorPosition pos(lastAnchor.line, insertColumn);
|
CursorPosition pos(lastAnchor.line, insertColumn);
|
||||||
|
|
||||||
if (change)
|
if (change)
|
||||||
pos.column = m_insertState.pos1 - document()->findBlock(m_insertState.pos1).position();
|
pos.column = m_buffer->insertState.pos1 - document()->findBlock(m_buffer->insertState.pos1).position();
|
||||||
|
|
||||||
// Cursor position after block insert is on the first selected line,
|
// Cursor position after block insert is on the first selected line,
|
||||||
// last selected column for 's' command, otherwise first selected column.
|
// last selected column for 's' command, otherwise first selected column.
|
||||||
@@ -4862,15 +4891,15 @@ void FakeVimHandler::Private::finishInsertMode()
|
|||||||
endEditBlock();
|
endEditBlock();
|
||||||
breakEditBlock();
|
breakEditBlock();
|
||||||
|
|
||||||
m_lastInsertion = text;
|
m_buffer->lastInsertion = text;
|
||||||
g.dotCommand = dotCommand;
|
g.dotCommand = dotCommand;
|
||||||
} else {
|
} else {
|
||||||
moveLeft(qMin(1, leftDist()));
|
moveLeft(qMin(1, leftDist()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newLineBefore || newLineAfter)
|
if (newLineBefore || newLineAfter)
|
||||||
m_lastInsertion.remove(0, m_lastInsertion.indexOf(QLatin1Char('\n')) + 1);
|
m_buffer->lastInsertion.remove(0, m_buffer->lastInsertion.indexOf(QLatin1Char('\n')) + 1);
|
||||||
g.dotCommand.append(m_lastInsertion + _("<ESC>"));
|
g.dotCommand.append(m_buffer->lastInsertion + _("<ESC>"));
|
||||||
|
|
||||||
enterCommandMode();
|
enterCommandMode();
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
@@ -4986,7 +5015,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
} else if (input.isBackspace()) {
|
} else if (input.isBackspace()) {
|
||||||
if (!handleInsertInEditor(input)) {
|
if (!handleInsertInEditor(input)) {
|
||||||
joinPreviousEditBlock();
|
joinPreviousEditBlock();
|
||||||
if (!m_lastInsertion.isEmpty()
|
if (!m_buffer->lastInsertion.isEmpty()
|
||||||
|| hasConfig(ConfigBackspace, "start")
|
|| hasConfig(ConfigBackspace, "start")
|
||||||
|| hasConfig(ConfigBackspace, "2")) {
|
|| hasConfig(ConfigBackspace, "2")) {
|
||||||
const int line = cursorLine() + 1;
|
const int line = cursorLine() + 1;
|
||||||
@@ -5019,7 +5048,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
} else if (input.isKey(Key_PageUp) || input.isControl('b')) {
|
} else if (input.isKey(Key_PageUp) || input.isControl('b')) {
|
||||||
movePageUp();
|
movePageUp();
|
||||||
} else if (input.isKey(Key_Tab)) {
|
} else if (input.isKey(Key_Tab)) {
|
||||||
m_insertState.insertingSpaces = true;
|
m_buffer->insertState.insertingSpaces = true;
|
||||||
if (hasConfig(ConfigExpandTab)) {
|
if (hasConfig(ConfigExpandTab)) {
|
||||||
const int ts = config(ConfigTabStop).toInt();
|
const int ts = config(ConfigTabStop).toInt();
|
||||||
const int col = logicalCursorColumn();
|
const int col = logicalCursorColumn();
|
||||||
@@ -5028,7 +5057,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
} else {
|
} else {
|
||||||
insertInInsertMode(input.raw());
|
insertInInsertMode(input.raw());
|
||||||
}
|
}
|
||||||
m_insertState.insertingSpaces = false;
|
m_buffer->insertState.insertingSpaces = false;
|
||||||
} else if (input.isControl('d')) {
|
} else if (input.isControl('d')) {
|
||||||
// remove one level of indentation from the current line
|
// remove one level of indentation from the current line
|
||||||
int shift = config(ConfigShiftWidth).toInt();
|
int shift = config(ConfigShiftWidth).toInt();
|
||||||
@@ -5060,14 +5089,14 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input)
|
|||||||
if (data && data->hasText())
|
if (data && data->hasText())
|
||||||
insertInInsertMode(data->text());
|
insertInInsertMode(data->text());
|
||||||
} else {
|
} else {
|
||||||
m_insertState.insertingSpaces = input.isKey(Key_Space);
|
m_buffer->insertState.insertingSpaces = input.isKey(Key_Space);
|
||||||
if (!handleInsertInEditor(input)) {
|
if (!handleInsertInEditor(input)) {
|
||||||
const QString toInsert = input.text();
|
const QString toInsert = input.text();
|
||||||
if (toInsert.isEmpty())
|
if (toInsert.isEmpty())
|
||||||
return;
|
return;
|
||||||
insertInInsertMode(toInsert);
|
insertInInsertMode(toInsert);
|
||||||
}
|
}
|
||||||
m_insertState.insertingSpaces = false;
|
m_buffer->insertState.insertingSpaces = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5500,7 +5529,7 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastBlock.isValid()) {
|
if (lastBlock.isValid()) {
|
||||||
m_undoState.position = CursorPosition(firstBlock.blockNumber(), 0);
|
m_buffer->undoState.position = CursorPosition(firstBlock.blockNumber(), 0);
|
||||||
|
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
setPosition(lastBlock.position());
|
setPosition(lastBlock.position());
|
||||||
@@ -6391,9 +6420,9 @@ void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar)
|
|||||||
qSwap(beginBlock, endBlock);
|
qSwap(beginBlock, endBlock);
|
||||||
|
|
||||||
// Don't remember current indentation in last text insertion.
|
// Don't remember current indentation in last text insertion.
|
||||||
const QString lastInsertion = m_lastInsertion;
|
const QString lastInsertion = m_buffer->lastInsertion;
|
||||||
emit q->indentRegion(beginBlock, endBlock, typedChar);
|
emit q->indentRegion(beginBlock, endBlock, typedChar);
|
||||||
m_lastInsertion = lastInsertion;
|
m_buffer->lastInsertion = lastInsertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::isElectricCharacter(QChar c) const
|
bool FakeVimHandler::Private::isElectricCharacter(QChar c) const
|
||||||
@@ -6535,6 +6564,19 @@ void FakeVimHandler::Private::miniBufferTextEdited(const QString &text, int curs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::pullOrCreateBufferData()
|
||||||
|
{
|
||||||
|
const QVariant data = document()->property("FakeVimSharedData");
|
||||||
|
if (data.isValid()) {
|
||||||
|
// FakeVimHandler has been already created for this document (e.g. in other split).
|
||||||
|
m_buffer = data.value<BufferDataPtr>();
|
||||||
|
} else {
|
||||||
|
// FakeVimHandler has not been created for this document yet.
|
||||||
|
m_buffer = BufferDataPtr(new BufferData);
|
||||||
|
document()->setProperty("FakeVimSharedData", QVariant::fromValue(m_buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Helper to parse a-z,A-Z,48-57,_
|
// Helper to parse a-z,A-Z,48-57,_
|
||||||
static int someInt(const QString &str)
|
static int someInt(const QString &str)
|
||||||
{
|
{
|
||||||
@@ -7316,7 +7358,7 @@ void FakeVimHandler::Private::joinLines(int count, bool preserveSpace)
|
|||||||
|
|
||||||
void FakeVimHandler::Private::insertNewLine()
|
void FakeVimHandler::Private::insertNewLine()
|
||||||
{
|
{
|
||||||
if ( m_editBlockLevel <= 1 && hasConfig(ConfigPassKeys) ) {
|
if ( m_buffer->editBlockLevel <= 1 && hasConfig(ConfigPassKeys) ) {
|
||||||
QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, QLatin1String("\n"));
|
QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, QLatin1String("\n"));
|
||||||
if (passEventToEditor(event))
|
if (passEventToEditor(event))
|
||||||
return;
|
return;
|
||||||
@@ -7328,7 +7370,7 @@ void FakeVimHandler::Private::insertNewLine()
|
|||||||
|
|
||||||
bool FakeVimHandler::Private::handleInsertInEditor(const Input &input)
|
bool FakeVimHandler::Private::handleInsertInEditor(const Input &input)
|
||||||
{
|
{
|
||||||
if (m_editBlockLevel > 0 || !hasConfig(ConfigPassKeys))
|
if (m_buffer->editBlockLevel > 0 || !hasConfig(ConfigPassKeys))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
joinPreviousEditBlock();
|
joinPreviousEditBlock();
|
||||||
@@ -7530,7 +7572,7 @@ void FakeVimHandler::Private::toggleVisualMode(VisualMode visualMode)
|
|||||||
m_positionPastEnd = false;
|
m_positionPastEnd = false;
|
||||||
m_anchorPastEnd = false;
|
m_anchorPastEnd = false;
|
||||||
g.visualMode = visualMode;
|
g.visualMode = visualMode;
|
||||||
m_lastVisualMode = visualMode;
|
m_buffer->lastVisualMode = visualMode;
|
||||||
updateMiniBuffer();
|
updateMiniBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7542,7 +7584,7 @@ void FakeVimHandler::Private::leaveVisualMode()
|
|||||||
|
|
||||||
setMark(QLatin1Char('<'), markLessPosition());
|
setMark(QLatin1Char('<'), markLessPosition());
|
||||||
setMark(QLatin1Char('>'), markGreaterPosition());
|
setMark(QLatin1Char('>'), markGreaterPosition());
|
||||||
m_lastVisualModeInverted = anchor() > position();
|
m_buffer->lastVisualModeInverted = anchor() > position();
|
||||||
if (isVisualLineMode()) {
|
if (isVisualLineMode()) {
|
||||||
g.rangemode = RangeLineMode;
|
g.rangemode = RangeLineMode;
|
||||||
g.movetype = MoveLineWise;
|
g.movetype = MoveLineWise;
|
||||||
@@ -7568,7 +7610,7 @@ QWidget *FakeVimHandler::Private::editor() const
|
|||||||
void FakeVimHandler::Private::joinPreviousEditBlock()
|
void FakeVimHandler::Private::joinPreviousEditBlock()
|
||||||
{
|
{
|
||||||
UNDO_DEBUG("JOIN");
|
UNDO_DEBUG("JOIN");
|
||||||
if (m_breakEditBlock) {
|
if (m_buffer->breakEditBlock) {
|
||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
QTextCursor tc(m_cursor);
|
QTextCursor tc(m_cursor);
|
||||||
tc.setPosition(tc.position());
|
tc.setPosition(tc.position());
|
||||||
@@ -7576,78 +7618,79 @@ void FakeVimHandler::Private::joinPreviousEditBlock()
|
|||||||
tc.insertText(_("X"));
|
tc.insertText(_("X"));
|
||||||
tc.deletePreviousChar();
|
tc.deletePreviousChar();
|
||||||
tc.endEditBlock();
|
tc.endEditBlock();
|
||||||
m_breakEditBlock = false;
|
m_buffer->breakEditBlock = false;
|
||||||
} else {
|
} else {
|
||||||
if (m_editBlockLevel == 0 && !m_undo.empty())
|
if (m_buffer->editBlockLevel == 0 && !m_buffer->undo.empty())
|
||||||
m_undoState = m_undo.pop();
|
m_buffer->undoState = m_buffer->undo.pop();
|
||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::beginEditBlock(bool largeEditBlock)
|
void FakeVimHandler::Private::beginEditBlock(bool largeEditBlock)
|
||||||
{
|
{
|
||||||
UNDO_DEBUG("BEGIN EDIT BLOCK");
|
UNDO_DEBUG("BEGIN EDIT BLOCK" << m_buffer->editBlockLevel + 1);
|
||||||
if (!largeEditBlock && !m_undoState.isValid())
|
if (!largeEditBlock && !m_buffer->undoState.isValid())
|
||||||
pushUndoState(false);
|
pushUndoState(false);
|
||||||
if (m_editBlockLevel == 0)
|
if (m_buffer->editBlockLevel == 0)
|
||||||
m_breakEditBlock = true;
|
m_buffer->breakEditBlock = true;
|
||||||
++m_editBlockLevel;
|
++m_buffer->editBlockLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::endEditBlock()
|
void FakeVimHandler::Private::endEditBlock()
|
||||||
{
|
{
|
||||||
UNDO_DEBUG("END EDIT BLOCK");
|
UNDO_DEBUG("END EDIT BLOCK" << m_buffer->editBlockLevel);
|
||||||
QTC_ASSERT(m_editBlockLevel > 0,
|
QTC_ASSERT(m_buffer->editBlockLevel > 0,
|
||||||
qDebug() << "beginEditBlock() not called before endEditBlock()!"; return);
|
qDebug() << "beginEditBlock() not called before endEditBlock()!"; return);
|
||||||
--m_editBlockLevel;
|
--m_buffer->editBlockLevel;
|
||||||
if (m_editBlockLevel == 0 && m_undoState.isValid()) {
|
if (m_buffer->editBlockLevel == 0 && m_buffer->undoState.isValid()) {
|
||||||
m_undo.push(m_undoState);
|
m_buffer->undo.push(m_buffer->undoState);
|
||||||
m_undoState = State();
|
m_buffer->undoState = State();
|
||||||
}
|
}
|
||||||
if (m_editBlockLevel == 0)
|
if (m_buffer->editBlockLevel == 0)
|
||||||
m_breakEditBlock = false;
|
m_buffer->breakEditBlock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved, int charsAdded)
|
void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved, int charsAdded)
|
||||||
{
|
{
|
||||||
// Record inserted and deleted text in insert mode.
|
// Record inserted and deleted text in insert mode.
|
||||||
if (isInsertMode() && (charsAdded > 0 || charsRemoved > 0)) {
|
if (isInsertMode() && (charsAdded > 0 || charsRemoved > 0)) {
|
||||||
|
BufferData::InsertState &insertState = m_buffer->insertState;
|
||||||
if (!isInsertStateValid()) {
|
if (!isInsertStateValid()) {
|
||||||
m_insertState.pos1 = m_oldInternalPosition;
|
insertState.pos1 = m_oldInternalPosition;
|
||||||
g.dotCommand = _("i");
|
g.dotCommand = _("i");
|
||||||
resetCount();
|
resetCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore changes outside inserted text (e.g. renaming other occurrences of a variable).
|
// Ignore changes outside inserted text (e.g. renaming other occurrences of a variable).
|
||||||
if (position + charsRemoved >= m_insertState.pos1 && position <= m_insertState.pos2) {
|
if (position + charsRemoved >= insertState.pos1 && position <= insertState.pos2) {
|
||||||
if (charsRemoved > 0) {
|
if (charsRemoved > 0) {
|
||||||
if (position < m_insertState.pos1) {
|
if (position < insertState.pos1) {
|
||||||
// backspaces
|
// backspaces
|
||||||
const int bs = m_insertState.pos1 - position;
|
const int bs = insertState.pos1 - position;
|
||||||
const QString inserted = textAt(position, m_oldInternalPosition);
|
const QString inserted = textAt(position, m_oldInternalPosition);
|
||||||
const QString removed = m_insertState.textBeforeCursor.right(bs);
|
const QString removed = insertState.textBeforeCursor.right(bs);
|
||||||
// Ignore backspaces if same text was just inserted.
|
// Ignore backspaces if same text was just inserted.
|
||||||
if ( !inserted.endsWith(removed) ) {
|
if ( !inserted.endsWith(removed) ) {
|
||||||
m_insertState.backspaces += bs;
|
insertState.backspaces += bs;
|
||||||
m_insertState.pos1 = position;
|
insertState.pos1 = position;
|
||||||
m_insertState.pos2 = qMax(position, m_insertState.pos2 - bs);
|
insertState.pos2 = qMax(position, insertState.pos2 - bs);
|
||||||
}
|
}
|
||||||
} else if (position + charsRemoved > m_insertState.pos2) {
|
} else if (position + charsRemoved > insertState.pos2) {
|
||||||
// deletes
|
// deletes
|
||||||
m_insertState.deletes += position + charsRemoved - m_insertState.pos2;
|
insertState.deletes += position + charsRemoved - insertState.pos2;
|
||||||
}
|
}
|
||||||
} else if (charsAdded > 0 && m_insertState.insertingSpaces) {
|
} else if (charsAdded > 0 && insertState.insertingSpaces) {
|
||||||
for (int i = position; i < position + charsAdded; ++i) {
|
for (int i = position; i < position + charsAdded; ++i) {
|
||||||
const QChar c = document()->characterAt(i);
|
const QChar c = document()->characterAt(i);
|
||||||
if (c.unicode() == ' ' || c.unicode() == '\t')
|
if (c.unicode() == ' ' || c.unicode() == '\t')
|
||||||
m_insertState.spaces.insert(i);
|
insertState.spaces.insert(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_insertState.pos2 = qMax(m_insertState.pos2 + charsAdded - charsRemoved,
|
insertState.pos2 = qMax(insertState.pos2 + charsAdded - charsRemoved,
|
||||||
position + charsAdded);
|
position + charsAdded);
|
||||||
m_oldInternalPosition = position + charsAdded;
|
m_oldInternalPosition = position + charsAdded;
|
||||||
m_insertState.textBeforeCursor = textAt(document()->findBlock(m_oldInternalPosition).position(),
|
insertState.textBeforeCursor = textAt(document()->findBlock(m_oldInternalPosition).position(),
|
||||||
m_oldInternalPosition);
|
m_oldInternalPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7659,20 +7702,22 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
|
|||||||
void FakeVimHandler::Private::onUndoCommandAdded()
|
void FakeVimHandler::Private::onUndoCommandAdded()
|
||||||
{
|
{
|
||||||
// Undo commands removed?
|
// Undo commands removed?
|
||||||
if (m_lastRevision >= revision()) {
|
UNDO_DEBUG("Undo added" << "previous: REV" << m_buffer->lastRevision);
|
||||||
const int removed = m_lastRevision - revision();
|
if (m_buffer->lastRevision >= revision()) {
|
||||||
for (int i = m_undo.size() - 1; i >= 0; --i) {
|
UNDO_DEBUG("UNDO REMOVED!");
|
||||||
if ((m_undo[i].revision -= removed) < 0) {
|
const int removed = m_buffer->lastRevision - revision();
|
||||||
m_undo.remove(0, i + 1);
|
for (int i = m_buffer->undo.size() - 1; i >= 0; --i) {
|
||||||
|
if ((m_buffer->undo[i].revision -= removed) < 0) {
|
||||||
|
m_buffer->undo.remove(0, i + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_redo.clear();
|
m_buffer->redo.clear();
|
||||||
// External change while FakeVim disabled.
|
// External change while FakeVim disabled.
|
||||||
if (m_editBlockLevel == 0 && !m_undo.isEmpty() && !isInsertMode())
|
if (m_buffer->editBlockLevel == 0 && !m_buffer->undo.isEmpty() && !isInsertMode())
|
||||||
m_undo.push(State());
|
m_buffer->undo.push(State());
|
||||||
}
|
}
|
||||||
|
|
||||||
char FakeVimHandler::Private::currentModeCode() const
|
char FakeVimHandler::Private::currentModeCode() const
|
||||||
@@ -7693,13 +7738,15 @@ char FakeVimHandler::Private::currentModeCode() const
|
|||||||
|
|
||||||
void FakeVimHandler::Private::undoRedo(bool undo)
|
void FakeVimHandler::Private::undoRedo(bool undo)
|
||||||
{
|
{
|
||||||
|
UNDO_DEBUG((undo ? "UNDO" : "REDO"));
|
||||||
|
|
||||||
// FIXME: That's only an approximaxtion. The real solution might
|
// FIXME: That's only an approximaxtion. The real solution might
|
||||||
// be to store marks and old userData with QTextBlock setUserData
|
// be to store marks and old userData with QTextBlock setUserData
|
||||||
// and retrieve them afterward.
|
// and retrieve them afterward.
|
||||||
QStack<State> &stack = undo ? m_undo : m_redo;
|
QStack<State> &stack = undo ? m_buffer->undo : m_buffer->redo;
|
||||||
QStack<State> &stack2 = undo ? m_redo : m_undo;
|
QStack<State> &stack2 = undo ? m_buffer->redo : m_buffer->undo;
|
||||||
|
|
||||||
State state = m_undoState.isValid() ? m_undoState
|
State state = m_buffer->undoState.isValid() ? m_buffer->undoState
|
||||||
: !stack.empty() ? stack.pop() : State();
|
: !stack.empty() ? stack.pop() : State();
|
||||||
|
|
||||||
CursorPosition lastPos(m_cursor);
|
CursorPosition lastPos(m_cursor);
|
||||||
@@ -7707,11 +7754,12 @@ void FakeVimHandler::Private::undoRedo(bool undo)
|
|||||||
const QString msg = undo ? FakeVimHandler::tr("Already at oldest change.")
|
const QString msg = undo ? FakeVimHandler::tr("Already at oldest change.")
|
||||||
: FakeVimHandler::tr("Already at newest change.");
|
: FakeVimHandler::tr("Already at newest change.");
|
||||||
showMessage(MessageInfo, msg);
|
showMessage(MessageInfo, msg);
|
||||||
|
UNDO_DEBUG(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearMessage();
|
clearMessage();
|
||||||
|
|
||||||
++m_editBlockLevel;
|
++m_buffer->editBlockLevel;
|
||||||
|
|
||||||
// Do undo/redo [count] times to reach previous revision.
|
// Do undo/redo [count] times to reach previous revision.
|
||||||
const int previousRevision = revision();
|
const int previousRevision = revision();
|
||||||
@@ -7725,18 +7773,18 @@ void FakeVimHandler::Private::undoRedo(bool undo)
|
|||||||
} while (document()->isRedoAvailable() && state.revision > revision());
|
} while (document()->isRedoAvailable() && state.revision > revision());
|
||||||
}
|
}
|
||||||
|
|
||||||
--m_editBlockLevel;
|
--m_buffer->editBlockLevel;
|
||||||
|
|
||||||
if (state.isValid()) {
|
if (state.isValid()) {
|
||||||
m_lastChangePosition = state.position;
|
m_buffer->lastChangePosition = state.position;
|
||||||
Marks marks = m_marks;
|
Marks marks = m_buffer->marks;
|
||||||
marks.swap(state.marks);
|
marks.swap(state.marks);
|
||||||
updateMarks(marks);
|
updateMarks(marks);
|
||||||
m_lastVisualMode = state.lastVisualMode;
|
m_buffer->lastVisualMode = state.lastVisualMode;
|
||||||
m_lastVisualModeInverted = state.lastVisualModeInverted;
|
m_buffer->lastVisualModeInverted = state.lastVisualModeInverted;
|
||||||
setMark(QLatin1Char('\''), lastPos);
|
setMark(QLatin1Char('\''), lastPos);
|
||||||
setMark(QLatin1Char('`'), lastPos);
|
setMark(QLatin1Char('`'), lastPos);
|
||||||
setCursorPosition(m_lastChangePosition);
|
setCursorPosition(m_buffer->lastChangePosition);
|
||||||
setAnchor();
|
setAnchor();
|
||||||
state.revision = previousRevision;
|
state.revision = previousRevision;
|
||||||
} else {
|
} else {
|
||||||
@@ -7748,6 +7796,8 @@ void FakeVimHandler::Private::undoRedo(bool undo)
|
|||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
if (atEndOfLine())
|
if (atEndOfLine())
|
||||||
moveLeft();
|
moveLeft();
|
||||||
|
|
||||||
|
UNDO_DEBUG((undo ? "UNDONE" : "REDONE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::undo()
|
void FakeVimHandler::Private::undo()
|
||||||
@@ -7886,16 +7936,16 @@ void FakeVimHandler::Private::recordJump(int position)
|
|||||||
: CursorPosition(m_cursor);
|
: CursorPosition(m_cursor);
|
||||||
setMark(QLatin1Char('\''), pos);
|
setMark(QLatin1Char('\''), pos);
|
||||||
setMark(QLatin1Char('`'), pos);
|
setMark(QLatin1Char('`'), pos);
|
||||||
if (m_jumpListUndo.isEmpty() || m_jumpListUndo.top() != pos)
|
if (m_buffer->jumpListUndo.isEmpty() || m_buffer->jumpListUndo.top() != pos)
|
||||||
m_jumpListUndo.push(pos);
|
m_buffer->jumpListUndo.push(pos);
|
||||||
m_jumpListRedo.clear();
|
m_buffer->jumpListRedo.clear();
|
||||||
UNDO_DEBUG("jumps: " << m_jumpListUndo);
|
UNDO_DEBUG("jumps: " << m_buffer->jumpListUndo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::jump(int distance)
|
void FakeVimHandler::Private::jump(int distance)
|
||||||
{
|
{
|
||||||
QStack<CursorPosition> &from = (distance > 0) ? m_jumpListRedo : m_jumpListUndo;
|
QStack<CursorPosition> &from = (distance > 0) ? m_buffer->jumpListRedo : m_buffer->jumpListUndo;
|
||||||
QStack<CursorPosition> &to = (distance > 0) ? m_jumpListUndo : m_jumpListRedo;
|
QStack<CursorPosition> &to = (distance > 0) ? m_buffer->jumpListUndo : m_buffer->jumpListRedo;
|
||||||
int len = qMin(qAbs(distance), from.size());
|
int len = qMin(qAbs(distance), from.size());
|
||||||
CursorPosition m(m_cursor);
|
CursorPosition m(m_cursor);
|
||||||
setMark(QLatin1Char('\''), m);
|
setMark(QLatin1Char('\''), m);
|
||||||
@@ -8265,11 +8315,11 @@ Mark FakeVimHandler::Private::mark(QChar code) const
|
|||||||
return CursorPosition(document(), qMax(anchor(), position()));
|
return CursorPosition(document(), qMax(anchor(), position()));
|
||||||
}
|
}
|
||||||
if (code == QLatin1Char('.'))
|
if (code == QLatin1Char('.'))
|
||||||
return m_lastChangePosition;
|
return m_buffer->lastChangePosition;
|
||||||
if (code.isUpper())
|
if (code.isUpper())
|
||||||
return g.marks.value(code);
|
return g.marks.value(code);
|
||||||
|
|
||||||
return m_marks.value(code);
|
return m_buffer->marks.value(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::setMark(QChar code, CursorPosition position)
|
void FakeVimHandler::Private::setMark(QChar code, CursorPosition position)
|
||||||
@@ -8277,7 +8327,7 @@ void FakeVimHandler::Private::setMark(QChar code, CursorPosition position)
|
|||||||
if (code.isUpper())
|
if (code.isUpper())
|
||||||
g.marks[code] = Mark(position, m_currentFileName);
|
g.marks[code] = Mark(position, m_currentFileName);
|
||||||
else
|
else
|
||||||
m_marks[code] = Mark(position);
|
m_buffer->marks[code] = Mark(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FakeVimHandler::Private::jumpToMark(QChar mark, bool backTickMode)
|
bool FakeVimHandler::Private::jumpToMark(QChar mark, bool backTickMode)
|
||||||
@@ -8292,8 +8342,8 @@ bool FakeVimHandler::Private::jumpToMark(QChar mark, bool backTickMode)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mark == QLatin1Char('\'') || mark == QLatin1Char('`')) && !m_jumpListUndo.isEmpty())
|
if ((mark == QLatin1Char('\'') || mark == QLatin1Char('`')) && !m_buffer->jumpListUndo.isEmpty())
|
||||||
m_jumpListUndo.pop();
|
m_buffer->jumpListUndo.pop();
|
||||||
recordJump();
|
recordJump();
|
||||||
setCursorPosition(m.position(document()));
|
setCursorPosition(m.position(document()));
|
||||||
if (!backTickMode)
|
if (!backTickMode)
|
||||||
@@ -8309,7 +8359,7 @@ void FakeVimHandler::Private::updateMarks(const Marks &newMarks)
|
|||||||
{
|
{
|
||||||
for (MarksIterator it(newMarks); it.hasNext(); ) {
|
for (MarksIterator it(newMarks); it.hasNext(); ) {
|
||||||
it.next();
|
it.next();
|
||||||
m_marks[it.key()] = it.value();
|
m_buffer->marks[it.key()] = it.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8622,4 +8672,6 @@ bool FakeVimHandler::jumpToLocalMark(QChar mark, bool backTickMode)
|
|||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace FakeVim
|
} // namespace FakeVim
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(FakeVim::Internal::FakeVimHandler::Private::BufferDataPtr)
|
||||||
|
|
||||||
#include "fakevimhandler.moc"
|
#include "fakevimhandler.moc"
|
||||||
|
|||||||
Reference in New Issue
Block a user