fakevim: rework undo/redo cursor positioning

Change-Id: I1daa788377295fb1446f31d9a74b9fd0df6920d1
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
hjk
2011-12-27 17:39:56 +01:00
parent c137cd9b5a
commit 29eff52529

View File

@@ -862,8 +862,6 @@ public:
{ return document()->characterAt(position()); } { return document()->characterAt(position()); }
void beginEditBlock() void beginEditBlock()
{ UNDO_DEBUG("BEGIN EDIT BLOCK"); cursor().beginEditBlock(); } { UNDO_DEBUG("BEGIN EDIT BLOCK"); cursor().beginEditBlock(); }
void beginEditBlock(int pos)
{ setUndoPosition(pos); cursor().beginEditBlock(); }
void endEditBlock() void endEditBlock()
{ UNDO_DEBUG("END EDIT BLOCK"); cursor().endEditBlock(); } { UNDO_DEBUG("END EDIT BLOCK"); cursor().endEditBlock(); }
void joinPreviousEditBlock() void joinPreviousEditBlock()
@@ -982,7 +980,7 @@ public:
// undo handling // undo handling
void undo(); void undo();
void redo(); void redo();
void setUndoPosition(int pos); void setUndoPosition();
QMap<int, int> m_undoCursorPosition; // revision -> position QMap<int, int> m_undoCursorPosition; // revision -> position
// extra data for '.' // extra data for '.'
@@ -1433,7 +1431,6 @@ EventResult FakeVimHandler::Private::handleKey(const Input &input)
EventResult FakeVimHandler::Private::handleKey2() EventResult FakeVimHandler::Private::handleKey2()
{ {
setUndoPosition(position());
if (m_mode == InsertMode) { if (m_mode == InsertMode) {
EventResult result = EventUnhandled; EventResult result = EventUnhandled;
foreach (const Input &in, g.pendingInput) { foreach (const Input &in, g.pendingInput) {
@@ -1484,9 +1481,13 @@ void FakeVimHandler::Private::stopIncrementalFind()
} }
} }
void FakeVimHandler::Private::setUndoPosition(int pos) void FakeVimHandler::Private::setUndoPosition()
{ {
m_undoCursorPosition[document()->availableUndoSteps()] = pos; int pos = qMin(position(), anchor());
if (m_visualMode == VisualLineMode)
pos = firstPositionInLine(lineForPosition(pos));
const int rev = document()->availableUndoSteps();
m_undoCursorPosition[rev] = pos;
} }
void FakeVimHandler::Private::moveDown(int n) void FakeVimHandler::Private::moveDown(int n)
@@ -1607,7 +1608,6 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
if (m_movetype == MoveLineWise) if (m_movetype == MoveLineWise)
insertAutomaticIndentation(true); insertAutomaticIndentation(true);
endEditBlock(); endEditBlock();
setUndoPosition(position());
enterInsertMode(); enterInsertMode();
m_submode = NoSubMode; m_submode = NoSubMode;
} else if (m_submode == DeleteSubMode) { } else if (m_submode == DeleteSubMode) {
@@ -1656,16 +1656,17 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
handleStartOfLine(); handleStartOfLine();
endEditBlock(); endEditBlock();
} else if (m_submode == IndentSubMode) { } else if (m_submode == IndentSubMode) {
setUndoPosition();
recordJump(); recordJump();
beginEditBlock();
indentSelectedText(); indentSelectedText();
endEditBlock();
m_submode = NoSubMode; m_submode = NoSubMode;
} else if (m_submode == ShiftRightSubMode) { } else if (m_submode == ShiftRightSubMode) {
setUndoPosition();
recordJump(); recordJump();
shiftRegionRight(1); shiftRegionRight(1);
m_submode = NoSubMode; m_submode = NoSubMode;
} else if (m_submode == ShiftLeftSubMode) { } else if (m_submode == ShiftLeftSubMode) {
setUndoPosition();
recordJump(); recordJump();
shiftRegionLeft(1); shiftRegionLeft(1);
m_submode = NoSubMode; m_submode = NoSubMode;
@@ -1926,6 +1927,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
m_rangemode = RangeLineMode; m_rangemode = RangeLineMode;
} else if (m_submode == ReplaceSubMode) { } else if (m_submode == ReplaceSubMode) {
if (isVisualMode()) { if (isVisualMode()) {
setUndoPosition();
m_lastChangePosition = position(); m_lastChangePosition = position();
if (isVisualLineMode()) if (isVisualLineMode())
m_rangemode = RangeLineMode; m_rangemode = RangeLineMode;
@@ -1940,6 +1942,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
transformText(range, tr, input.asChar()); transformText(range, tr, input.asChar());
setPosition(range.beginPos); setPosition(range.beginPos);
} else if (count() <= rightDist()) { } else if (count() <= rightDist()) {
setUndoPosition();
m_lastChangePosition = position(); m_lastChangePosition = position();
setAnchor(); setAnchor();
moveRight(count()); moveRight(count());
@@ -1959,6 +1962,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
m_submode = NoSubMode; m_submode = NoSubMode;
finishMovement(); finishMovement();
} else if (m_submode == ChangeSubMode && input.is('c')) { // tested } else if (m_submode == ChangeSubMode && input.is('c')) { // tested
setUndoPosition();
m_lastChangePosition = position(); m_lastChangePosition = position();
moveToStartOfLine(); moveToStartOfLine();
setAnchor(); setAnchor();
@@ -1969,6 +1973,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
setDotCommand("%1cc", count()); setDotCommand("%1cc", count());
finishMovement(); finishMovement();
} else if (m_submode == DeleteSubMode && input.is('d')) { // tested } else if (m_submode == DeleteSubMode && input.is('d')) { // tested
setUndoPosition();
m_lastChangePosition = position(); m_lastChangePosition = position();
m_movetype = MoveLineWise; m_movetype = MoveLineWise;
int endPos = firstPositionInLine(lineForPosition(position()) + count() - 1); int endPos = firstPositionInLine(lineForPosition(position()) + count() - 1);
@@ -2198,29 +2203,36 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
replay(savedCommand, count()); replay(savedCommand, count());
enterCommandMode(); enterCommandMode();
g.dotCommand = savedCommand; g.dotCommand = savedCommand;
} else if (input.is('<') && isNoVisualMode()) { } else if (input.is('<')) {
m_submode = ShiftLeftSubMode; setUndoPosition();
} else if (input.is('<') && isVisualMode()) { if (isNoVisualMode()) {
shiftRegionLeft(1); m_submode = ShiftLeftSubMode;
leaveVisualMode(); } else {
} else if (input.is('>') && isNoVisualMode()) { shiftRegionLeft(1);
m_submode = ShiftRightSubMode; leaveVisualMode();
} else if (input.is('>') && isVisualMode()) { }
shiftRegionRight(1); } else if (input.is('>')) {
leaveVisualMode(); setUndoPosition();
} else if (input.is('=') && isNoVisualMode()) { if (isNoVisualMode()) {
m_submode = IndentSubMode; m_submode = ShiftRightSubMode;
} else if (input.is('=') && isVisualMode()) { } else {
beginEditBlock(); shiftRegionRight(1);
indentSelectedText(); leaveVisualMode();
endEditBlock(); }
leaveVisualMode(); } else if (input.is('=')) {
setUndoPosition();
if (isNoVisualMode()) {
m_submode = IndentSubMode;
} else {
indentSelectedText();
leaveVisualMode();
}
} else if (input.is('%')) { } else if (input.is('%')) {
moveToMatchingParanthesis(); moveToMatchingParanthesis();
finishMovement(); finishMovement();
} else if ((!isVisualMode() && input.is('a')) || (isVisualMode() && input.is('A'))) { } else if ((!isVisualMode() && input.is('a')) || (isVisualMode() && input.is('A'))) {
leaveVisualMode(); leaveVisualMode();
setUndoPosition(position()); setUndoPosition();
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
m_lastInsertion.clear(); m_lastInsertion.clear();
@@ -2228,7 +2240,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
moveRight(); moveRight();
updateMiniBuffer(); updateMiniBuffer();
} else if (input.is('A')) { } else if (input.is('A')) {
setUndoPosition(position()); setUndoPosition();
breakEditBlock(); breakEditBlock();
moveBehindEndOfLine(); moveBehindEndOfLine();
setAnchor(); setAnchor();
@@ -2249,6 +2261,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
setTargetColumn(); setTargetColumn();
finishMovement(); finishMovement();
} else if (input.is('c') && isNoVisualMode()) { } else if (input.is('c') && isNoVisualMode()) {
setUndoPosition();
if (atEndOfLine()) if (atEndOfLine())
moveLeft(); moveLeft();
setAnchor(); setAnchor();
@@ -2399,7 +2412,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
finishMovement(); finishMovement();
} else if (!isVisualMode() && (input.is('i') || input.isKey(Key_Insert))) { } else if (!isVisualMode() && (input.is('i') || input.isKey(Key_Insert))) {
setDotCommand(QString(QLatin1Char('i'))); // setDotCommand("%1i", count()); setDotCommand(QString(QLatin1Char('i'))); // setDotCommand("%1i", count());
setUndoPosition(position()); setUndoPosition();
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
updateMiniBuffer(); updateMiniBuffer();
@@ -2416,6 +2429,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
EventResult handled = EventHandled; EventResult handled = EventHandled;
if (input.is('I')) { if (input.is('I')) {
setUndoPosition();
setDotCommand(QString(QLatin1Char('I'))); // setDotCommand("%1I", count()); setDotCommand(QString(QLatin1Char('I'))); // setDotCommand("%1I", count());
if (isVisualMode()) { if (isVisualMode()) {
int beginLine = lineForPosition(anchor()); int beginLine = lineForPosition(anchor());
@@ -2430,7 +2444,6 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
m_gflag = false; m_gflag = false;
//m_tc.clearSelection(); //m_tc.clearSelection();
} }
setUndoPosition(position());
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
} else if (input.isControl('i')) { } else if (input.isControl('i')) {
@@ -2530,10 +2543,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
updateSelection(); updateSelection();
} else if (input.is('o')) { } else if (input.is('o')) {
setDotCommand("%1o", count()); setDotCommand("%1o", count());
setUndoPosition(position()); setUndoPosition();
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
beginEditBlock(position()); beginEditBlock();
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
moveBehindEndOfLine(); moveBehindEndOfLine();
insertText(QString("\n")); insertText(QString("\n"));
@@ -2541,10 +2554,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
endEditBlock(); endEditBlock();
} else if (input.is('O')) { } else if (input.is('O')) {
setDotCommand("%1O", count()); setDotCommand("%1O", count());
setUndoPosition(position()); setUndoPosition();
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
beginEditBlock(position()); beginEditBlock();
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
moveToStartOfLine(); moveToStartOfLine();
insertText(QString("\n")); insertText(QString("\n"));
@@ -2563,15 +2576,17 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
setDotCommand("%1p", count()); setDotCommand("%1p", count());
finishMovement(); finishMovement();
} else if (input.is('r')) { } else if (input.is('r')) {
setUndoPosition();
m_submode = ReplaceSubMode; m_submode = ReplaceSubMode;
} else if (!isVisualMode() && input.is('R')) { } else if (!isVisualMode() && input.is('R')) {
setUndoPosition(position()); setUndoPosition();
breakEditBlock(); breakEditBlock();
enterReplaceMode(); enterReplaceMode();
updateMiniBuffer(); updateMiniBuffer();
} else if (input.isControl('r')) { } else if (input.isControl('r')) {
redo(); redo();
} else if (input.is('s') && isVisualBlockMode()) { } else if (input.is('s') && isVisualBlockMode()) {
setUndoPosition();
Range range(position(), anchor(), RangeBlockMode); Range range(position(), anchor(), RangeBlockMode);
int beginLine = lineForPosition(anchor()); int beginLine = lineForPosition(anchor());
int endLine = lineForPosition(position()); int endLine = lineForPosition(position());
@@ -2580,10 +2595,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
yankText(range, m_register); yankText(range, m_register);
removeText(range); removeText(range);
setDotCommand("%1s", count()); setDotCommand("%1s", count());
setUndoPosition(position());
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
} else if (input.is('s')) { } else if (input.is('s')) {
setUndoPosition();
leaveVisualMode(); leaveVisualMode();
if (atEndOfLine()) if (atEndOfLine())
moveLeft(); moveLeft();
@@ -2594,10 +2609,10 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
setDotCommand("%1s", count()); setDotCommand("%1s", count());
m_opcount.clear(); m_opcount.clear();
m_mvcount.clear(); m_mvcount.clear();
setUndoPosition(position());
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
} else if (input.is('S')) { } else if (input.is('S')) {
setUndoPosition();
beginEditBlock(); beginEditBlock();
if (!isVisualMode()) { if (!isVisualMode()) {
const int line = cursorLine() + 1; const int line = cursorLine() + 1;
@@ -2606,7 +2621,6 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
setAnchorAndPosition(anc, pos); setAnchorAndPosition(anc, pos);
} }
setDotCommand("%1S", count()); setDotCommand("%1S", count());
setUndoPosition(position());
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
m_submode = ChangeSubMode; m_submode = ChangeSubMode;
@@ -3625,7 +3639,7 @@ bool FakeVimHandler::Private::handleExWriteCommand(const ExCommand &cmd)
if (endLine == -1) if (endLine == -1)
endLine = linesInDocument(); endLine = linesInDocument();
//qDebug() << "LINES: " << beginLine << endLine; //qDebug() << "LINES: " << beginLine << endLine;
QString prefix = cmd.args; //QString prefix = cmd.args;
const bool forced = cmd.hasBang; const bool forced = cmd.hasBang;
//const bool quit = prefix.contains(QChar('q')) || prefix.contains(QChar('x')); //const bool quit = prefix.contains(QChar('q')) || prefix.contains(QChar('x'));
//const bool quitAll = quit && prefix.contains(QChar('a')); //const bool quitAll = quit && prefix.contains(QChar('a'));
@@ -3711,7 +3725,7 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :!
proc.closeWriteChannel(); proc.closeWriteChannel();
proc.waitForFinished(); proc.waitForFinished();
QString result = QString::fromUtf8(proc.readAllStandardOutput()); QString result = QString::fromUtf8(proc.readAllStandardOutput());
beginEditBlock(targetPosition); beginEditBlock();
removeText(currentRange()); removeText(currentRange());
insertText(result); insertText(result);
setPosition(targetPosition); setPosition(targetPosition);
@@ -4052,6 +4066,7 @@ void FakeVimHandler::Private::moveToFirstNonBlankOnLine()
void FakeVimHandler::Private::indentSelectedText(QChar typedChar) void FakeVimHandler::Private::indentSelectedText(QChar typedChar)
{ {
beginEditBlock();
setTargetColumn(); setTargetColumn();
int beginLine = qMin(lineForPosition(position()), lineForPosition(anchor())); int beginLine = qMin(lineForPosition(position()), lineForPosition(anchor()));
int endLine = qMax(lineForPosition(position()), lineForPosition(anchor())); int endLine = qMax(lineForPosition(position()), lineForPosition(anchor()));
@@ -4063,6 +4078,7 @@ void FakeVimHandler::Private::indentSelectedText(QChar typedChar)
handleStartOfLine(); handleStartOfLine();
setTargetColumn(); setTargetColumn();
setDotCommand("%1==", endLine - beginLine + 1); setDotCommand("%1==", endLine - beginLine + 1);
endEditBlock();
} }
void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar) void FakeVimHandler::Private::indentText(const Range &range, QChar typedChar)
@@ -4098,7 +4114,7 @@ void FakeVimHandler::Private::shiftRegionRight(int repeat)
targetPos = firstPositionInLine(beginLine); targetPos = firstPositionInLine(beginLine);
const int sw = config(ConfigShiftWidth).toInt(); const int sw = config(ConfigShiftWidth).toInt();
beginEditBlock(targetPos); beginEditBlock();
for (int line = beginLine; line <= endLine; ++line) { for (int line = beginLine; line <= endLine; ++line) {
QString data = lineContents(line); QString data = lineContents(line);
const Column col = indentation(data); const Column col = indentation(data);
@@ -4127,7 +4143,7 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat)
if (hasConfig(ConfigStartOfLine)) if (hasConfig(ConfigStartOfLine))
targetPos = firstPositionInLine(beginLine); targetPos = firstPositionInLine(beginLine);
beginEditBlock(targetPos); beginEditBlock();
for (int line = endLine; line >= beginLine; --line) { for (int line = endLine; line >= beginLine; --line) {
int pos = firstPositionInLine(line); int pos = firstPositionInLine(line);
const QString text = lineContents(line); const QString text = lineContents(line);
@@ -4479,7 +4495,7 @@ QString FakeVimHandler::Private::selectText(const Range &range) const
int firstPos = firstPositionInLine(lineForPosition(range.beginPos)); int firstPos = firstPositionInLine(lineForPosition(range.beginPos));
int lastLine = lineForPosition(range.endPos); int lastLine = lineForPosition(range.endPos);
bool endOfDoc = lastLine == document()->lastBlock().blockNumber() + 1; bool endOfDoc = lastLine == document()->lastBlock().blockNumber() + 1;
int lastPos = endOfDoc ? lastPositionInDocument() : firstPositionInLine(lastLine + 1); int lastPos = endOfDoc ? lastPositionInDocument() : firstPositionInLine(lastLine + 1);
tc.setPosition(firstPos, MoveAnchor); tc.setPosition(firstPos, MoveAnchor);
tc.setPosition(lastPos, KeepAnchor); tc.setPosition(lastPos, KeepAnchor);
return tc.selection().toPlainText() + QString((endOfDoc? "\n" : "")); return tc.selection().toPlainText() + QString((endOfDoc? "\n" : ""));
@@ -4539,7 +4555,7 @@ void FakeVimHandler::Private::transformText(const Range &range,
} }
case RangeLineMode: case RangeLineMode:
case RangeLineModeExclusive: { case RangeLineModeExclusive: {
beginEditBlock(range.beginPos); beginEditBlock();
tc.setPosition(range.beginPos, MoveAnchor); tc.setPosition(range.beginPos, MoveAnchor);
tc.movePosition(StartOfLine, MoveAnchor); tc.movePosition(StartOfLine, MoveAnchor);
tc.setPosition(range.endPos, KeepAnchor); tc.setPosition(range.endPos, KeepAnchor);
@@ -4579,7 +4595,7 @@ void FakeVimHandler::Private::transformText(const Range &range,
if (range.rangemode == RangeBlockAndTailMode) if (range.rangemode == RangeBlockAndTailMode)
endColumn = INT_MAX - 1; endColumn = INT_MAX - 1;
QTextBlock block = document()->findBlockByNumber(endLine - 1); QTextBlock block = document()->findBlockByNumber(endLine - 1);
beginEditBlock(range.beginPos); beginEditBlock();
for (int i = beginLine; i <= endLine && block.isValid(); ++i) { for (int i = beginLine; i <= endLine && block.isValid(); ++i) {
int bCol = qMin(beginColumn, block.length() - 1); int bCol = qMin(beginColumn, block.length() - 1);
int eCol = qMin(endColumn + 1, block.length() - 1); int eCol = qMin(endColumn + 1, block.length() - 1);