KTextEditor

replacevimode.cpp
1/*
2 SPDX-FileCopyrightText: 2008 Erlend Hamberg <ehamberg@gmail.com>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6#include "katedocument.h"
7#include "kateviinputmode.h"
8
9#include "kateview.h"
10#include <utils/kateconfig.h>
11#include <view/kateviewinternal.h>
12#include <vimode/emulatedcommandbar/emulatedcommandbar.h>
13#include <vimode/inputmodemanager.h>
14#include <vimode/marks.h>
15#include <vimode/modes/replacevimode.h>
16
17using namespace KateVi;
18
19ReplaceViMode::ReplaceViMode(InputModeManager *viInputModeManager, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal)
20 : ModeBase()
21{
22 m_view = view;
23 m_viewInternal = viewInternal;
24 m_viInputModeManager = viInputModeManager;
25 m_count = 1;
26}
27
28bool ReplaceViMode::commandInsertFromLine(int offset)
29{
30 KTextEditor::Cursor c(m_view->cursorPosition());
31
32 if (c.line() + offset >= doc()->lines() || c.line() + offset < 0) {
33 return false;
34 }
35
36 // Fetch the new character from the specified line.
37 KTextEditor::Cursor target(c.line() + offset, c.column());
38 QChar ch = doc()->characterAt(target);
39 if (ch == QChar::Null) {
40 return false;
41 }
42
43 // The cursor is at the end of the line: just append the char.
44 if (c.column() == doc()->lineLength(c.line())) {
45 return doc()->insertText(c, ch);
46 }
47
48 // We can replace the current one with the fetched character.
49 KTextEditor::Cursor next(c.line(), c.column() + 1);
50 QChar removed = doc()->line(c.line()).at(c.column());
51 if (doc()->replaceText(KTextEditor::Range(c, next), ch)) {
52 overwrittenChar(removed);
53 return true;
54 }
55 return false;
56}
57
58bool ReplaceViMode::commandMoveOneWordLeft()
59{
60 KTextEditor::Cursor c(m_view->cursorPosition());
61 c = findPrevWordStart(c.line(), c.column());
62
63 if (!c.isValid()) {
64 c = KTextEditor::Cursor(0, 0);
65 }
66
67 updateCursor(c);
68 return true;
69}
70
71bool ReplaceViMode::commandMoveOneWordRight()
72{
73 KTextEditor::Cursor c(m_view->cursorPosition());
74 c = findNextWordStart(c.line(), c.column());
75
76 if (!c.isValid()) {
77 c = doc()->documentEnd();
78 }
79
80 updateCursor(c);
81 return true;
82}
83
85{
86 // backspace should work even if the shift key is down
87 if (e->modifiers() != CONTROL_MODIFIER && e->key() == Qt::Key_Backspace) {
88 backspace();
89 return true;
90 }
91
92 // on macOS the KeypadModifier is set for the arrow keys too
94 switch (e->key()) {
95 case Qt::Key_Escape:
96 m_overwritten.clear();
97 leaveReplaceMode();
98 return true;
99 case Qt::Key_Left:
100 m_overwritten.clear();
101 m_view->cursorLeft();
102 return true;
103 case Qt::Key_Right:
104 m_overwritten.clear();
105 m_view->cursorRight();
106 return true;
107 case Qt::Key_Up:
108 m_overwritten.clear();
109 m_view->up();
110 return true;
111 case Qt::Key_Down:
112 m_overwritten.clear();
113 m_view->down();
114 return true;
115 case Qt::Key_Home:
116 m_overwritten.clear();
117 m_view->home();
118 return true;
119 case Qt::Key_End:
120 m_overwritten.clear();
121 m_view->end();
122 return true;
123 case Qt::Key_PageUp:
124 m_overwritten.clear();
125 m_view->pageUp();
126 return true;
127 case Qt::Key_PageDown:
128 m_overwritten.clear();
129 m_view->pageDown();
130 return true;
131 case Qt::Key_Delete:
132 m_view->keyDelete();
133 return true;
134 case Qt::Key_Insert:
135 startInsertMode();
136 return true;
137 case Qt::Key_Enter:
138 case Qt::Key_Return:
139 if (m_viInputModeManager->inputAdapter()->viModeEmulatedCommandBar()->isSendingSyntheticSearchCompletedKeypress()) {
140 // BUG #451076, Do not record/send return for a newline when doing a search via Ctrl+F/Edit->Find menu
141 m_viInputModeManager->doNotLogCurrentKeypress();
142 return true;
143 }
144 Q_FALLTHROUGH();
145 default:
146 return false;
147 }
148 } else if (e->modifiers() == CONTROL_MODIFIER) {
149 switch (e->key()) {
151 case Qt::Key_C:
152 startNormalMode();
153 return true;
154 case Qt::Key_E:
155 commandInsertFromLine(1);
156 return true;
157 case Qt::Key_Y:
158 commandInsertFromLine(-1);
159 return true;
160 case Qt::Key_W:
161 commandBackWord();
162 return true;
163 case Qt::Key_U:
164 commandBackLine();
165 return true;
166 case Qt::Key_Left:
167 m_overwritten.clear();
168 commandMoveOneWordLeft();
169 return true;
170 case Qt::Key_Right:
171 m_overwritten.clear();
172 commandMoveOneWordRight();
173 return true;
174 default:
175 return false;
176 }
177 }
178
179 return false;
180}
181
182void ReplaceViMode::backspace()
183{
184 KTextEditor::Cursor c1(m_view->cursorPosition());
185 KTextEditor::Cursor c2(c1.line(), c1.column() - 1);
186
187 if (c1.column() > 0) {
188 if (!m_overwritten.isEmpty()) {
189 doc()->removeText(KTextEditor::Range(c1.line(), c1.column() - 1, c1.line(), c1.column()));
190 doc()->insertText(c2, m_overwritten.right(1));
191 m_overwritten.remove(m_overwritten.length() - 1, 1);
192 }
193 updateCursor(c2);
194 }
195}
196
197void ReplaceViMode::commandBackWord()
198{
199 KTextEditor::Cursor current(m_view->cursorPosition());
200 KTextEditor::Cursor to(findPrevWordStart(current.line(), current.column()));
201
202 if (!to.isValid()) {
203 return;
204 }
205
206 while (current.isValid() && current != to) {
207 backspace();
208 current = m_view->cursorPosition();
209 }
210}
211
212void ReplaceViMode::commandBackLine()
213{
214 const int column = m_view->cursorPosition().column();
215
216 for (int i = column; i >= 0 && !m_overwritten.isEmpty(); i--) {
217 backspace();
218 }
219}
220
221void ReplaceViMode::leaveReplaceMode()
222{
223 // Redo replacement operation <count> times
224 m_view->abortCompletion();
225
226 if (m_count > 1) {
227 // Look at added text so that we can repeat the addition
228 const QString added = doc()->text(KTextEditor::Range(m_viInputModeManager->marks()->getStartEditYanked(), m_view->cursorPosition()));
229 for (unsigned int i = 0; i < m_count - 1; i++) {
230 KTextEditor::Cursor c(m_view->cursorPosition());
231 KTextEditor::Cursor c2(c.line(), c.column() + added.length());
232 doc()->replaceText(KTextEditor::Range(c, c2), added);
233 }
234 }
235
236 startNormalMode();
237}
The Cursor represents a position in a Document.
Definition cursor.h:75
constexpr int column() const noexcept
Retrieve the column on which this cursor is situated.
Definition cursor.h:192
KTextEditor::Cursor documentEnd() const override
End position of the document.
QString text(KTextEditor::Range range, bool blockwise=false) const override
Get the document content within the given range.
QString line(int line) const override
Get a single text line.
QChar characterAt(KTextEditor::Cursor position) const override
Get the character at text position cursor.
An object representing a section of text, from one Cursor to another.
bool handleKeypress(const QKeyEvent *e) override
Checks if the key is a valid command in replace mode.
void overwrittenChar(const QChar &s)
Update the track of overwritten characters with the s character.
const QList< QKeySequence > & next()
int key() const const
Qt::KeyboardModifiers modifiers() const const
const QChar at(qsizetype position) const const
void clear()
bool isEmpty() const const
qsizetype length() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString right(qsizetype n) const const
Key_Backspace
NoModifier
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:11:27 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.