10#include <vimode/inputmodemanager.h>
12#include <QApplication>
16#include <KConfigGroup>
17#include <KLocalizedString>
19#include "completionrecorder.h"
20#include "completionreplayer.h"
21#include "definitions.h"
22#include "globalstate.h"
24#include "kateconfig.h"
25#include "katedocument.h"
26#include "kateglobal.h"
27#include "katerenderer.h"
29#include "kateviewinternal.h"
30#include "kateviinputmode.h"
31#include "lastchangerecorder.h"
32#include "macrorecorder.h"
38#include <vimode/emulatedcommandbar/emulatedcommandbar.h>
39#include <vimode/keymapper.h>
40#include <vimode/keyparser.h>
41#include <vimode/modes/insertvimode.h>
42#include <vimode/modes/normalvimode.h>
43#include <vimode/modes/replacevimode.h>
44#include <vimode/modes/visualvimode.h>
46using namespace KateVi;
48InputModeManager::InputModeManager(KateViInputMode *inputAdapter, KTextEditor::ViewPrivate *view, KateViewInternal *viewInternal)
49 : m_inputAdapter(inputAdapter)
51 m_currentViMode = ViMode::NormalMode;
52 m_previousViMode = ViMode::NormalMode;
54 m_viNormalMode =
new NormalViMode(
this, view, viewInternal);
55 m_viInsertMode =
new InsertViMode(
this, view, viewInternal);
56 m_viVisualMode =
new VisualViMode(
this, view, viewInternal);
57 m_viReplaceMode =
new ReplaceViMode(
this, view, viewInternal);
60 m_viewInternal = viewInternal;
62 m_insideHandlingKeyPressCount = 0;
64 m_keyMapperStack.push(std::make_shared<KeyMapper>(
this, m_view->doc()));
66 m_temporaryNormalMode =
false;
68 m_jumps =
new Jumps();
69 m_marks =
new Marks(
this);
71 m_searcher =
new Searcher(
this);
72 m_completionRecorder =
new CompletionRecorder(
this);
73 m_completionReplayer =
new CompletionReplayer(
this);
75 m_macroRecorder =
new MacroRecorder(
this);
77 m_lastChangeRecorder =
new LastChangeRecorder(
this);
82 m_viNormalMode->beginMonitoringDocumentChanges();
85InputModeManager::~InputModeManager()
87 delete m_viNormalMode;
88 delete m_viInsertMode;
89 delete m_viVisualMode;
90 delete m_viReplaceMode;
94 delete m_macroRecorder;
95 delete m_completionRecorder;
96 delete m_completionReplayer;
97 delete m_lastChangeRecorder;
100bool InputModeManager::handleKeypress(
const QKeyEvent *e)
102 m_insideHandlingKeyPressCount++;
104 bool keyIsPartOfMapping =
false;
105 const bool isSyntheticSearchCompletedKeyPress = m_inputAdapter->viModeEmulatedCommandBar()->isSendingSyntheticSearchCompletedKeypress();
111 if (m_macroRecorder->isRecording() && !m_macroRecorder->isReplaying() && !isSyntheticSearchCompletedKeyPress && !keyMapper()->isExecutingMapping()
112 && !keyMapper()->isPlayingBackRejectedKeys() && !lastChangeRecorder()->isReplaying()) {
113 m_macroRecorder->record(*e);
116 if (!m_lastChangeRecorder->isReplaying() && !isSyntheticSearchCompletedKeyPress) {
123 const QChar key = KeyParser::self()->KeyEventToQChar(*e);
124 if (keyMapper()->handleKeypress(key)) {
125 keyIsPartOfMapping =
true;
131 if (!keyIsPartOfMapping) {
132 if (!m_lastChangeRecorder->isReplaying() && !isSyntheticSearchCompletedKeyPress) {
134 m_lastChangeRecorder->record(*e);
137 if (m_inputAdapter->viModeEmulatedCommandBar()->isActive()) {
138 res = m_inputAdapter->viModeEmulatedCommandBar()->handleKeyPress(e);
140 res = getCurrentViModeHandler()->handleKeypress(e);
144 m_insideHandlingKeyPressCount--;
145 Q_ASSERT(m_insideHandlingKeyPressCount >= 0);
150void InputModeManager::feedKeyPresses(
const QString &keyPresses)
const
156 for (
const QChar c : keyPresses) {
157 QString decoded = KeyParser::self()->decodeKeySequence(QString(c));
162 if (decoded.
length() > 1) {
169 if (decoded.
indexOf(QLatin1String(
"s-")) != -1 || decoded.
indexOf(QLatin1String(
"c-")) != -1 || decoded.
indexOf(QLatin1String(
"m-")) != -1
170 || decoded.
indexOf(QLatin1String(
"a-")) != -1) {
171 int s = decoded.
indexOf(QLatin1String(
"s-"));
177 int c = decoded.
indexOf(QLatin1String(
"c-"));
179 mods |= CONTROL_MODIFIER;
183 int a = decoded.
indexOf(QLatin1String(
"a-"));
189 int m = decoded.
indexOf(QLatin1String(
"m-"));
191 mods |= META_MODIFIER;
195 if (decoded.
length() > 1) {
196 key = KeyParser::self()->vi2qt(decoded);
197 }
else if (decoded.
length() == 1) {
198 key = int(decoded.
at(0).
toUpper().toLatin1());
199 text = decoded.
at(0);
202 key = KeyParser::self()->vi2qt(decoded);
206 text = decoded.
at(0);
216 QWidget *destWidget =
nullptr;
233bool InputModeManager::isHandlingKeypress()
const
235 return m_insideHandlingKeyPressCount > 0;
238void InputModeManager::storeLastChangeCommand()
240 m_lastChange = m_lastChangeRecorder->encodedChanges();
241 m_lastChangeCompletionsLog = m_completionRecorder->currentChangeCompletionsLog();
244void InputModeManager::repeatLastChange()
246 m_lastChangeRecorder->replay(m_lastChange, m_lastChangeCompletionsLog);
249void InputModeManager::clearCurrentChangeLog()
251 m_lastChangeRecorder->clear();
252 m_completionRecorder->clearCurrentChangeCompletionsLog();
255void InputModeManager::doNotLogCurrentKeypress()
257 m_macroRecorder->dropLast();
258 m_lastChangeRecorder->dropLast();
261void InputModeManager::changeViMode(ViMode newMode)
263 m_previousViMode = m_currentViMode;
264 m_currentViMode = newMode;
267ViMode InputModeManager::getCurrentViMode()
const
269 return m_currentViMode;
274 switch (m_currentViMode) {
275 case ViMode::InsertMode:
276 return KTextEditor::View::ViModeInsert;
277 case ViMode::VisualMode:
278 return KTextEditor::View::ViModeVisual;
279 case ViMode::VisualLineMode:
280 return KTextEditor::View::ViModeVisualLine;
281 case ViMode::VisualBlockMode:
282 return KTextEditor::View::ViModeVisualBlock;
283 case ViMode::ReplaceMode:
284 return KTextEditor::View::ViModeReplace;
285 case ViMode::NormalMode:
287 return KTextEditor::View::ViModeNormal;
291ViMode InputModeManager::getPreviousViMode()
const
293 return m_previousViMode;
296bool InputModeManager::isAnyVisualMode()
const
298 return ((m_currentViMode == ViMode::VisualMode) || (m_currentViMode == ViMode::VisualLineMode) || (m_currentViMode == ViMode::VisualBlockMode));
301::ModeBase *InputModeManager::getCurrentViModeHandler()
const
303 switch (m_currentViMode) {
304 case ViMode::NormalMode:
305 return m_viNormalMode;
306 case ViMode::InsertMode:
307 return m_viInsertMode;
308 case ViMode::VisualMode:
309 case ViMode::VisualLineMode:
310 case ViMode::VisualBlockMode:
311 return m_viVisualMode;
312 case ViMode::ReplaceMode:
313 return m_viReplaceMode;
318void InputModeManager::viEnterNormalMode()
320 bool moveCursorLeft = (m_currentViMode == ViMode::InsertMode || m_currentViMode == ViMode::ReplaceMode) && m_viewInternal->cursorPosition().column() > 0;
322 if (!m_lastChangeRecorder->isReplaying() && (m_currentViMode == ViMode::InsertMode || m_currentViMode == ViMode::ReplaceMode)) {
325 KTextEditor::Range r(m_view->cursorPosition(), m_marks->getInsertStopped());
328 QString insertedText = m_view->doc()->text(r);
329 m_inputAdapter->globalState()->registers()->setInsertStopped(insertedText);
332 m_marks->setInsertStopped(KTextEditor::Cursor(m_view->cursorPosition()));
335 changeViMode(ViMode::NormalMode);
337 if (moveCursorLeft) {
338 m_viewInternal->cursorPrevChar();
340 m_inputAdapter->setCaretStyle(KTextEditor::caretStyles::Block);
341 m_viewInternal->update();
344void InputModeManager::viEnterInsertMode()
346 changeViMode(ViMode::InsertMode);
347 m_marks->setInsertStopped(KTextEditor::Cursor(m_view->cursorPosition()));
348 if (getTemporaryNormalMode()) {
353 m_inputAdapter->setCaretStyle(KTextEditor::caretStyles::Line);
354 setTemporaryNormalMode(
false);
355 m_viewInternal->update();
358void InputModeManager::viEnterVisualMode(ViMode mode)
364 m_inputAdapter->setCaretStyle(KTextEditor::caretStyles::Block);
365 m_viewInternal->update();
366 getViVisualMode()->setVisualModeType(mode);
367 getViVisualMode()->init();
370void InputModeManager::viEnterReplaceMode()
372 changeViMode(ViMode::ReplaceMode);
373 m_marks->setStartEditYanked(KTextEditor::Cursor(m_view->cursorPosition()));
374 m_inputAdapter->setCaretStyle(KTextEditor::caretStyles::Underline);
375 m_viewInternal->update();
380 return m_viNormalMode;
383InsertViMode *InputModeManager::getViInsertMode()
385 return m_viInsertMode;
388VisualViMode *InputModeManager::getViVisualMode()
390 return m_viVisualMode;
395 return m_viReplaceMode;
398const QString InputModeManager::getVerbatimKeys()
const
402 switch (getCurrentViMode()) {
403 case ViMode::NormalMode:
404 cmd = m_viNormalMode->getVerbatimKeys();
406 case ViMode::InsertMode:
407 case ViMode::ReplaceMode:
410 case ViMode::VisualMode:
411 case ViMode::VisualLineMode:
412 case ViMode::VisualBlockMode:
413 cmd = m_viVisualMode->getVerbatimKeys();
420void InputModeManager::readSessionConfig(
const KConfigGroup &config)
422 m_jumps->readSessionConfig(config);
423 m_marks->readSessionConfig(config);
426void InputModeManager::writeSessionConfig(KConfigGroup &config)
428 m_jumps->writeSessionConfig(config);
429 m_marks->writeSessionConfig(config);
432void InputModeManager::reset()
434 if (m_viVisualMode) {
435 m_viVisualMode->reset();
439KeyMapper *InputModeManager::keyMapper()
441 return m_keyMapperStack.top().get();
444void InputModeManager::updateCursor(
const KTextEditor::Cursor c)
446 m_inputAdapter->updateCursor(c);
449GlobalState *InputModeManager::globalState()
const
451 return m_inputAdapter->globalState();
454KTextEditor::ViewPrivate *InputModeManager::view()
const
459void InputModeManager::pushKeyMapper(std::shared_ptr<KeyMapper> mapper)
461 m_keyMapperStack.push(mapper);
464void InputModeManager::popKeyMapper()
466 m_keyMapperStack.pop();
ViewMode
Possible view modes These correspond to various modes the text editor might be in.
Commands for the vi normal mode.
Commands for the vi replace mode.
char32_t toUpper(char32_t ucs4)
bool sendEvent(QObject *receiver, QEvent *event)
const QChar at(qsizetype position) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
qsizetype length() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
typedef KeyboardModifiers