10#include <document/katedocument.h>
11#include <inputmode/kateviinputmode.h>
13#include <vimode/inputmodemanager.h>
14#include <vimode/marks.h>
15#include <vimode/modes/visualvimode.h>
16#include <vimode/motion.h>
17#include <vimode/range.h>
19using namespace KateVi;
21VisualViMode::VisualViMode(InputModeManager *viInputModeManager, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal)
24 m_start.setPosition(-1, -1);
25 m_mode = ViMode::VisualMode;
41 m_view->setBlockSelection(
true);
54 int ecol = m_view->doc()->
lineLength(eline) + 1;
59void VisualViMode::goToPos(
const Range &r)
63 if (r.startLine != -1 && r.startColumn != -1 && c == m_start) {
68 }
else if (r.startLine != -1 && r.startColumn != -1 && m_motionCanChangeWholeVisualModeSelection) {
70 if (textObjectBegin < m_start) {
81 if (c.
line() >= doc()->lines()) {
88 m_commandRange = Range(m_start, c, m_commandRange.motionType);
91 if (isVisualBlock()) {
92 selectBlockInclusive(m_start, c);
96 qSwap(m_commandRange.endColumn, m_commandRange.startColumn);
100 m_view->setBlockSelection(
false);
104 if (isVisualLine()) {
110 selectInclusive(m_start, c);
113void VisualViMode::reset()
115 m_mode = ViMode::VisualMode;
119 if (m_viInputModeManager->isAnyVisualMode()) {
121 m_lastVisualMode = m_viInputModeManager->getCurrentViMode();
124 if (!m_pendingResetIsDueToExit) {
126 if (m_start.
line() != -1 && m_start.
column() != -1) {
127 if (m_viInputModeManager->getCurrentViMode() == ViMode::VisualLineMode) {
133 updateCursor(qMin(m_start, c));
139 if (m_viInputModeManager->getPreviousViMode() == ViMode::InsertMode) {
146 if (!m_commandShouldKeepSelection) {
147 m_view->removeSelection();
149 m_commandShouldKeepSelection =
false;
153 m_pendingResetIsDueToExit =
false;
156void VisualViMode::saveRangeMarks()
160 if (m_deleteCommand ==
false) {
161 m_viInputModeManager->marks()->setSelectionStart(m_start);
162 m_viInputModeManager->marks()->setSelectionFinish(m_view->cursorPosition());
166void VisualViMode::init()
170 m_start = m_view->cursorPosition();
173 if (isVisualLine()) {
178 m_commandRange = Range(m_start, m_start, m_commandRange.motionType);
181void VisualViMode::setVisualModeType(ViMode mode)
183 Q_ASSERT(mode == ViMode::VisualMode || mode == ViMode::VisualLineMode || mode == ViMode::VisualBlockMode);
187void VisualViMode::switchStartEnd()
190 m_start = m_view->cursorPosition();
199 Range r(c, InclusiveMotion);
203void VisualViMode::updateSelection()
205 if (!m_viInputModeManager->inputAdapter()->isActive()) {
208 if (m_viInputModeManager->isHandlingKeypress() && !m_isUndo) {
213 m_view->setBlockSelection(
false);
219 m_pendingResetIsDueToExit =
true;
225 if (m_viInputModeManager->getCurrentViMode() != ViMode::VisualMode) {
226 commandEnterVisualMode();
230 m_start = (m_view->cursorPosition() == r.
start()) ? r.
end() : r.
start();
231 m_commandRange = Range(r.
start(), r.
end(), m_commandRange.motionType);
233 m_commandRange.endColumn--;
236#define ADDCMD(STR, FUNC, FLGS) Command(QStringLiteral(STR), &NormalViMode::FUNC, FLGS)
238#define ADDMOTION(STR, FUNC, FLGS) Motion(QStringLiteral(STR), &NormalViMode::FUNC, FLGS)
240const std::vector<Command> &VisualViMode::commands()
243 static std::vector<Command> global{
244 ADDCMD(
"J", commandJoinLines, IS_CHANGE),
245 ADDCMD(
"c", commandChange, IS_CHANGE),
246 ADDCMD(
"s", commandChange, IS_CHANGE),
247 ADDCMD(
"C", commandChangeToEOL, IS_CHANGE),
248 ADDCMD(
"S", commandChangeToEOL, IS_CHANGE),
249 ADDCMD(
"d", commandDelete, IS_CHANGE),
250 ADDCMD(
"<delete>", commandDelete, IS_CHANGE),
251 ADDCMD(
"D", commandDeleteToEOL, IS_CHANGE),
252 ADDCMD(
"x", commandDeleteChar, IS_CHANGE),
253 ADDCMD(
"X", commandDeleteCharBackward, IS_CHANGE),
254 ADDCMD(
"gu", commandMakeLowercase, IS_CHANGE),
255 ADDCMD(
"u", commandMakeLowercase, IS_CHANGE),
256 ADDCMD(
"gU", commandMakeUppercase, IS_CHANGE),
257 ADDCMD(
"g~", commandChangeCaseRange, IS_CHANGE),
258 ADDCMD(
"U", commandMakeUppercase, IS_CHANGE),
259 ADDCMD(
"y", commandYank, 0),
260 ADDCMD(
"Y", commandYankToEOL, 0),
261 ADDCMD(
"p", commandPaste, IS_CHANGE),
262 ADDCMD(
"P", commandPasteBefore, IS_CHANGE),
263 ADDCMD(
"r.", commandReplaceCharacter, IS_CHANGE | REGEX_PATTERN),
264 ADDCMD(
":", commandSwitchToCmdLine, SHOULD_NOT_RESET),
265 ADDCMD(
"m.", commandSetMark, REGEX_PATTERN | SHOULD_NOT_RESET),
266 ADDCMD(
">", commandIndentLines, IS_CHANGE),
267 ADDCMD(
"<", commandUnindentLines, IS_CHANGE),
268 ADDCMD(
"<c-c>", commandAbort, 0),
269 ADDCMD(
"<c-[>", commandAbort, 0),
270 ADDCMD(
"ga", commandPrintCharacterCode, SHOULD_NOT_RESET),
271 ADDCMD(
"v", commandEnterVisualMode, SHOULD_NOT_RESET),
272 ADDCMD(
"V", commandEnterVisualLineMode, SHOULD_NOT_RESET),
273 ADDCMD(
"o", commandToOtherEnd, SHOULD_NOT_RESET | CAN_LAND_INSIDE_FOLDING_RANGE),
274 ADDCMD(
"=", commandAlignLines, SHOULD_NOT_RESET),
275 ADDCMD(
"~", commandChangeCase, IS_CHANGE),
276 ADDCMD(
"I", commandPrependToBlock, IS_CHANGE),
277 ADDCMD(
"A", commandAppendToBlock, IS_CHANGE),
278 ADDCMD(
"gq", commandFormatLines, IS_CHANGE),
279 ADDCMD(
"q.", commandStartRecordingMacro, REGEX_PATTERN | SHOULD_NOT_RESET),
280 ADDCMD(
"@.", commandReplayMacro, REGEX_PATTERN | SHOULD_NOT_RESET),
281 ADDCMD(
"z.", commandCenterViewOnNonBlank, 0),
282 ADDCMD(
"zz", commandCenterViewOnCursor, 0),
283 ADDCMD(
"z<return>", commandTopViewOnNonBlank, 0),
284 ADDCMD(
"zt", commandTopViewOnCursor, 0),
285 ADDCMD(
"z-", commandBottomViewOnNonBlank, 0),
286 ADDCMD(
"zb", commandBottomViewOnCursor, 0),
291const std::vector<Motion> &VisualViMode::motions()
294 static std::vector<Motion> global{
296 ADDMOTION(
"h", motionLeft, 0),
297 ADDMOTION(
"<left>", motionLeft, 0),
298 ADDMOTION(
"<backspace>", motionLeft, 0),
299 ADDMOTION(
"j", motionDown, 0),
300 ADDMOTION(
"<down>", motionDown, 0),
301 ADDMOTION(
"k", motionUp, 0),
302 ADDMOTION(
"<up>", motionUp, 0),
303 ADDMOTION(
"l", motionRight, 0),
304 ADDMOTION(
"<right>", motionRight, 0),
305 ADDMOTION(
" ", motionRight, 0),
306 ADDMOTION(
"$", motionToEOL, 0),
307 ADDMOTION(
"<end>", motionToEOL, 0),
308 ADDMOTION(
"g_", motionToLastNonBlank, 0),
309 ADDMOTION(
"0", motionToColumn0, 0),
310 ADDMOTION(
"<home>", motionToColumn0, 0),
311 ADDMOTION(
"^", motionToFirstCharacterOfLine, 0),
312 ADDMOTION(
"f.", motionFindChar, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
313 ADDMOTION(
"F.", motionFindCharBackward, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
314 ADDMOTION(
"t.", motionToChar, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
315 ADDMOTION(
"T.", motionToCharBackward, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
316 ADDMOTION(
";", motionRepeatlastTF, CAN_LAND_INSIDE_FOLDING_RANGE),
317 ADDMOTION(
",", motionRepeatlastTFBackward, CAN_LAND_INSIDE_FOLDING_RANGE),
318 ADDMOTION(
"n", motionFindNext, CAN_LAND_INSIDE_FOLDING_RANGE),
319 ADDMOTION(
"N", motionFindPrev, CAN_LAND_INSIDE_FOLDING_RANGE),
320 ADDMOTION(
"gg", motionToLineFirst, 0),
321 ADDMOTION(
"G", motionToLineLast, 0),
322 ADDMOTION(
"w", motionWordForward, CAN_LAND_INSIDE_FOLDING_RANGE),
323 ADDMOTION(
"W", motionWORDForward, CAN_LAND_INSIDE_FOLDING_RANGE),
324 ADDMOTION(
"<c-right>", motionWordForward, IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE),
325 ADDMOTION(
"<c-left>", motionWordBackward, IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE),
326 ADDMOTION(
"b", motionWordBackward, CAN_LAND_INSIDE_FOLDING_RANGE),
327 ADDMOTION(
"B", motionWORDBackward, CAN_LAND_INSIDE_FOLDING_RANGE),
328 ADDMOTION(
"e", motionToEndOfWord, CAN_LAND_INSIDE_FOLDING_RANGE),
329 ADDMOTION(
"E", motionToEndOfWORD, CAN_LAND_INSIDE_FOLDING_RANGE),
330 ADDMOTION(
"ge", motionToEndOfPrevWord, CAN_LAND_INSIDE_FOLDING_RANGE),
331 ADDMOTION(
"gE", motionToEndOfPrevWORD, CAN_LAND_INSIDE_FOLDING_RANGE),
332 ADDMOTION(
"|", motionToScreenColumn, 0),
333 ADDMOTION(
"%", motionToMatchingItem, CAN_LAND_INSIDE_FOLDING_RANGE),
334 ADDMOTION(
"`.", motionToMark, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
335 ADDMOTION(
"'.", motionToMarkLine, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
336 ADDMOTION(
"[[", motionToPreviousBraceBlockStart, CAN_LAND_INSIDE_FOLDING_RANGE),
337 ADDMOTION(
"]]", motionToNextBraceBlockStart, CAN_LAND_INSIDE_FOLDING_RANGE),
338 ADDMOTION(
"[]", motionToPreviousBraceBlockEnd, CAN_LAND_INSIDE_FOLDING_RANGE),
339 ADDMOTION(
"][", motionToNextBraceBlockEnd, CAN_LAND_INSIDE_FOLDING_RANGE),
340 ADDMOTION(
"*", motionToNextOccurrence, CAN_LAND_INSIDE_FOLDING_RANGE),
341 ADDMOTION(
"#", motionToPrevOccurrence, CAN_LAND_INSIDE_FOLDING_RANGE),
342 ADDMOTION(
"<c-f>", motionPageDown, 0),
343 ADDMOTION(
"<pagedown>", motionPageDown, 0),
344 ADDMOTION(
"<c-b>", motionPageUp, 0),
345 ADDMOTION(
"<pageup>", motionPageUp, 0),
346 ADDMOTION(
"gj", motionToNextVisualLine, 0),
347 ADDMOTION(
"g<down>", motionToNextVisualLine, 0),
348 ADDMOTION(
"gk", motionToPrevVisualLine, 0),
349 ADDMOTION(
"g<up>", motionToPrevVisualLine, 0),
350 ADDMOTION(
"(", motionToPreviousSentence, CAN_LAND_INSIDE_FOLDING_RANGE),
351 ADDMOTION(
")", motionToNextSentence, CAN_LAND_INSIDE_FOLDING_RANGE),
352 ADDMOTION(
"{", motionToBeforeParagraph, CAN_LAND_INSIDE_FOLDING_RANGE),
353 ADDMOTION(
"}", motionToAfterParagraph, CAN_LAND_INSIDE_FOLDING_RANGE),
354 ADDMOTION(
"<c-u>", motionHalfPageUp, 0),
355 ADDMOTION(
"<c-d>", motionHalfPageDown, 0),
358 ADDMOTION(
"iw", textObjectInnerWord, 0),
359 ADDMOTION(
"aw", textObjectAWord, 0),
360 ADDMOTION(
"iW", textObjectInnerWORD, 0),
361 ADDMOTION(
"aW", textObjectAWORD, IS_NOT_LINEWISE),
362 ADDMOTION(
"is", textObjectInnerSentence, IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
363 ADDMOTION(
"as", textObjectASentence, IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE | CAN_LAND_INSIDE_FOLDING_RANGE),
364 ADDMOTION(
"ip", textObjectInnerParagraph, IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
365 ADDMOTION(
"ap", textObjectAParagraph, IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
366 ADDMOTION(
"i\"", textObjectInnerQuoteDouble, CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
367 ADDMOTION(
"a\"", textObjectAQuoteDouble, CAN_LAND_INSIDE_FOLDING_RANGE),
368 ADDMOTION(
"i'", textObjectInnerQuoteSingle, CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
369 ADDMOTION(
"a'", textObjectAQuoteSingle, CAN_LAND_INSIDE_FOLDING_RANGE),
370 ADDMOTION(
"i[()b]", textObjectInnerParen, REGEX_PATTERN | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
371 ADDMOTION(
"a[()b]", textObjectAParen, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
373 textObjectInnerCurlyBracket,
374 REGEX_PATTERN | IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
375 ADDMOTION(
"a[{}B]", textObjectACurlyBracket, REGEX_PATTERN | IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE),
377 textObjectInnerInequalitySign,
378 REGEX_PATTERN | IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
379 ADDMOTION(
"i[\\[\\]]", textObjectInnerBracket, REGEX_PATTERN | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE),
380 ADDMOTION(
"a[\\[\\]]", textObjectABracket, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE),
381 ADDMOTION(
"i,", textObjectInnerComma, CAN_LAND_INSIDE_FOLDING_RANGE),
382 ADDMOTION(
"a,", textObjectAComma, CAN_LAND_INSIDE_FOLDING_RANGE),
384 ADDMOTION(
"/<enter>", motionToIncrementalSearchMatch, CAN_LAND_INSIDE_FOLDING_RANGE),
385 ADDMOTION(
"?<enter>", motionToIncrementalSearchMatch, CAN_LAND_INSIDE_FOLDING_RANGE),
The Cursor represents a position in a Document.
constexpr int column() const noexcept
Retrieve the column on which this cursor is situated.
void setColumn(int column) noexcept
Set the cursor column to column.
void setPosition(Cursor position) noexcept
Set the current cursor position to position.
constexpr bool isValid() const noexcept
Returns whether the current position of this cursor is a valid position (line + column must both be >...
void setLine(int line) noexcept
Set the cursor line to line.
constexpr int line() const noexcept
Retrieve the line on which this cursor is situated.
int lineLength(int line) const override
Get the length of a given line in characters.
An object representing a section of text, from one Cursor to another.
constexpr Cursor end() const noexcept
Get the end position of this range.
constexpr Cursor start() const noexcept
Get the start position of this range.
constexpr bool isValid() const noexcept
Validity check.
void selectionChanged(KTextEditor::View *view)
This signal is emitted whenever the view's selection changes.
Commands for the vi normal mode.
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)