diff --git a/src/utils/vvim.cpp b/src/utils/vvim.cpp index fea5112b..f64099eb 100644 --- a/src/utils/vvim.cpp +++ b/src/utils/vvim.cpp @@ -1018,26 +1018,18 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos) case Qt::Key_S: { - if (modifiers == Qt::NoModifier) { - // 1. If there is selection, delete the selected text. - // 2. Otherwise, if cursor is not at the end of block, delete the - // character after current cursor. - // 3. Enter Insert mode. - QTextCursor cursor = m_editor->textCursor(); - if (cursor.hasSelection() || !cursor.atBlockEnd()) { - cursor.deleteChar(); - m_editor->setTextCursor(cursor); - } + tryGetRepeatToken(m_keys, m_tokens); + if (!m_keys.isEmpty() || hasActionToken()) { + break; + } - 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) { // S, change current line. - tryGetRepeatToken(m_keys, m_tokens); - if (hasActionToken() || !m_keys.isEmpty()) { - // Invalid sequence. - break; - } - addActionToken(Action::Change); addRangeToken(Range::Line); processCommand(m_tokens); @@ -1294,25 +1286,15 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos) } } else { // The first d, an Action. - if (m_mode == VimMode::Visual || m_mode == VimMode::VisualLine) { - QTextCursor cursor = m_editor->textCursor(); - 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); - } else if (m_mode == VimMode::VisualLine) { - VEditUtils::removeBlock(cursor); - saveToRegister("\n"); - } - - cursor.endEditBlock(); - m_editor->setTextCursor(cursor); + addActionToken(Action::Delete); + if (checkMode(VimMode::Visual) || checkMode(VimMode::VisualLine)) { + // Movement will be ignored. + addMovementToken(Movement::Left); + processCommand(m_tokens); setMode(VimMode::Normal); break; } - addActionToken(Action::Delete); goto accept; } } 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) { // x, or X to delete one char. tryGetRepeatToken(m_keys, m_tokens); - if (!m_keys.isEmpty()) { + if (!m_keys.isEmpty() || hasActionToken()) { break; } - if (!hasActionToken()) { - addActionToken(Action::Delete); - addMovementToken(modifiers == Qt::ShiftModifier ? Movement::Left - : Movement::Right); - processCommand(m_tokens); + addActionToken(Action::Delete); + if (modifiers == Qt::ShiftModifier) { + if (checkMode(VimMode::Visual) || checkMode(VimMode::VisualLine)) { + // X, same as dd. + 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; } @@ -1695,28 +1687,15 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos) } } else { // The first c, an action. - if (m_mode == VimMode::Visual || m_mode == VimMode::VisualLine) { - 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"); - } + addActionToken(Action::Change); - cursor.endEditBlock(); - m_editor->setTextCursor(cursor); - setMode(VimMode::Insert); + if (checkMode(VimMode::VisualLine) || checkMode(VimMode::Visual)) { + // Movement will be ignored. + addMovementToken(Movement::Left); + processCommand(m_tokens); break; } - addActionToken(Action::Change); goto accept; } } else if (modifiers == Qt::ShiftModifier) { @@ -3487,6 +3466,7 @@ void VVim::processDeleteAction(QList &p_tokens) deleteSelectedText(cursor, true); } else { VEditUtils::removeBlock(cursor); + saveToRegister("\n"); repeat = 1; } @@ -3582,6 +3562,23 @@ void VVim::processDeleteAction(QList &p_tokens) } 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); if (repeat == -1) { repeat = 1; @@ -4115,6 +4112,27 @@ void VVim::processChangeAction(QList &p_tokens) } 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); if (repeat == -1) { repeat = 1;