vim-mode: bug-fix for s, d, c in visual mode

This commit is contained in:
Le Tan 2017-09-23 10:38:50 +08:00
parent 73ede805d1
commit b04a44f82d

View File

@ -1018,26 +1018,18 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
case Qt::Key_S: case Qt::Key_S:
{ {
if (modifiers == Qt::NoModifier) { tryGetRepeatToken(m_keys, m_tokens);
// 1. If there is selection, delete the selected text. if (!m_keys.isEmpty() || hasActionToken()) {
// 2. Otherwise, if cursor is not at the end of block, delete the break;
// character after current cursor. }
// 3. Enter Insert mode.
QTextCursor cursor = m_editor->textCursor();
if (cursor.hasSelection() || !cursor.atBlockEnd()) {
cursor.deleteChar();
m_editor->setTextCursor(cursor);
}
setMode(VimMode::Insert); if (modifiers == Qt::NoModifier) {
addActionToken(Action::Change);
// Movement will be ignored in Visual mode.
addMovementToken(Movement::Right);
processCommand(m_tokens);
} else if (modifiers == Qt::ShiftModifier) { } else if (modifiers == Qt::ShiftModifier) {
// S, change current line. // S, change current line.
tryGetRepeatToken(m_keys, m_tokens);
if (hasActionToken() || !m_keys.isEmpty()) {
// Invalid sequence.
break;
}
addActionToken(Action::Change); addActionToken(Action::Change);
addRangeToken(Range::Line); addRangeToken(Range::Line);
processCommand(m_tokens); processCommand(m_tokens);
@ -1294,25 +1286,15 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
} }
} else { } else {
// The first d, an Action. // The first d, an Action.
if (m_mode == VimMode::Visual || m_mode == VimMode::VisualLine) { addActionToken(Action::Delete);
QTextCursor cursor = m_editor->textCursor(); if (checkMode(VimMode::Visual) || checkMode(VimMode::VisualLine)) {
cursor.beginEditBlock(); // Movement will be ignored.
// Different from Vim: addMovementToken(Movement::Left);
// If there is no selection in Visual mode, we do nothing. processCommand(m_tokens);
if (cursor.hasSelection()) {
deleteSelectedText(cursor, m_mode == VimMode::VisualLine);
} else if (m_mode == VimMode::VisualLine) {
VEditUtils::removeBlock(cursor);
saveToRegister("\n");
}
cursor.endEditBlock();
m_editor->setTextCursor(cursor);
setMode(VimMode::Normal); setMode(VimMode::Normal);
break; break;
} }
addActionToken(Action::Delete);
goto accept; goto accept;
} }
} else if (modifiers == Qt::ShiftModifier) { } else if (modifiers == Qt::ShiftModifier) {
@ -1601,17 +1583,27 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
if (modifiers == Qt::ShiftModifier || modifiers == Qt::NoModifier) { if (modifiers == Qt::ShiftModifier || modifiers == Qt::NoModifier) {
// x, or X to delete one char. // x, or X to delete one char.
tryGetRepeatToken(m_keys, m_tokens); tryGetRepeatToken(m_keys, m_tokens);
if (!m_keys.isEmpty()) { if (!m_keys.isEmpty() || hasActionToken()) {
break; break;
} }
if (!hasActionToken()) { addActionToken(Action::Delete);
addActionToken(Action::Delete); if (modifiers == Qt::ShiftModifier) {
addMovementToken(modifiers == Qt::ShiftModifier ? Movement::Left if (checkMode(VimMode::Visual) || checkMode(VimMode::VisualLine)) {
: Movement::Right); // X, same as dd.
processCommand(m_tokens); addRangeToken(Range::Line);
} else {
// X, delete one char.
addMovementToken(Movement::Left);
}
} else {
// x.
// Movement will be ignored in Visual mode.
addMovementToken(Movement::Right);
} }
processCommand(m_tokens);
setMode(VimMode::Normal);
break; break;
} }
@ -1695,28 +1687,15 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
} }
} else { } else {
// The first c, an action. // The first c, an action.
if (m_mode == VimMode::Visual || m_mode == VimMode::VisualLine) { addActionToken(Action::Change);
QTextCursor cursor = m_editor->textCursor();
int pos = cursor.selectionStart();
cursor.beginEditBlock();
// Different from Vim:
// If there is no selection in Visual mode, we do nothing.
if (cursor.hasSelection()) {
deleteSelectedText(cursor, m_mode == VimMode::VisualLine);
if (m_mode == VimMode::VisualLine) {
insertChangeBlockAfterDeletion(cursor, pos);
}
} else if (m_mode == VimMode::VisualLine) {
saveToRegister("\n");
}
cursor.endEditBlock(); if (checkMode(VimMode::VisualLine) || checkMode(VimMode::Visual)) {
m_editor->setTextCursor(cursor); // Movement will be ignored.
setMode(VimMode::Insert); addMovementToken(Movement::Left);
processCommand(m_tokens);
break; break;
} }
addActionToken(Action::Change);
goto accept; goto accept;
} }
} else if (modifiers == Qt::ShiftModifier) { } else if (modifiers == Qt::ShiftModifier) {
@ -3487,6 +3466,7 @@ void VVim::processDeleteAction(QList<Token> &p_tokens)
deleteSelectedText(cursor, true); deleteSelectedText(cursor, true);
} else { } else {
VEditUtils::removeBlock(cursor); VEditUtils::removeBlock(cursor);
saveToRegister("\n");
repeat = 1; repeat = 1;
} }
@ -3582,6 +3562,23 @@ void VVim::processDeleteAction(QList<Token> &p_tokens)
} }
cursor.beginEditBlock(); cursor.beginEditBlock();
if (checkMode(VimMode::VisualLine) || checkMode(VimMode::Visual)) {
// Visual mode, omitting repeat and movement.
// Different from Vim:
// If there is no selection in Visual mode, we do nothing.
if (cursor.hasSelection()) {
hasMoved = true;
deleteSelectedText(cursor, m_mode == VimMode::VisualLine);
} else if (checkMode(VimMode::Visual)) {
hasMoved = true;
VEditUtils::removeBlock(cursor);
saveToRegister("\n");
}
cursor.endEditBlock();
goto exit;
}
hasMoved = processMovement(cursor, moveMode, to, repeat); hasMoved = processMovement(cursor, moveMode, to, repeat);
if (repeat == -1) { if (repeat == -1) {
repeat = 1; repeat = 1;
@ -4115,6 +4112,27 @@ void VVim::processChangeAction(QList<Token> &p_tokens)
} }
cursor.beginEditBlock(); cursor.beginEditBlock();
if (checkMode(VimMode::VisualLine) || checkMode(VimMode::Visual)) {
// Visual mode, omitting repeat and movement.
// Different from Vim:
// If there is no selection in Visual mode, we do nothing.
bool visualLine = checkMode(VimMode::VisualLine);
if (cursor.hasSelection()) {
hasMoved = true;
int pos = cursor.selectionStart();
deleteSelectedText(cursor, visualLine);
if (visualLine) {
insertChangeBlockAfterDeletion(cursor, pos);
}
} else if (visualLine) {
hasMoved = true;
saveToRegister("\n");
}
cursor.endEditBlock();
goto exit;
}
hasMoved = processMovement(cursor, moveMode, to, repeat); hasMoved = processMovement(cursor, moveMode, to, repeat);
if (repeat == -1) { if (repeat == -1) {
repeat = 1; repeat = 1;