| 1 | /* |
| 2 | SPDX-FileCopyrightText: 2008 Erlend Hamberg <ehamberg@gmail.com> |
| 3 | SPDX-FileCopyrightText: 2011 Svyatoslav Kuzmich <svatoslav1@gmail.com> |
| 4 | SPDX-FileCopyrightText: 2012-2013 Simon St James <kdedevel@etotheipiplusone.com> |
| 5 | |
| 6 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 7 | */ |
| 8 | |
| 9 | #include "kateview.h" |
| 10 | #include <document/katedocument.h> |
| 11 | #include <inputmode/kateviinputmode.h> |
| 12 | |
| 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> |
| 18 | |
| 19 | using namespace KateVi; |
| 20 | |
| 21 | VisualViMode::VisualViMode(InputModeManager *viInputModeManager, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal) |
| 22 | : NormalViMode(viInputModeManager, view, viewInternal) |
| 23 | { |
| 24 | m_start.setPosition(line: -1, column: -1); |
| 25 | m_mode = ViMode::VisualMode; |
| 26 | |
| 27 | connect(sender: m_view, signal: &KTextEditor::ViewPrivate::selectionChanged, context: this, slot: &VisualViMode::updateSelection); |
| 28 | } |
| 29 | |
| 30 | void VisualViMode::selectInclusive(const KTextEditor::Cursor c1, const KTextEditor::Cursor c2) |
| 31 | { |
| 32 | if (c1 >= c2) { |
| 33 | m_view->setSelection(KTextEditor::Range(c1.line(), c1.column() + 1, c2.line(), c2.column())); |
| 34 | } else { |
| 35 | m_view->setSelection(KTextEditor::Range(c1.line(), c1.column(), c2.line(), c2.column() + 1)); |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | void VisualViMode::selectBlockInclusive(const KTextEditor::Cursor c1, const KTextEditor::Cursor c2) |
| 40 | { |
| 41 | m_view->setBlockSelection(true); |
| 42 | |
| 43 | if (c1.column() >= c2.column()) { |
| 44 | m_view->setSelection(KTextEditor::Range(c1.line(), c1.column() + 1, c2.line(), c2.column())); |
| 45 | } else { |
| 46 | m_view->setSelection(KTextEditor::Range(c1.line(), c1.column(), c2.line(), c2.column() + 1)); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | void VisualViMode::selectLines(KTextEditor::Range range) |
| 51 | { |
| 52 | int sline = qMin(a: range.start().line(), b: range.end().line()); |
| 53 | int eline = qMax(a: range.start().line(), b: range.end().line()); |
| 54 | int ecol = m_view->doc()->lineLength(line: eline) + 1; |
| 55 | |
| 56 | m_view->setSelection(KTextEditor::Range(KTextEditor::Cursor(sline, 0), KTextEditor::Cursor(eline, ecol))); |
| 57 | } |
| 58 | |
| 59 | void VisualViMode::goToPos(const Range &r) |
| 60 | { |
| 61 | KTextEditor::Cursor c = m_view->cursorPosition(); |
| 62 | |
| 63 | if (r.startLine != -1 && r.startColumn != -1 && c == m_start) { |
| 64 | m_start.setLine(r.startLine); |
| 65 | m_start.setColumn(r.startColumn); |
| 66 | c.setLine(r.endLine); |
| 67 | c.setColumn(r.endColumn); |
| 68 | } else if (r.startLine != -1 && r.startColumn != -1 && m_motionCanChangeWholeVisualModeSelection) { |
| 69 | const KTextEditor::Cursor textObjectBegin(r.startLine, r.startColumn); |
| 70 | if (textObjectBegin < m_start) { |
| 71 | m_start.setLine(r.startLine); |
| 72 | m_start.setColumn(r.startColumn); |
| 73 | c.setLine(r.endLine); |
| 74 | c.setColumn(r.endColumn); |
| 75 | } |
| 76 | } else { |
| 77 | c.setLine(r.endLine); |
| 78 | c.setColumn(r.endColumn); |
| 79 | } |
| 80 | |
| 81 | if (c.line() >= doc()->lines()) { |
| 82 | c.setLine(doc()->lines() - 1); |
| 83 | } |
| 84 | |
| 85 | updateCursor(c); |
| 86 | |
| 87 | // Setting range for a command |
| 88 | m_commandRange = Range(m_start, c, m_commandRange.motionType); |
| 89 | |
| 90 | // If visual mode is blockwise |
| 91 | if (isVisualBlock()) { |
| 92 | selectBlockInclusive(c1: m_start, c2: c); |
| 93 | |
| 94 | // Need to correct command range to make it inclusive. |
| 95 | if ((c.line() < m_start.line() && c.column() > m_start.column()) || (c.line() > m_start.line() && c.column() < m_start.column())) { |
| 96 | qSwap(value1&: m_commandRange.endColumn, value2&: m_commandRange.startColumn); |
| 97 | } |
| 98 | return; |
| 99 | } else { |
| 100 | m_view->setBlockSelection(false); |
| 101 | } |
| 102 | |
| 103 | // If visual mode is linewise |
| 104 | if (isVisualLine()) { |
| 105 | selectLines(range: KTextEditor::Range(m_start, c)); |
| 106 | return; |
| 107 | } |
| 108 | |
| 109 | // If visual mode is charwise |
| 110 | selectInclusive(c1: m_start, c2: c); |
| 111 | } |
| 112 | |
| 113 | void VisualViMode::reset() |
| 114 | { |
| 115 | m_mode = ViMode::VisualMode; |
| 116 | |
| 117 | // only switch to normal mode if still in visual mode. commands like c, s, ... |
| 118 | // can have switched to insert mode |
| 119 | if (m_viInputModeManager->isAnyVisualMode()) { |
| 120 | saveRangeMarks(); |
| 121 | m_lastVisualMode = m_viInputModeManager->getCurrentViMode(); |
| 122 | |
| 123 | // Return the cursor back to start of selection after. |
| 124 | if (!m_pendingResetIsDueToExit) { |
| 125 | KTextEditor::Cursor c = m_view->cursorPosition(); |
| 126 | if (m_start.line() != -1 && m_start.column() != -1) { |
| 127 | if (m_viInputModeManager->getCurrentViMode() == ViMode::VisualLineMode) { |
| 128 | if (m_start.line() < c.line()) { |
| 129 | updateCursor(c: KTextEditor::Cursor(m_start.line(), 0)); |
| 130 | m_stickyColumn = -1; |
| 131 | } |
| 132 | } else { |
| 133 | updateCursor(c: qMin(a: m_start, b: c)); |
| 134 | m_stickyColumn = -1; |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | if (m_viInputModeManager->getPreviousViMode() == ViMode::InsertMode) { |
| 140 | startInsertMode(); |
| 141 | } else { |
| 142 | startNormalMode(); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | if (!m_commandShouldKeepSelection) { |
| 147 | m_view->removeSelection(); |
| 148 | } else { |
| 149 | m_commandShouldKeepSelection = false; |
| 150 | } |
| 151 | |
| 152 | m_start.setPosition(line: -1, column: -1); |
| 153 | m_pendingResetIsDueToExit = false; |
| 154 | } |
| 155 | |
| 156 | void VisualViMode::saveRangeMarks() |
| 157 | { |
| 158 | // DO NOT save these marks if the |
| 159 | // action that exited visual mode deleted the selection |
| 160 | if (m_deleteCommand == false) { |
| 161 | m_viInputModeManager->marks()->setSelectionStart(m_start); |
| 162 | m_viInputModeManager->marks()->setSelectionFinish(m_view->cursorPosition()); |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | void VisualViMode::init() |
| 167 | { |
| 168 | // when using "gv" we already have a start position |
| 169 | if (!m_start.isValid()) { |
| 170 | m_start = m_view->cursorPosition(); |
| 171 | } |
| 172 | |
| 173 | if (isVisualLine()) { |
| 174 | KTextEditor::Cursor c = m_view->cursorPosition(); |
| 175 | selectLines(range: KTextEditor::Range(c, c)); |
| 176 | } |
| 177 | |
| 178 | m_commandRange = Range(m_start, m_start, m_commandRange.motionType); |
| 179 | } |
| 180 | |
| 181 | void VisualViMode::setVisualModeType(ViMode mode) |
| 182 | { |
| 183 | Q_ASSERT(mode == ViMode::VisualMode || mode == ViMode::VisualLineMode || mode == ViMode::VisualBlockMode); |
| 184 | m_mode = mode; |
| 185 | } |
| 186 | |
| 187 | void VisualViMode::switchStartEnd() |
| 188 | { |
| 189 | KTextEditor::Cursor c = m_start; |
| 190 | m_start = m_view->cursorPosition(); |
| 191 | |
| 192 | updateCursor(c); |
| 193 | |
| 194 | m_stickyColumn = -1; |
| 195 | } |
| 196 | |
| 197 | void VisualViMode::goToPos(const KTextEditor::Cursor c) |
| 198 | { |
| 199 | Range r(c, InclusiveMotion); |
| 200 | goToPos(r); |
| 201 | } |
| 202 | |
| 203 | void VisualViMode::updateSelection() |
| 204 | { |
| 205 | if (!m_viInputModeManager->inputAdapter()->isActive()) { |
| 206 | return; |
| 207 | } |
| 208 | if (m_viInputModeManager->isHandlingKeypress() && !m_isUndo) { |
| 209 | return; |
| 210 | } |
| 211 | |
| 212 | // If we are there it's already not VisualBlock mode. |
| 213 | m_view->setBlockSelection(false); |
| 214 | |
| 215 | // If not valid going back to normal mode |
| 216 | KTextEditor::Range r = m_view->selectionRange(); |
| 217 | if (!r.isValid()) { |
| 218 | // Don't screw up the cursor's position. See BUG #337286. |
| 219 | m_pendingResetIsDueToExit = true; |
| 220 | reset(); |
| 221 | return; |
| 222 | } |
| 223 | |
| 224 | // If already not in visual mode, it's time to go there. |
| 225 | if (m_viInputModeManager->getCurrentViMode() != ViMode::VisualMode) { |
| 226 | commandEnterVisualMode(); |
| 227 | } |
| 228 | |
| 229 | // Set range for commands |
| 230 | m_start = (m_view->cursorPosition() == r.start()) ? r.end() : r.start(); |
| 231 | m_commandRange = Range(r.start(), r.end(), m_commandRange.motionType); |
| 232 | // The end of the range seems to be one space forward of where it should be. |
| 233 | m_commandRange.endColumn--; |
| 234 | } |
| 235 | |
| 236 | #define ADDCMD(STR, FUNC, FLGS) Command(QStringLiteral(STR), &NormalViMode::FUNC, FLGS) |
| 237 | |
| 238 | #define ADDMOTION(STR, FUNC, FLGS) Motion(QStringLiteral(STR), &NormalViMode::FUNC, FLGS) |
| 239 | |
| 240 | const std::vector<Command> &VisualViMode::commands() |
| 241 | { |
| 242 | // init once, is expensive |
| 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("gc" , commandToggleComment, IS_CHANGE), |
| 265 | ADDCMD(":" , commandSwitchToCmdLine, SHOULD_NOT_RESET), |
| 266 | ADDCMD("m." , commandSetMark, REGEX_PATTERN | SHOULD_NOT_RESET), |
| 267 | ADDCMD(">" , commandIndentLines, IS_CHANGE), |
| 268 | ADDCMD("<" , commandUnindentLines, IS_CHANGE), |
| 269 | ADDCMD("<c-c>" , commandAbort, 0), |
| 270 | ADDCMD("<c-[>" , commandAbort, 0), |
| 271 | ADDCMD("ga" , commandPrintCharacterCode, SHOULD_NOT_RESET), |
| 272 | ADDCMD("v" , commandEnterVisualMode, SHOULD_NOT_RESET), |
| 273 | ADDCMD("V" , commandEnterVisualLineMode, SHOULD_NOT_RESET), |
| 274 | ADDCMD("o" , commandToOtherEnd, SHOULD_NOT_RESET | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 275 | ADDCMD("=" , commandAlignLines, SHOULD_NOT_RESET), |
| 276 | ADDCMD("~" , commandChangeCase, IS_CHANGE), |
| 277 | ADDCMD("I" , commandPrependToBlock, IS_CHANGE), |
| 278 | ADDCMD("A" , commandAppendToBlock, IS_CHANGE), |
| 279 | ADDCMD("gq" , commandFormatLines, IS_CHANGE), |
| 280 | ADDCMD("q." , commandStartRecordingMacro, REGEX_PATTERN | SHOULD_NOT_RESET), |
| 281 | ADDCMD("@." , commandReplayMacro, REGEX_PATTERN | SHOULD_NOT_RESET), |
| 282 | ADDCMD("z." , commandCenterViewOnNonBlank, 0), |
| 283 | ADDCMD("zz" , commandCenterViewOnCursor, 0), |
| 284 | ADDCMD("z<return>" , commandTopViewOnNonBlank, 0), |
| 285 | ADDCMD("zt" , commandTopViewOnCursor, 0), |
| 286 | ADDCMD("z-" , commandBottomViewOnNonBlank, 0), |
| 287 | ADDCMD("zb" , commandBottomViewOnCursor, 0), |
| 288 | }; |
| 289 | return global; |
| 290 | } |
| 291 | |
| 292 | const std::vector<Motion> &VisualViMode::motions() |
| 293 | { |
| 294 | // init once, is expensive |
| 295 | static std::vector<Motion> global{ |
| 296 | // regular motions |
| 297 | ADDMOTION("h" , motionLeft, 0), |
| 298 | ADDMOTION("<left>" , motionLeft, 0), |
| 299 | ADDMOTION("<backspace>" , motionLeft, 0), |
| 300 | ADDMOTION("j" , motionDown, 0), |
| 301 | ADDMOTION("<down>" , motionDown, 0), |
| 302 | ADDMOTION("k" , motionUp, 0), |
| 303 | ADDMOTION("<up>" , motionUp, 0), |
| 304 | ADDMOTION("l" , motionRight, 0), |
| 305 | ADDMOTION("<right>" , motionRight, 0), |
| 306 | ADDMOTION(" " , motionRight, 0), |
| 307 | ADDMOTION("$" , motionToEOL, 0), |
| 308 | ADDMOTION("<end>" , motionToEOL, 0), |
| 309 | ADDMOTION("g_" , motionToLastNonBlank, 0), |
| 310 | ADDMOTION("0" , motionToColumn0, 0), |
| 311 | ADDMOTION("<home>" , motionToColumn0, 0), |
| 312 | ADDMOTION("^" , motionToFirstCharacterOfLine, 0), |
| 313 | ADDMOTION("f." , motionFindChar, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 314 | ADDMOTION("F." , motionFindCharBackward, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 315 | ADDMOTION("t." , motionToChar, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 316 | ADDMOTION("T." , motionToCharBackward, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 317 | ADDMOTION(";" , motionRepeatlastTF, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 318 | ADDMOTION("," , motionRepeatlastTFBackward, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 319 | ADDMOTION("n" , motionFindNext, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 320 | ADDMOTION("N" , motionFindPrev, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 321 | ADDMOTION("gg" , motionToLineFirst, 0), |
| 322 | ADDMOTION("G" , motionToLineLast, 0), |
| 323 | ADDMOTION("w" , motionWordForward, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 324 | ADDMOTION("W" , motionWORDForward, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 325 | ADDMOTION("<c-right>" , motionWordForward, IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 326 | ADDMOTION("<c-left>" , motionWordBackward, IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 327 | ADDMOTION("b" , motionWordBackward, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 328 | ADDMOTION("B" , motionWORDBackward, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 329 | ADDMOTION("e" , motionToEndOfWord, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 330 | ADDMOTION("E" , motionToEndOfWORD, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 331 | ADDMOTION("ge" , motionToEndOfPrevWord, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 332 | ADDMOTION("gE" , motionToEndOfPrevWORD, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 333 | ADDMOTION("|" , motionToScreenColumn, 0), |
| 334 | ADDMOTION("%" , motionToMatchingItem, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 335 | ADDMOTION("`." , motionToMark, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 336 | ADDMOTION("'." , motionToMarkLine, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 337 | ADDMOTION("[[" , motionToPreviousBraceBlockStart, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 338 | ADDMOTION("]]" , motionToNextBraceBlockStart, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 339 | ADDMOTION("[]" , motionToPreviousBraceBlockEnd, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 340 | ADDMOTION("][" , motionToNextBraceBlockEnd, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 341 | ADDMOTION("*" , motionToNextOccurrence, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 342 | ADDMOTION("#" , motionToPrevOccurrence, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 343 | ADDMOTION("<c-f>" , motionPageDown, 0), |
| 344 | ADDMOTION("<pagedown>" , motionPageDown, 0), |
| 345 | ADDMOTION("<c-b>" , motionPageUp, 0), |
| 346 | ADDMOTION("<pageup>" , motionPageUp, 0), |
| 347 | ADDMOTION("gj" , motionToNextVisualLine, 0), |
| 348 | ADDMOTION("g<down>" , motionToNextVisualLine, 0), |
| 349 | ADDMOTION("gk" , motionToPrevVisualLine, 0), |
| 350 | ADDMOTION("g<up>" , motionToPrevVisualLine, 0), |
| 351 | ADDMOTION("(" , motionToPreviousSentence, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 352 | ADDMOTION(")" , motionToNextSentence, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 353 | ADDMOTION("{" , motionToBeforeParagraph, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 354 | ADDMOTION("}" , motionToAfterParagraph, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 355 | ADDMOTION("<c-u>" , motionHalfPageUp, 0), |
| 356 | ADDMOTION("<c-d>" , motionHalfPageDown, 0), |
| 357 | |
| 358 | // text objects |
| 359 | ADDMOTION("iw" , textObjectInnerWord, 0), |
| 360 | ADDMOTION("aw" , textObjectAWord, 0), |
| 361 | ADDMOTION("iW" , textObjectInnerWORD, 0), |
| 362 | ADDMOTION("aW" , textObjectAWORD, IS_NOT_LINEWISE), |
| 363 | ADDMOTION("is" , textObjectInnerSentence, IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 364 | ADDMOTION("as" , textObjectASentence, IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 365 | ADDMOTION("ip" , textObjectInnerParagraph, IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 366 | ADDMOTION("ap" , textObjectAParagraph, IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 367 | ADDMOTION("i\"" , textObjectInnerQuoteDouble, CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 368 | ADDMOTION("a\"" , textObjectAQuoteDouble, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 369 | ADDMOTION("i'" , textObjectInnerQuoteSingle, CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 370 | ADDMOTION("a'" , textObjectAQuoteSingle, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 371 | ADDMOTION("i[()b]" , textObjectInnerParen, REGEX_PATTERN | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 372 | ADDMOTION("a[()b]" , textObjectAParen, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 373 | ADDMOTION("i[{}B]" , |
| 374 | textObjectInnerCurlyBracket, |
| 375 | REGEX_PATTERN | IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 376 | ADDMOTION("a[{}B]" , textObjectACurlyBracket, REGEX_PATTERN | IS_NOT_LINEWISE | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 377 | ADDMOTION("i[><]" , |
| 378 | textObjectInnerInequalitySign, |
| 379 | REGEX_PATTERN | IS_NOT_LINEWISE | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 380 | ADDMOTION("i[\\[\\]]" , textObjectInnerBracket, REGEX_PATTERN | CAN_CHANGE_WHOLE_VISUAL_MODE_SELECTION | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 381 | ADDMOTION("a[\\[\\]]" , textObjectABracket, REGEX_PATTERN | CAN_LAND_INSIDE_FOLDING_RANGE), |
| 382 | ADDMOTION("i," , textObjectInnerComma, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 383 | ADDMOTION("a," , textObjectAComma, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 384 | |
| 385 | ADDMOTION("/<enter>" , motionToIncrementalSearchMatch, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 386 | ADDMOTION("?<enter>" , motionToIncrementalSearchMatch, CAN_LAND_INSIDE_FOLDING_RANGE), |
| 387 | }; |
| 388 | return global; |
| 389 | } |
| 390 | |