FakeVim: Improve handling of content changes

..when indenter or auto completer may interfere.

Task-number: QTCREATORBUG-26195
Change-Id: Iaf0eefd74344423409fa0c22f8e3ea618b4c9930
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Stenger
2021-12-03 10:56:07 +01:00
parent 104ea4accc
commit e158bfe618

View File

@@ -8261,7 +8261,8 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
g.dotCommand = "i"; g.dotCommand = "i";
resetCount(); resetCount();
} }
int indentation = 0;
bool changedAtEnd = false;
// 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 >= insertState.pos1 && position <= insertState.pos2) { if (position + charsRemoved >= insertState.pos1 && position <= insertState.pos2) {
if (charsRemoved > 0) { if (charsRemoved > 0) {
@@ -8280,17 +8281,39 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
if (position < insertState.pos1) { if (position < insertState.pos1) {
// <BACKSPACE> // <BACKSPACE>
const int backspaceCount = insertState.pos1 - position; const int backspaceCount = insertState.pos1 - position;
if (backspaceCount != charsRemoved || (oldPosition == charsRemoved && wholeDocumentChanged)) { const QString inserted = textAt(position, position + charsAdded);
const QString unified = inserted.startsWith('\n') ? inserted.mid(1) : inserted;
changedAtEnd = unified.startsWith(insertState.textBeforeCursor);
int indentNew = 0;
for (int i = 0, end = unified.size(); i < end; ++i) {
if (unified.at(i) != ' ')
break;
++indentNew;
}
int indentOld = 0;
for (int i = 0, end = insertState.textBeforeCursor.size(); i < end; ++i) {
if (insertState.textBeforeCursor.at(i) != ' ')
break;
--indentOld;
}
indentation = indentNew + indentOld;
if ((backspaceCount != charsRemoved && indentation == 0 && !changedAtEnd)
|| (oldPosition == charsRemoved && wholeDocumentChanged)) {
invalidateInsertState(); invalidateInsertState();
} else { } else {
const QString inserted = textAt(position, oldPosition); const QString removed = insertState.textBeforeCursor.right(
const QString removed = insertState.textBeforeCursor.right(backspaceCount); qMax(backspaceCount, charsRemoved));
// Ignore backspaces if same text was just inserted. if (indentation != 0 || changedAtEnd) {
if ( !inserted.endsWith(removed) ) { // automatic indent by electric chars / skipping of automatic inserted
insertState.pos1 = position + backspaceCount + indentation;
insertState.pos2 = position + charsAdded;
} else if ( !inserted.endsWith(removed) ) {
insertState.backspaces += backspaceCount; insertState.backspaces += backspaceCount;
insertState.pos1 = position; insertState.pos1 = position;
insertState.pos2 = qMax(position, insertState.pos2 - backspaceCount); insertState.pos2 = qMax(position, insertState.pos2 - backspaceCount);
} } // Ignore backspaces if same text was just inserted.
} }
} else if (position + charsRemoved > insertState.pos2) { } else if (position + charsRemoved > insertState.pos2) {
// <DELETE> // <DELETE>
@@ -8309,7 +8332,8 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
} }
const int newPosition = position + charsAdded; const int newPosition = position + charsAdded;
insertState.pos2 = qMax(insertState.pos2 + charsAdded - charsRemoved, newPosition); if (indentation == 0 && !changedAtEnd) // (un)indented has pos2 set correctly already
insertState.pos2 = qMax(insertState.pos2 + charsAdded - charsRemoved, newPosition);
insertState.textBeforeCursor = textAt(block().position(), newPosition); insertState.textBeforeCursor = textAt(block().position(), newPosition);
} }
} }