forked from qt-creator/qt-creator
FakeVim: Reworked undo/redo
Don't use QTextCursor::beginEditBlock() and others since it can change the behavior of underlying editor widget. Use these methods only for interrupting current edit block. Change-Id: I848d6287faeeaad9c04a76758bd0b2cc673ad2ef Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -1957,7 +1957,8 @@ void FakeVimPlugin::test_vim_substitute()
|
|||||||
data.setText("abc" N "def" N "ghi" N "jkl");
|
data.setText("abc" N "def" N "ghi" N "jkl");
|
||||||
KEYS("jVj:s/^/*<CR>", "abc" N "*def" N X "*ghi" N "jkl");
|
KEYS("jVj:s/^/*<CR>", "abc" N "*def" N X "*ghi" N "jkl");
|
||||||
COMMAND("'<,'>s/^/*", "abc" N "**def" N X "**ghi" N "jkl");
|
COMMAND("'<,'>s/^/*", "abc" N "**def" N X "**ghi" N "jkl");
|
||||||
KEYS("ugv:s/^/+<CR>", "abc" N "+*def" N X "+*ghi" N "jkl");
|
KEYS("u", "abc" N X "*def" N "*ghi" N "jkl");
|
||||||
|
KEYS("gv:s/^/+<CR>", "abc" N "+*def" N X "+*ghi" N "jkl");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimPlugin::test_vim_ex_yank()
|
void FakeVimPlugin::test_vim_ex_yank()
|
||||||
|
@@ -1661,11 +1661,13 @@ public:
|
|||||||
{ return document()->characterAt(position()); }
|
{ return document()->characterAt(position()); }
|
||||||
|
|
||||||
int m_editBlockLevel; // current level of edit blocks
|
int m_editBlockLevel; // current level of edit blocks
|
||||||
|
int m_largeEditBlockRevision; // current level of large edit block
|
||||||
void joinPreviousEditBlock();
|
void joinPreviousEditBlock();
|
||||||
void beginEditBlock(bool rememberPosition = true);
|
void beginEditBlock(bool largeEditBlock = false);
|
||||||
void beginLargeEditBlock() { beginEditBlock(false); }
|
void beginLargeEditBlock() { beginEditBlock(true); }
|
||||||
void endEditBlock();
|
void endEditBlock();
|
||||||
void breakEditBlock() { m_breakEditBlock = true; }
|
void breakEditBlock() { m_breakEditBlock = true; }
|
||||||
|
Q_SLOT void onContentsChanged();
|
||||||
|
|
||||||
bool isVisualMode() const { return m_visualMode != NoVisualMode; }
|
bool isVisualMode() const { return m_visualMode != NoVisualMode; }
|
||||||
bool isNoVisualMode() const { return m_visualMode == NoVisualMode; }
|
bool isNoVisualMode() const { return m_visualMode == NoVisualMode; }
|
||||||
@@ -1785,10 +1787,11 @@ public:
|
|||||||
|
|
||||||
// undo handling
|
// undo handling
|
||||||
int revision() const { return document()->availableUndoSteps(); }
|
int revision() const { return document()->availableUndoSteps(); }
|
||||||
|
int lastUndoRevision() const { return m_undo.empty() ? -1 : m_undo.top().revision; }
|
||||||
void undoRedo(bool undo);
|
void undoRedo(bool undo);
|
||||||
void undo();
|
void undo();
|
||||||
void redo();
|
void redo();
|
||||||
void setUndoPosition(bool overwrite = true);
|
void pushUndoState(bool overwrite = true);
|
||||||
// revision -> state
|
// revision -> state
|
||||||
QStack<State> m_undo;
|
QStack<State> m_undo;
|
||||||
QStack<State> m_redo;
|
QStack<State> m_redo;
|
||||||
@@ -1952,6 +1955,8 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
|
|||||||
q = parent;
|
q = parent;
|
||||||
m_textedit = qobject_cast<QTextEdit *>(widget);
|
m_textedit = qobject_cast<QTextEdit *>(widget);
|
||||||
m_plaintextedit = qobject_cast<QPlainTextEdit *>(widget);
|
m_plaintextedit = qobject_cast<QPlainTextEdit *>(widget);
|
||||||
|
if (editor())
|
||||||
|
connect(EDITOR(document()), SIGNAL(contentsChanged()), SLOT(onContentsChanged()));
|
||||||
//new Highlighter(document(), &pythonRules);
|
//new Highlighter(document(), &pythonRules);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@@ -1990,6 +1995,7 @@ void FakeVimHandler::Private::init()
|
|||||||
m_searchStartPosition = 0;
|
m_searchStartPosition = 0;
|
||||||
m_searchFromScreenLine = 0;
|
m_searchFromScreenLine = 0;
|
||||||
m_editBlockLevel = 0;
|
m_editBlockLevel = 0;
|
||||||
|
m_largeEditBlockRevision = -1;
|
||||||
|
|
||||||
setupCharClass();
|
setupCharClass();
|
||||||
}
|
}
|
||||||
@@ -2642,11 +2648,24 @@ bool FakeVimHandler::Private::isFirstNonBlankOnLine(int pos)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::setUndoPosition(bool overwrite)
|
void FakeVimHandler::Private::pushUndoState(bool overwrite)
|
||||||
{
|
{
|
||||||
const int rev = revision();
|
if (m_editBlockLevel != 0 && m_largeEditBlockRevision == -1)
|
||||||
if (!overwrite && !m_undo.empty() && m_undo.top().revision >= rev)
|
return; // No need to save undo state for inner edit blocks.
|
||||||
return;
|
|
||||||
|
// Use revision of large edit block if started.
|
||||||
|
int rev;
|
||||||
|
if (m_largeEditBlockRevision != -1) {
|
||||||
|
rev = m_largeEditBlockRevision;
|
||||||
|
m_largeEditBlockRevision = -1;
|
||||||
|
} else {
|
||||||
|
rev = revision();
|
||||||
|
if (!overwrite && lastUndoRevision() == rev)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lastUndoRevision() == rev)
|
||||||
|
m_undo.pop();
|
||||||
|
|
||||||
int pos = position();
|
int pos = position();
|
||||||
if (m_mode != InsertMode && m_mode != ReplaceMode) {
|
if (m_mode != InsertMode && m_mode != ReplaceMode) {
|
||||||
@@ -2667,8 +2686,6 @@ void FakeVimHandler::Private::setUndoPosition(bool overwrite)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_redo.clear();
|
m_redo.clear();
|
||||||
while (!m_undo.empty() && m_undo.top().revision >= rev)
|
|
||||||
m_undo.pop();
|
|
||||||
m_lastChangePosition = CursorPosition(document(), pos);
|
m_lastChangePosition = CursorPosition(document(), pos);
|
||||||
if (isVisualMode()) {
|
if (isVisualMode()) {
|
||||||
setMark(QLatin1Char('<'), mark(QLatin1Char('<')).position);
|
setMark(QLatin1Char('<'), mark(QLatin1Char('<')).position);
|
||||||
@@ -2873,7 +2890,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
|
|||||||
QString dotCommand;
|
QString dotCommand;
|
||||||
if (m_submode == ChangeSubMode) {
|
if (m_submode == ChangeSubMode) {
|
||||||
if (m_rangemode != RangeLineModeExclusive)
|
if (m_rangemode != RangeLineModeExclusive)
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
removeText(currentRange());
|
removeText(currentRange());
|
||||||
dotCommand = _("c");
|
dotCommand = _("c");
|
||||||
if (m_movetype == MoveLineWise)
|
if (m_movetype == MoveLineWise)
|
||||||
@@ -2883,7 +2900,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
|
|||||||
m_lastInsertion.clear();
|
m_lastInsertion.clear();
|
||||||
g.returnToMode = InsertMode;
|
g.returnToMode = InsertMode;
|
||||||
} else if (m_submode == DeleteSubMode) {
|
} else if (m_submode == DeleteSubMode) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
const int pos = position();
|
const int pos = position();
|
||||||
// Always delete something (e.g. 'dw' on an empty line deletes the line).
|
// Always delete something (e.g. 'dw' on an empty line deletes the line).
|
||||||
if (pos == anchor() && m_movetype == MoveInclusive)
|
if (pos == anchor() && m_movetype == MoveInclusive)
|
||||||
@@ -2934,7 +2951,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
|
|||||||
|| m_submode == ShiftRightSubMode
|
|| m_submode == ShiftRightSubMode
|
||||||
|| m_submode == ShiftLeftSubMode) {
|
|| m_submode == ShiftLeftSubMode) {
|
||||||
recordJump();
|
recordJump();
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
if (m_submode == IndentSubMode) {
|
if (m_submode == IndentSubMode) {
|
||||||
indentSelectedText();
|
indentSelectedText();
|
||||||
dotCommand = _("=");
|
dotCommand = _("=");
|
||||||
@@ -3663,11 +3680,11 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
moveRight();
|
moveRight();
|
||||||
breakEditBlock();
|
breakEditBlock();
|
||||||
enterInsertMode();
|
enterInsertMode();
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
} else if (input.is('A')) {
|
} else if (input.is('A')) {
|
||||||
breakEditBlock();
|
breakEditBlock();
|
||||||
moveBehindEndOfLine();
|
moveBehindEndOfLine();
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
setAnchor();
|
setAnchor();
|
||||||
enterInsertMode();
|
enterInsertMode();
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
@@ -3702,7 +3719,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
} else if ((input.is('d') || input.is('x') || input.isKey(Key_Delete))
|
} else if ((input.is('d') || input.is('x') || input.isKey(Key_Delete))
|
||||||
&& isVisualMode()) {
|
&& isVisualMode()) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
setDotCommand(visualDotCommand() + QLatin1Char('x'));
|
setDotCommand(visualDotCommand() + QLatin1Char('x'));
|
||||||
if (isVisualCharMode()) {
|
if (isVisualCharMode()) {
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
@@ -3720,7 +3737,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
setPosition(qMin(position(), anchor()));
|
setPosition(qMin(position(), anchor()));
|
||||||
}
|
}
|
||||||
} else if (input.is('D') && isNoVisualMode()) {
|
} else if (input.is('D') && isNoVisualMode()) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
if (atEndOfLine())
|
if (atEndOfLine())
|
||||||
moveLeft();
|
moveLeft();
|
||||||
m_submode = DeleteSubMode;
|
m_submode = DeleteSubMode;
|
||||||
@@ -3770,14 +3787,14 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
moveToFirstNonBlankOnLine();
|
moveToFirstNonBlankOnLine();
|
||||||
//m_tc.clearSelection();
|
//m_tc.clearSelection();
|
||||||
}
|
}
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
breakEditBlock();
|
breakEditBlock();
|
||||||
enterInsertMode();
|
enterInsertMode();
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
} else if (input.isControl('i')) {
|
} else if (input.isControl('i')) {
|
||||||
jump(count());
|
jump(count());
|
||||||
} else if (input.is('J')) {
|
} else if (input.is('J')) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
moveBehindEndOfLine();
|
moveBehindEndOfLine();
|
||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
if (m_submode == NoSubMode)
|
if (m_submode == NoSubMode)
|
||||||
@@ -3798,7 +3815,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
} else if (input.is('o') || input.is('O')) {
|
} else if (input.is('o') || input.is('O')) {
|
||||||
bool insertAfter = input.is('o');
|
bool insertAfter = input.is('o');
|
||||||
setDotCommand(_(insertAfter ? "%1o" : "%1O"), count());
|
setDotCommand(_(insertAfter ? "%1o" : "%1O"), count());
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
|
|
||||||
// Prepend line only if on the first line and command is 'O'.
|
// Prepend line only if on the first line and command is 'O'.
|
||||||
bool appendLine = true;
|
bool appendLine = true;
|
||||||
@@ -3851,7 +3868,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
} else if (input.is('r')) {
|
} else if (input.is('r')) {
|
||||||
m_submode = ReplaceSubMode;
|
m_submode = ReplaceSubMode;
|
||||||
} else if (!isVisualMode() && input.is('R')) {
|
} else if (!isVisualMode() && input.is('R')) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
breakEditBlock();
|
breakEditBlock();
|
||||||
enterReplaceMode();
|
enterReplaceMode();
|
||||||
} else if (input.isControl('r')) {
|
} else if (input.isControl('r')) {
|
||||||
@@ -3861,13 +3878,13 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
} else if (input.is('s') && isVisualBlockMode()) {
|
} else if (input.is('s') && isVisualBlockMode()) {
|
||||||
m_opcount.clear();
|
m_opcount.clear();
|
||||||
m_mvcount.clear();
|
m_mvcount.clear();
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
initVisualBlockInsertMode(QLatin1Char('s'));
|
initVisualBlockInsertMode(QLatin1Char('s'));
|
||||||
endEditBlock();
|
endEditBlock();
|
||||||
enterInsertMode();
|
enterInsertMode();
|
||||||
} else if (input.is('s')) {
|
} else if (input.is('s')) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
if (atEndOfLine())
|
if (atEndOfLine())
|
||||||
moveLeft();
|
moveLeft();
|
||||||
@@ -3879,7 +3896,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
finishMovement();
|
finishMovement();
|
||||||
} else if (input.is('S')) {
|
} else if (input.is('S')) {
|
||||||
m_movetype = MoveLineWise;
|
m_movetype = MoveLineWise;
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
if (!isVisualMode()) {
|
if (!isVisualMode()) {
|
||||||
const int line = cursorLine() + 1;
|
const int line = cursorLine() + 1;
|
||||||
const int anc = firstPositionInLine(line);
|
const int anc = firstPositionInLine(line);
|
||||||
@@ -3988,7 +4005,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
|
|||||||
m_submode = UpCaseSubMode;
|
m_submode = UpCaseSubMode;
|
||||||
finishMovement();
|
finishMovement();
|
||||||
} else if (m_gflag || (input.is('~') && hasConfig(ConfigTildeOp))) {
|
} else if (m_gflag || (input.is('~') && hasConfig(ConfigTildeOp))) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
if (atEndOfLine())
|
if (atEndOfLine())
|
||||||
moveLeft();
|
moveLeft();
|
||||||
setAnchor();
|
setAnchor();
|
||||||
@@ -4042,7 +4059,7 @@ bool FakeVimHandler::Private::handleChangeDeleteSubModes(const Input &input)
|
|||||||
if ((m_submode == ChangeSubMode && input.is('c'))
|
if ((m_submode == ChangeSubMode && input.is('c'))
|
||||||
|| (m_submode == DeleteSubMode && input.is('d'))) {
|
|| (m_submode == DeleteSubMode && input.is('d'))) {
|
||||||
m_movetype = MoveLineWise;
|
m_movetype = MoveLineWise;
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
const int line = cursorLine() + 1;
|
const int line = cursorLine() + 1;
|
||||||
const int anc = firstPositionInLine(line);
|
const int anc = firstPositionInLine(line);
|
||||||
const int pos = lastPositionInLine(line + count() - 1);
|
const int pos = lastPositionInLine(line + count() - 1);
|
||||||
@@ -4067,7 +4084,7 @@ bool FakeVimHandler::Private::handleReplaceSubMode(const Input &input)
|
|||||||
|
|
||||||
setDotCommand(visualDotCommand() + QLatin1Char('r') + input.asChar());
|
setDotCommand(visualDotCommand() + QLatin1Char('r') + input.asChar());
|
||||||
if (isVisualMode()) {
|
if (isVisualMode()) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
if (isVisualLineMode())
|
if (isVisualLineMode())
|
||||||
m_rangemode = RangeLineMode;
|
m_rangemode = RangeLineMode;
|
||||||
else if (isVisualBlockMode())
|
else if (isVisualBlockMode())
|
||||||
@@ -4082,7 +4099,7 @@ bool FakeVimHandler::Private::handleReplaceSubMode(const Input &input)
|
|||||||
&FakeVimHandler::Private::replaceByCharTransform;
|
&FakeVimHandler::Private::replaceByCharTransform;
|
||||||
transformText(range, tr, input.asChar());
|
transformText(range, tr, input.asChar());
|
||||||
} else if (count() <= rightDist()) {
|
} else if (count() <= rightDist()) {
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
setAnchor();
|
setAnchor();
|
||||||
moveRight(count());
|
moveRight(count());
|
||||||
Range range = currentRange();
|
Range range = currentRange();
|
||||||
@@ -4133,7 +4150,7 @@ bool FakeVimHandler::Private::handleShiftSubMode(const Input &input)
|
|||||||
|| (m_submode == ShiftRightSubMode && input.is('>'))
|
|| (m_submode == ShiftRightSubMode && input.is('>'))
|
||||||
|| (m_submode == IndentSubMode && input.is('='))) {
|
|| (m_submode == IndentSubMode && input.is('='))) {
|
||||||
m_movetype = MoveLineWise;
|
m_movetype = MoveLineWise;
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
moveDown(count() - 1);
|
moveDown(count() - 1);
|
||||||
setDotCommand(QString::fromLatin1("%2%1%1").arg(input.asChar()), count());
|
setDotCommand(QString::fromLatin1("%2%1%1").arg(input.asChar()), count());
|
||||||
finishMovement();
|
finishMovement();
|
||||||
@@ -4156,7 +4173,7 @@ bool FakeVimHandler::Private::handleChangeCaseSubMode(const Input &input)
|
|||||||
moveToFirstNonBlankOnLine();
|
moveToFirstNonBlankOnLine();
|
||||||
}
|
}
|
||||||
setTargetColumn();
|
setTargetColumn();
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
setAnchor();
|
setAnchor();
|
||||||
setPosition(lastPositionInLine(cursorLine() + count()) + 1);
|
setPosition(lastPositionInLine(cursorLine() + count()) + 1);
|
||||||
finishMovement(QString::fromLatin1("%1%2").arg(count()).arg(input.raw()));
|
finishMovement(QString::fromLatin1("%1%2").arg(count()).arg(input.raw()));
|
||||||
@@ -5216,7 +5233,7 @@ bool FakeVimHandler::Private::handleExYankDeleteCommand(const ExCommand &cmd)
|
|||||||
if (remove) {
|
if (remove) {
|
||||||
leaveVisualMode();
|
leaveVisualMode();
|
||||||
setPosition(range.beginPos);
|
setPosition(range.beginPos);
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
setCurrentRange(range);
|
setCurrentRange(range);
|
||||||
removeText(currentRange());
|
removeText(currentRange());
|
||||||
}
|
}
|
||||||
@@ -5265,7 +5282,7 @@ bool FakeVimHandler::Private::handleExMoveCommand(const ExCommand &cmd)
|
|||||||
|
|
||||||
recordJump();
|
recordJump();
|
||||||
setPosition(cmd.range.beginPos);
|
setPosition(cmd.range.beginPos);
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
|
|
||||||
setCurrentRange(cmd.range);
|
setCurrentRange(cmd.range);
|
||||||
QString text = selectText(cmd.range);
|
QString text = selectText(cmd.range);
|
||||||
@@ -5326,7 +5343,7 @@ bool FakeVimHandler::Private::handleExJoinCommand(const ExCommand &cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
moveToStartOfLine();
|
moveToStartOfLine();
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
joinLines(count, cmd.hasBang);
|
joinLines(count, cmd.hasBang);
|
||||||
|
|
||||||
moveToFirstNonBlankOnLine();
|
moveToFirstNonBlankOnLine();
|
||||||
@@ -6706,9 +6723,11 @@ void FakeVimHandler::Private::insertNewLine()
|
|||||||
|
|
||||||
bool FakeVimHandler::Private::handleInsertInEditor(const Input &input, QString *insert)
|
bool FakeVimHandler::Private::handleInsertInEditor(const Input &input, QString *insert)
|
||||||
{
|
{
|
||||||
if (!hasConfig(ConfigPassKeys) || m_editBlockLevel > 0)
|
if (m_editBlockLevel > 0 || !hasConfig(ConfigPassKeys))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
joinPreviousEditBlock();
|
||||||
|
|
||||||
const int pos1 = position();
|
const int pos1 = position();
|
||||||
const int len1 = lastPositionInDocument();
|
const int len1 = lastPositionInDocument();
|
||||||
|
|
||||||
@@ -6722,6 +6741,8 @@ bool FakeVimHandler::Private::handleInsertInEditor(const Input &input, QString *
|
|||||||
|
|
||||||
*insert = guessInsertCommand(pos1, pos2, len1, len2);
|
*insert = guessInsertCommand(pos1, pos2, len1, len2);
|
||||||
|
|
||||||
|
endEditBlock();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6730,7 +6751,6 @@ bool FakeVimHandler::Private::passEventToEditor(QEvent &event)
|
|||||||
removeEventFilter();
|
removeEventFilter();
|
||||||
|
|
||||||
QTextCursor tc = m_cursor;
|
QTextCursor tc = m_cursor;
|
||||||
tc.setPosition(tc.position());
|
|
||||||
EDITOR(setTextCursor(tc));
|
EDITOR(setTextCursor(tc));
|
||||||
bool accepted = QApplication::sendEvent(editor(), &event);
|
bool accepted = QApplication::sendEvent(editor(), &event);
|
||||||
|
|
||||||
@@ -6985,23 +7005,31 @@ void FakeVimHandler::Private::joinPreviousEditBlock()
|
|||||||
UNDO_DEBUG("JOIN");
|
UNDO_DEBUG("JOIN");
|
||||||
if (m_breakEditBlock) {
|
if (m_breakEditBlock) {
|
||||||
beginEditBlock();
|
beginEditBlock();
|
||||||
|
QTextCursor tc(document());
|
||||||
|
tc.beginEditBlock();
|
||||||
|
tc.insertText(_("X"));
|
||||||
|
tc.deletePreviousChar();
|
||||||
|
tc.endEditBlock();
|
||||||
} else {
|
} else {
|
||||||
if (m_editBlockLevel == 0)
|
if (m_editBlockLevel == 0)
|
||||||
m_cursor = cursor();
|
m_cursor = cursor();
|
||||||
++m_editBlockLevel;
|
++m_editBlockLevel;
|
||||||
cursor().joinPreviousEditBlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeVimHandler::Private::beginEditBlock(bool rememberPosition)
|
void FakeVimHandler::Private::beginEditBlock(bool largeEditBlock)
|
||||||
{
|
{
|
||||||
UNDO_DEBUG("BEGIN EDIT BLOCK");
|
UNDO_DEBUG("BEGIN EDIT BLOCK");
|
||||||
if (m_editBlockLevel == 0)
|
if (m_editBlockLevel == 0)
|
||||||
m_cursor = cursor();
|
m_cursor = cursor();
|
||||||
|
|
||||||
|
if (m_editBlockLevel == 0 || m_largeEditBlockRevision != -1) {
|
||||||
|
if (largeEditBlock)
|
||||||
|
m_largeEditBlockRevision = revision();
|
||||||
|
else
|
||||||
|
pushUndoState(false);
|
||||||
|
}
|
||||||
++m_editBlockLevel;
|
++m_editBlockLevel;
|
||||||
cursor().beginEditBlock();
|
|
||||||
if (rememberPosition)
|
|
||||||
setUndoPosition(false);
|
|
||||||
m_breakEditBlock = false;
|
m_breakEditBlock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7011,9 +7039,30 @@ void FakeVimHandler::Private::endEditBlock()
|
|||||||
QTC_ASSERT(m_editBlockLevel > 0,
|
QTC_ASSERT(m_editBlockLevel > 0,
|
||||||
qDebug() << "beginEditBlock() not called before endEditBlock()!"; return);
|
qDebug() << "beginEditBlock() not called before endEditBlock()!"; return);
|
||||||
--m_editBlockLevel;
|
--m_editBlockLevel;
|
||||||
cursor().endEditBlock();
|
|
||||||
if (m_editBlockLevel == 0)
|
if (m_editBlockLevel == 0)
|
||||||
setCursor(m_cursor);
|
setCursor(m_cursor);
|
||||||
|
if (m_largeEditBlockRevision != -1)
|
||||||
|
m_largeEditBlockRevision = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeVimHandler::Private::onContentsChanged()
|
||||||
|
{
|
||||||
|
if (!document()->isUndoAvailable())
|
||||||
|
m_undo.clear();
|
||||||
|
|
||||||
|
const int rev = revision();
|
||||||
|
if (lastUndoRevision() > rev) {
|
||||||
|
m_redo.clear();
|
||||||
|
while (lastUndoRevision() > rev)
|
||||||
|
m_undo.pop();
|
||||||
|
} else {
|
||||||
|
while (!m_redo.empty() && m_redo.top().revision < rev)
|
||||||
|
m_redo.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// External change.
|
||||||
|
if (m_editBlockLevel == 0 && document()->isUndoAvailable())
|
||||||
|
pushUndoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
char FakeVimHandler::Private::currentModeCode() const
|
char FakeVimHandler::Private::currentModeCode() const
|
||||||
@@ -7038,17 +7087,33 @@ void FakeVimHandler::Private::undoRedo(bool undo)
|
|||||||
QStack<State> &stack = undo ? m_undo : m_redo;
|
QStack<State> &stack = undo ? m_undo : m_redo;
|
||||||
QStack<State> &stack2 = undo ? m_redo : m_undo;
|
QStack<State> &stack2 = undo ? m_redo : m_undo;
|
||||||
|
|
||||||
|
bool validState = !stack.empty();
|
||||||
|
State state = validState ? stack.pop() : State();
|
||||||
|
|
||||||
|
++m_editBlockLevel;
|
||||||
|
const int firstLine = firstVisibleLine();
|
||||||
|
|
||||||
CursorPosition lastPos(cursor());
|
CursorPosition lastPos(cursor());
|
||||||
const int current = revision();
|
const int current = revision();
|
||||||
if (undo)
|
const int prevRev = validState ? state.revision : current;
|
||||||
EDITOR(undo());
|
int rev = current;
|
||||||
else
|
int last;
|
||||||
EDITOR(redo());
|
if (undo) {
|
||||||
const int rev = revision();
|
do {
|
||||||
|
last = rev;
|
||||||
|
EDITOR(undo());
|
||||||
|
rev = revision();
|
||||||
|
} while (prevRev < rev && last != rev);
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
last = rev;
|
||||||
|
EDITOR(redo());
|
||||||
|
rev = revision();
|
||||||
|
} while (prevRev > rev && last != rev);
|
||||||
|
}
|
||||||
|
|
||||||
// rewind/forward to last saved revision
|
scrollToLine(firstLine);
|
||||||
while (!stack.empty() && stack.top().revision > rev)
|
--m_editBlockLevel;
|
||||||
stack.pop();
|
|
||||||
|
|
||||||
if (current == rev) {
|
if (current == rev) {
|
||||||
const QString msg = undo ? FakeVimHandler::tr("Already at oldest change.")
|
const QString msg = undo ? FakeVimHandler::tr("Already at oldest change.")
|
||||||
@@ -7058,8 +7123,7 @@ void FakeVimHandler::Private::undoRedo(bool undo)
|
|||||||
}
|
}
|
||||||
clearMessage();
|
clearMessage();
|
||||||
|
|
||||||
if (!stack.empty()) {
|
if (validState) {
|
||||||
State &state = stack.top();
|
|
||||||
if (state.revision == rev) {
|
if (state.revision == rev) {
|
||||||
m_lastChangePosition = state.position;
|
m_lastChangePosition = state.position;
|
||||||
Marks marks = m_marks;
|
Marks marks = m_marks;
|
||||||
@@ -7071,7 +7135,9 @@ void FakeVimHandler::Private::undoRedo(bool undo)
|
|||||||
setCursorPosition(m_lastChangePosition);
|
setCursorPosition(m_lastChangePosition);
|
||||||
setAnchor();
|
setAnchor();
|
||||||
state.revision = current;
|
state.revision = current;
|
||||||
stack2.push(stack.pop());
|
stack2.push(state);
|
||||||
|
} else {
|
||||||
|
stack.push(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7507,7 +7573,7 @@ bool FakeVimHandler::Private::changeNumberTextObject(int count)
|
|||||||
repl.prepend(prefix);
|
repl.prepend(prefix);
|
||||||
|
|
||||||
pos += block.position();
|
pos += block.position();
|
||||||
setUndoPosition();
|
pushUndoState();
|
||||||
setAnchorAndPosition(pos, pos + len);
|
setAnchorAndPosition(pos, pos + len);
|
||||||
replaceText(currentRange(), repl);
|
replaceText(currentRange(), repl);
|
||||||
setPosition(pos + repl.size() - 1);
|
setPosition(pos + repl.size() - 1);
|
||||||
|
Reference in New Issue
Block a user