[frameworks/ktexteditor] /: vi-mode: Update view selection when switching modes
Christoph Cullmann <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit ad3d4a782afc9e8c69dd5a28213bd6a48bb24c63 by Christoph Cullmann, on behalf of Ismael Asensio.
Committed on 20/07/2026 at 21:22.
Pushed by cullmann into branch 'master'.
vi-mode: Update view selection when switching modes
When entering a visual mode, or switching between them, the properties
of the underlying view need to be kept in sync with the expected vi mode
behavior.
Extract the code into a separate method to trigger this update when
switching or entering a visual mode and not only after a cursor
movement.
M +25 -4 autotests/src/vimode/modes.cpp
M +1 -0 src/vimode/modes/modebase.cpp
M +15 -14 src/vimode/modes/visualvimode.cpp
M +4 -0 src/vimode/modes/visualvimode.h
https://invent.kde.org/frameworks/ktexteditor/-/commit/ad3d4a782afc9e8c69dd5a28213bd6a48bb24c63
diff --git a/autotests/src/vimode/modes.cpp b/autotests/src/vimode/modes.cpp
index 2a56b270f..b871ea5e8 100644
--- a/autotests/src/vimode/modes.cpp
+++ b/autotests/src/vimode/modes.cpp
@@ -1427,10 +1427,31 @@ void ModesTest::VisualCommandsTests()
}
// BUG #328277 - make sure kate doesn't crash
- BeginTest(QStringLiteral("aaa\nbbb"));
- TestPressKey(QStringLiteral("Vj>u>."));
- QCOMPARE(kate_view->renderer()->caretStyle(), KTextEditor::caretStyles::Block);
- FinishTest("aaa\nbbb");
+ {
+ BeginTest(QStringLiteral("aaa\nbbb"));
+ TestPressKey(QStringLiteral("Vj>u>."));
+ QCOMPARE(kate_view->renderer()->caretStyle(), KTextEditor::caretStyles::Block);
+ FinishTest("aaa\nbbb");
+ }
+
+ // Switch between different visual modes
+ {
+ BeginTest(QStringLiteral("aaaa\nbbbb\ncccc\ndddd"));
+ TestPressKey(QStringLiteral("3lv2j2h")); // Start charwise Visual mode
+ QCOMPARE(kate_view->selectionText(), QStringLiteral("a\nbbbb\ncc"));
+ QCOMPARE(kate_view->blockSelection(), false);
+ TestPressKey(QStringLiteral("V")); // Visual Line
+ QCOMPARE(kate_view->selectionText(), QStringLiteral("aaaa\nbbbb\ncccc"));
+ QCOMPARE(kate_view->blockSelection(), false);
+ TestPressKey(QStringLiteral("\\ctrl-v")); // Visual Block
+ QCOMPARE(kate_view->selectionText(), QStringLiteral("aaa\nbbb\nccc"));
+ QCOMPARE(kate_view->blockSelection(), true);
+ TestPressKey(QStringLiteral("v")); // Back to Visual
+ QCOMPARE(kate_view->selectionText(), QStringLiteral("a\nbbbb\ncc"));
+ QCOMPARE(kate_view->blockSelection(), false);
+ TestPressKey(QStringLiteral("v")); // Press "v" again. Exit visual mode
+ QCOMPARE(kate_view->selectionText(), QString());
+ }
}
void ModesTest::VisualExternalTests()
diff --git a/src/vimode/modes/modebase.cpp b/src/vimode/modes/modebase.cpp
index cc8fe93ee..9f8623d16 100644
--- a/src/vimode/modes/modebase.cpp
+++ b/src/vimode/modes/modebase.cpp
@@ -1058,6 +1058,7 @@ bool ModeBase::startVisualMode(ViMode mode)
if (m_viInputModeManager->isAnyVisualMode()) {
m_viInputModeManager->changeViMode(mode);
m_viInputModeManager->getViVisualMode()->setVisualModeType(mode);
+ m_viInputModeManager->getViVisualMode()->updateViewSelection();
} else {
m_viInputModeManager->viEnterVisualMode(mode);
}
diff --git a/src/vimode/modes/visualvimode.cpp b/src/vimode/modes/visualvimode.cpp
index 4b1c71c91..6c601c597 100644
--- a/src/vimode/modes/visualvimode.cpp
+++ b/src/vimode/modes/visualvimode.cpp
@@ -29,6 +29,8 @@ VisualViMode::VisualViMode(InputModeManager *viInputModeManager, KTextEditor::Vi
void VisualViMode::selectInclusive(const KTextEditor::Cursor c1, const KTextEditor::Cursor c2)
{
+ m_view->setBlockSelection(false);
+
if (c1 >= c2) {
m_view->setSelection(KTextEditor::Range(c1.line(), c1.column() + 1, c2.line(), c2.column()));
} else {
@@ -53,6 +55,7 @@ void VisualViMode::selectLines(KTextEditor::Range range)
int eline = qMax(range.start().line(), range.end().line());
int ecol = m_view->doc()->lineLength(eline) + 1;
+ m_view->setBlockSelection(false);
m_view->setSelection(KTextEditor::Range(KTextEditor::Cursor(sline, 0), KTextEditor::Cursor(eline, ecol)));
}
@@ -87,27 +90,24 @@ void VisualViMode::goToPos(const Range &r)
// Setting range for a command
m_commandRange = Range(m_start, c, m_commandRange.motionType);
- // If visual mode is blockwise
+ updateViewSelection();
+}
+
+void VisualViMode::updateViewSelection()
+{
+ KTextEditor::Cursor c = m_view->cursorPosition();
+
if (isVisualBlock()) {
selectBlockInclusive(m_start, c);
-
// Need to correct command range to make it inclusive.
- if ((c.line() < m_start.line() && c.column() > m_start.column()) || (c.line() > m_start.line() && c.column() < m_start.column())) {
+ if ((c.line() < m_start.line()) != (c.column() < m_start.column())) {
qSwap(m_commandRange.endColumn, m_commandRange.startColumn);
}
- return;
- } else {
- m_view->setBlockSelection(false);
- }
-
- // If visual mode is linewise
- if (isVisualLine()) {
+ } else if (isVisualLine()) {
selectLines(KTextEditor::Range(m_start, c));
- return;
+ } else { // If visual mode is charwise
+ selectInclusive(m_start, c);
}
-
- // If visual mode is charwise
- selectInclusive(m_start, c);
}
void VisualViMode::reset()
@@ -176,6 +176,7 @@ void VisualViMode::init()
}
m_commandRange = Range(m_start, m_start, m_commandRange.motionType);
+ updateViewSelection();
}
void VisualViMode::setVisualModeType(ViMode mode)
diff --git a/src/vimode/modes/visualvimode.h b/src/vimode/modes/visualvimode.h
index e2c4c1caf..dc9086b3a 100644
--- a/src/vimode/modes/visualvimode.h
+++ b/src/vimode/modes/visualvimode.h
@@ -98,6 +98,10 @@ public:
* via mouse selection.
*/
void updateSelection();
+ /**
+ * Updates the selection of the view when an internal change happens
+ */
+ void updateViewSelection();
private:
KTextEditor::Cursor m_start;