1 /*
2     SPDX-FileCopyrightText: 2008-2009 Erlend Hamberg <ehamberg@gmail.com>
3     SPDX-FileCopyrightText: 2009 Paul Gideon Dann <pdgiddie@gmail.com>
4     SPDX-FileCopyrightText: 2011 Svyatoslav Kuzmich <svatoslav1@gmail.com>
5     SPDX-FileCopyrightText: 2012-2013 Simon St James <kdedevel@etotheipiplusone.com>
6 
7     SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #ifndef KATEVI_NORMAL_VI_MODE_H
11 #define KATEVI_NORMAL_VI_MODE_H
12 
13 #include <vimode/command.h>
14 #include <vimode/modes/modebase.h>
15 #include <vimode/motion.h>
16 #include <vimode/range.h>
17 
18 #include <QHash>
19 #include <QRegularExpression>
20 #include <QStack>
21 #include <QVector>
22 
23 #include <vector>
24 
25 #include <ktexteditor/range.h>
26 #include <ktexteditor_export.h>
27 
28 class QKeyEvent;
29 class KateViInputMode;
30 
31 namespace KateVi
32 {
33 class KeyParser;
34 class InputModeManager;
35 
36 /**
37  * Commands for the vi normal mode
38  */
39 class KTEXTEDITOR_EXPORT NormalViMode : public ModeBase
40 {
41     Q_OBJECT
42 
43     friend KateViInputMode;
44 
45 public:
46     explicit NormalViMode(InputModeManager *viInputModeManager, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal);
47     ~NormalViMode() override;
48 
49     bool handleKeypress(const QKeyEvent *e) override;
50 
51     bool commandEnterInsertMode();
52     bool commandEnterInsertModeAppend();
53     bool commandEnterInsertModeAppendEOL();
54     bool commandEnterInsertModeBeforeFirstNonBlankInLine();
55     bool commandEnterInsertModeLast();
56 
57     bool commandEnterVisualMode();
58     bool commandEnterVisualLineMode();
59     bool commandEnterVisualBlockMode();
60     bool commandReselectVisual();
61     bool commandToOtherEnd();
62 
63     bool commandEnterReplaceMode();
64 
65     bool commandDelete();
66     bool commandDeleteToEOL();
67     bool commandDeleteLine();
68 
69     bool commandMakeLowercase();
70     bool commandMakeLowercaseLine();
71     bool commandMakeUppercase();
72     bool commandMakeUppercaseLine();
73     bool commandChangeCase();
74     bool commandChangeCaseRange();
75     bool commandChangeCaseLine();
76 
77     bool commandOpenNewLineUnder();
78     bool commandOpenNewLineOver();
79 
80     bool commandJoinLines();
81 
82     bool commandChange();
83     bool commandChangeLine();
84     bool commandChangeToEOL();
85     bool commandSubstituteChar();
86     bool commandSubstituteLine();
87 
88     bool commandYank();
89     bool commandYankLine();
90     bool commandYankToEOL();
91 
92     bool commandPaste();
93     bool commandPasteBefore();
94 
95     bool commandgPaste();
96     bool commandgPasteBefore();
97 
98     bool commandIndentedPaste();
99     bool commandIndentedPasteBefore();
100 
101     bool commandDeleteChar();
102     bool commandDeleteCharBackward();
103 
104     bool commandReplaceCharacter();
105 
106     bool commandSwitchToCmdLine();
107     bool commandSearchBackward();
108     bool commandSearchForward();
109     bool commandUndo();
110     bool commandRedo();
111 
112     bool commandSetMark();
113 
114     bool commandIndentLine();
115     bool commandUnindentLine();
116     bool commandIndentLines();
117     bool commandUnindentLines();
118 
119     bool commandScrollPageDown();
120     bool commandScrollPageUp();
121     bool commandScrollHalfPageUp();
122     bool commandScrollHalfPageDown();
123 
124     bool commandCenterView(bool onFirst);
125     bool commandCenterViewOnNonBlank();
126     bool commandCenterViewOnCursor();
127     bool commandTopView(bool onFirst);
128     bool commandTopViewOnNonBlank();
129     bool commandTopViewOnCursor();
130     bool commandBottomView(bool onFirst);
131     bool commandBottomViewOnNonBlank();
132     bool commandBottomViewOnCursor();
133 
134     bool commandAbort();
135 
136     bool commandPrintCharacterCode();
137 
138     bool commandRepeatLastChange();
139 
140     bool commandAlignLine();
141     bool commandAlignLines();
142 
143     bool commandAddToNumber();
144     bool commandSubtractFromNumber();
145 
146     bool commandPrependToBlock();
147     bool commandAppendToBlock();
148 
149     bool commandGoToNextJump();
150     bool commandGoToPrevJump();
151 
152     bool commandSwitchToLeftView();
153     bool commandSwitchToUpView();
154     bool commandSwitchToDownView();
155     bool commandSwitchToRightView();
156     bool commandSwitchToNextView();
157 
158     bool commandSplitHoriz();
159     bool commandSplitVert();
160     bool commandCloseView();
161 
162     bool commandSwitchToNextTab();
163     bool commandSwitchToPrevTab();
164 
165     bool commandFormatLine();
166     bool commandFormatLines();
167 
168     bool commandCollapseToplevelNodes();
169     bool commandCollapseLocal();
170     bool commandExpandAll();
171     bool commandExpandLocal();
172     bool commandToggleRegionVisibility();
173 
174     bool commandStartRecordingMacro();
175     bool commandReplayMacro();
176 
177     bool commandCloseWrite();
178     bool commandCloseNocheck();
179 
180     // MOTIONS
181 
182     Range motionLeft();
183     Range motionRight();
184     Range motionDown();
185     Range motionUp();
186 
187     Range motionPageDown();
188     Range motionPageUp();
189     Range motionHalfPageDown();
190     Range motionHalfPageUp();
191 
192     Range motionUpToFirstNonBlank();
193     Range motionDownToFirstNonBlank();
194 
195     Range motionWordForward();
196     Range motionWordBackward();
197     Range motionWORDForward();
198     Range motionWORDBackward();
199 
200     Range motionToEndOfWord();
201     Range motionToEndOfWORD();
202     Range motionToEndOfPrevWord();
203     Range motionToEndOfPrevWORD();
204 
205     Range motionFindChar();
206     Range motionFindCharBackward();
207     Range motionToChar();
208     Range motionToCharBackward();
209     Range motionRepeatlastTF();
210     Range motionRepeatlastTFBackward();
211 
212     Range motionToEOL();
213     Range motionToColumn0();
214     Range motionToFirstCharacterOfLine();
215 
216     Range motionToLineFirst();
217     Range motionToLineLast();
218 
219     Range motionToScreenColumn();
220 
221     Range motionToMark();
222     Range motionToMarkLine();
223 
224     Range motionToMatchingItem();
225 
226     Range motionToPreviousBraceBlockStart();
227     Range motionToNextBraceBlockStart();
228     Range motionToPreviousBraceBlockEnd();
229     Range motionToNextBraceBlockEnd();
230 
231     Range motionToNextOccurrence();
232     Range motionToPrevOccurrence();
233 
234     Range motionToFirstLineOfWindow();
235     Range motionToMiddleLineOfWindow();
236     Range motionToLastLineOfWindow();
237 
238     Range motionToNextVisualLine();
239     Range motionToPrevVisualLine();
240 
241     Range motionToPreviousSentence();
242     Range motionToNextSentence();
243 
244     Range motionToBeforeParagraph();
245     Range motionToAfterParagraph();
246 
247     Range motionToIncrementalSearchMatch();
248 
249     // TEXT OBJECTS
250 
251     Range textObjectAWord();
252     Range textObjectInnerWord();
253     Range textObjectAWORD();
254     Range textObjectInnerWORD();
255 
256     Range textObjectInnerSentence();
257     Range textObjectASentence();
258 
259     Range textObjectInnerParagraph();
260     Range textObjectAParagraph();
261 
262     Range textObjectAQuoteDouble();
263     Range textObjectInnerQuoteDouble();
264 
265     Range textObjectAQuoteSingle();
266     Range textObjectInnerQuoteSingle();
267 
268     Range textObjectABackQuote();
269     Range textObjectInnerBackQuote();
270 
271     Range textObjectAParen();
272     Range textObjectInnerParen();
273 
274     Range textObjectABracket();
275     Range textObjectInnerBracket();
276 
277     Range textObjectACurlyBracket();
278     Range textObjectInnerCurlyBracket();
279 
280     Range textObjectAInequalitySign();
281     Range textObjectInnerInequalitySign();
282 
283     Range textObjectAComma();
284     Range textObjectInnerComma();
285 
286     virtual void reset();
287 
288     void beginMonitoringDocumentChanges();
289 
290 protected:
291     void resetParser();
292     void initializeCommands();
293     QRegularExpression generateMatchingItemRegex() const;
294     void executeCommand(const Command *cmd);
295     OperationMode getOperationMode() const;
296 
297     void highlightYank(const Range &range, const OperationMode mode = CharWise);
298     void addHighlightYank(const KTextEditor::Range &range);
299 
motionWillBeUsedWithCommand()300     bool motionWillBeUsedWithCommand() const
301     {
302         return !m_awaitingMotionOrTextObject.isEmpty();
303     };
304 
305     void joinLines(unsigned int from, unsigned int to) const;
306     void reformatLines(unsigned int from, unsigned int to) const;
307     bool executeKateCommand(const QString &command);
308 
309     /**
310      * Get the index of the first non-blank character from the given line.
311      *
312      * @param line The line to be picked. The current line will picked instead
313      * if this parameter is set to a negative value.
314      * @returns the index of the first non-blank character from the given line.
315      * If a non-space character cannot be found, the 0 is returned.
316      */
317     int getFirstNonBlank(int line = -1) const;
318 
319     Range textObjectComma(bool inner) const;
320     void shrinkRangeAroundCursor(Range &toShrink, const Range &rangeToShrinkTo) const;
321     KTextEditor::Cursor findSentenceStart();
322     KTextEditor::Cursor findSentenceEnd();
323     KTextEditor::Cursor findParagraphStart();
324     KTextEditor::Cursor findParagraphEnd();
325 
326 protected:
327     // The 'current position' is the current cursor position for non-linewise pastes, and the current
328     // line for linewise.
329     enum PasteLocation { AtCurrentPosition, AfterCurrentPosition };
330     bool paste(NormalViMode::PasteLocation pasteLocation, bool isgPaste, bool isIndentedPaste);
331     KTextEditor::Cursor cursorPosAtEndOfPaste(const KTextEditor::Cursor pasteLocation, const QString &pastedText) const;
332 
333 protected:
334     QString m_keys;
335     QString m_lastTFcommand; // holds the last t/T/f/F command so that it can be repeated with ;/,
336 
337     unsigned int m_countTemp;
338     int m_motionOperatorIndex;
339     int m_scroll_count_limit;
340 
341     std::vector<Command> m_commands;
342     std::vector<Motion> m_motions;
343     QVector<int> m_matchingCommands;
344     QVector<int> m_matchingMotions;
345     QStack<int> m_awaitingMotionOrTextObject;
346 
347     bool m_findWaitingForChar;
348     bool m_isRepeatedTFcommand;
349     bool m_linewiseCommand;
350     bool m_commandWithMotion;
351     bool m_lastMotionWasLinewiseInnerBlock;
352     bool m_motionCanChangeWholeVisualModeSelection;
353     bool m_commandShouldKeepSelection;
354     bool m_deleteCommand;
355     // Ctrl-c or ESC have been pressed, leading to a call to reset().
356     bool m_pendingResetIsDueToExit;
357     bool m_isUndo;
358     bool waitingForRegisterOrCharToSearch();
359 
360     // item matching ('%' motion)
361     QHash<QString, QString> m_matchingItems;
362     QRegularExpression m_matchItemRegex;
363 
364     KeyParser *m_keyParser;
365 
366     KTextEditor::Attribute::Ptr m_highlightYankAttribute;
367     QSet<KTextEditor::MovingRange *> m_highlightedYanks;
368     QSet<KTextEditor::MovingRange *> &highlightedYankForDocument();
369 
370     KTextEditor::Cursor m_currentChangeEndMarker;
371     KTextEditor::Cursor m_positionWhenIncrementalSearchBegan;
372 
373 private Q_SLOTS:
374     void textInserted(KTextEditor::Document *document, KTextEditor::Range range);
375     void textRemoved(KTextEditor::Document *, KTextEditor::Range);
376     void undoBeginning();
377     void undoEnded();
378 
379     void updateYankHighlightAttrib();
380     void clearYankHighlight();
381     void aboutToDeleteMovingInterfaceContent();
382 };
383 
384 }
385 
386 #endif /* KATEVI_NORMAL_VI_MODE_H */
387