File indexing completed on 2024-05-05 03:58:02
0001 /* 0002 SPDX-FileCopyrightText: KDE Developers 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "kateviinputmode.h" 0008 #include "kateconfig.h" 0009 #include "katedocument.h" 0010 #include "katerenderer.h" 0011 #include "kateview.h" 0012 #include "kateviewinternal.h" 0013 #include <vimode/emulatedcommandbar/emulatedcommandbar.h> 0014 #include <vimode/macrorecorder.h> 0015 #include <vimode/marks.h> 0016 #include <vimode/modes/replacevimode.h> 0017 #include <vimode/modes/visualvimode.h> 0018 #include <vimode/searcher.h> 0019 0020 #include <KLocalizedString> 0021 0022 #include <QCoreApplication> 0023 0024 namespace 0025 { 0026 QString viModeToString(KateVi::ViMode mode) 0027 { 0028 QString modeStr; 0029 switch (mode) { 0030 case KateVi::InsertMode: 0031 modeStr = i18n("VI: INSERT MODE"); 0032 break; 0033 case KateVi::NormalMode: 0034 modeStr = i18n("VI: NORMAL MODE"); 0035 break; 0036 case KateVi::VisualMode: 0037 modeStr = i18n("VI: VISUAL"); 0038 break; 0039 case KateVi::VisualBlockMode: 0040 modeStr = i18n("VI: VISUAL BLOCK"); 0041 break; 0042 case KateVi::VisualLineMode: 0043 modeStr = i18n("VI: VISUAL LINE"); 0044 break; 0045 case KateVi::ReplaceMode: 0046 modeStr = i18n("VI: REPLACE"); 0047 break; 0048 } 0049 0050 return modeStr; 0051 } 0052 } 0053 0054 KateViInputMode::KateViInputMode(KateViewInternal *viewInternal, KateVi::GlobalState *global) 0055 : KateAbstractInputMode(viewInternal) 0056 , m_viModeEmulatedCommandBar(nullptr) 0057 , m_viGlobal(global) 0058 , m_caret(KTextEditor::caretStyles::Block) 0059 , m_nextKeypressIsOverriddenShortCut(false) 0060 , m_relLineNumbers(KateViewConfig::global()->viRelativeLineNumbers()) 0061 , m_activated(false) 0062 , m_viModeManager(new KateVi::InputModeManager(this, view(), viewInternal)) 0063 { 0064 } 0065 0066 void KateViInputMode::activate() 0067 { 0068 m_activated = true; 0069 setCaretStyle(KTextEditor::caretStyles::Block); // TODO: can we end up in insert mode? 0070 reset(); // TODO: is this necessary? (well, not anymore I guess) 0071 0072 if (view()->selection()) { 0073 m_viModeManager->changeViMode(KateVi::VisualMode); 0074 view()->setCursorPosition(KTextEditor::Cursor(view()->selectionRange().end().line(), view()->selectionRange().end().column() - 1)); 0075 m_viModeManager->m_viVisualMode->updateSelection(); 0076 } 0077 viewInternal()->iconBorder()->setRelLineNumbersOn(m_relLineNumbers); 0078 } 0079 0080 void KateViInputMode::deactivate() 0081 { 0082 if (m_viModeEmulatedCommandBar) { 0083 m_viModeEmulatedCommandBar->hideMe(); 0084 } 0085 0086 // make sure to turn off edits merging when leaving vi input mode 0087 view()->doc()->setUndoMergeAllEdits(false); 0088 m_activated = false; 0089 viewInternal()->iconBorder()->setRelLineNumbersOn(false); 0090 m_viModeManager->searcher()->enableHighlightSearch(false); 0091 } 0092 0093 void KateViInputMode::reset() 0094 { 0095 if (m_viModeEmulatedCommandBar) { 0096 m_viModeEmulatedCommandBar->hideMe(); 0097 } 0098 0099 // ensure first the old stuff is deleted and then the new manager is constructed 0100 m_viModeManager.reset(); 0101 m_viModeManager.reset(new KateVi::InputModeManager(this, view(), viewInternal())); 0102 0103 if (m_viModeEmulatedCommandBar) { 0104 m_viModeEmulatedCommandBar->setViInputModeManager(m_viModeManager.get()); 0105 } 0106 } 0107 0108 bool KateViInputMode::overwrite() const 0109 { 0110 return m_viModeManager->getCurrentViMode() == KateVi::ViMode::ReplaceMode; 0111 } 0112 0113 void KateViInputMode::overwrittenChar(const QChar &c) 0114 { 0115 m_viModeManager->getViReplaceMode()->overwrittenChar(c); 0116 } 0117 0118 void KateViInputMode::clearSelection() 0119 { 0120 // do nothing, handled elsewhere 0121 } 0122 0123 bool KateViInputMode::stealKey(QKeyEvent *k) 0124 { 0125 if (!KateViewConfig::global()->viInputModeStealKeys()) { 0126 return false; 0127 } 0128 0129 // Actually see if we can make use of this key - if so, we've stolen it; if not, 0130 // let Qt's shortcut handling system deal with it. 0131 const bool stolen = keyPress(k); 0132 if (stolen) { 0133 // Qt will replay this QKeyEvent, next time as an ordinary KeyPress. 0134 m_nextKeypressIsOverriddenShortCut = true; 0135 } 0136 return stolen; 0137 } 0138 0139 KTextEditor::View::InputMode KateViInputMode::viewInputMode() const 0140 { 0141 return KTextEditor::View::ViInputMode; 0142 } 0143 0144 QString KateViInputMode::viewInputModeHuman() const 0145 { 0146 return i18n("vi-mode"); 0147 } 0148 0149 KTextEditor::View::ViewMode KateViInputMode::viewMode() const 0150 { 0151 return m_viModeManager->getCurrentViewMode(); 0152 } 0153 0154 QString KateViInputMode::viewModeHuman() const 0155 { 0156 QString currentMode = viModeToString(m_viModeManager->getCurrentViMode()); 0157 0158 if (m_viModeManager->macroRecorder()->isRecording()) { 0159 currentMode.prepend(QLatin1Char('(') + i18n("recording") + QLatin1String(") ")); 0160 } 0161 0162 QString cmd = m_viModeManager->getVerbatimKeys(); 0163 if (!cmd.isEmpty()) { 0164 currentMode.prepend(QStringLiteral("%1 ").arg(cmd)); 0165 } 0166 0167 return currentMode; 0168 } 0169 0170 void KateViInputMode::gotFocus() 0171 { 0172 // nothing to do 0173 } 0174 0175 void KateViInputMode::lostFocus() 0176 { 0177 // nothing to do 0178 } 0179 0180 void KateViInputMode::readSessionConfig(const KConfigGroup &config) 0181 { 0182 // restore vi registers and jump list 0183 m_viModeManager->readSessionConfig(config); 0184 } 0185 0186 void KateViInputMode::writeSessionConfig(KConfigGroup &config) 0187 { 0188 // save vi registers and jump list 0189 m_viModeManager->writeSessionConfig(config); 0190 } 0191 0192 void KateViInputMode::updateConfig() 0193 { 0194 KateViewConfig *cfg = view()->config(); 0195 0196 // whether relative line numbers should be used or not. 0197 m_relLineNumbers = cfg->viRelativeLineNumbers(); 0198 0199 if (m_activated) { 0200 viewInternal()->iconBorder()->setRelLineNumbersOn(m_relLineNumbers); 0201 } 0202 } 0203 0204 void KateViInputMode::readWriteChanged(bool) 0205 { 0206 // nothing todo 0207 } 0208 0209 void KateViInputMode::find() 0210 { 0211 showViModeEmulatedCommandBar(); 0212 viModeEmulatedCommandBar()->init(KateVi::EmulatedCommandBar::SearchForward); 0213 } 0214 0215 void KateViInputMode::findSelectedForwards() 0216 { 0217 m_viModeManager->searcher()->findNext(); 0218 } 0219 0220 void KateViInputMode::findSelectedBackwards() 0221 { 0222 m_viModeManager->searcher()->findPrevious(); 0223 } 0224 0225 void KateViInputMode::findReplace() 0226 { 0227 showViModeEmulatedCommandBar(); 0228 viModeEmulatedCommandBar()->init(KateVi::EmulatedCommandBar::SearchForward); 0229 } 0230 0231 void KateViInputMode::findNext() 0232 { 0233 m_viModeManager->searcher()->findNext(); 0234 } 0235 0236 void KateViInputMode::findPrevious() 0237 { 0238 m_viModeManager->searcher()->findPrevious(); 0239 } 0240 0241 void KateViInputMode::activateCommandLine() 0242 { 0243 showViModeEmulatedCommandBar(); 0244 viModeEmulatedCommandBar()->init(KateVi::EmulatedCommandBar::Command); 0245 } 0246 0247 void KateViInputMode::showViModeEmulatedCommandBar() 0248 { 0249 view()->bottomViewBar()->addBarWidget(viModeEmulatedCommandBar()); 0250 view()->bottomViewBar()->showBarWidget(viModeEmulatedCommandBar()); 0251 } 0252 0253 KateVi::EmulatedCommandBar *KateViInputMode::viModeEmulatedCommandBar() 0254 { 0255 if (!m_viModeEmulatedCommandBar) { 0256 m_viModeEmulatedCommandBar = new KateVi::EmulatedCommandBar(this, m_viModeManager.get(), view()); 0257 m_viModeEmulatedCommandBar->hide(); 0258 } 0259 0260 return m_viModeEmulatedCommandBar; 0261 } 0262 0263 void KateViInputMode::updateRendererConfig() 0264 { 0265 m_viModeManager->searcher()->updateHighlightColors(); 0266 } 0267 0268 bool KateViInputMode::keyPress(QKeyEvent *e) 0269 { 0270 if (m_nextKeypressIsOverriddenShortCut) { 0271 // This is just the replay of a shortcut that we stole, this time as a QKeyEvent. 0272 // Ignore it, as we'll have already handled it via stealKey()! 0273 m_nextKeypressIsOverriddenShortCut = false; 0274 return true; 0275 } 0276 0277 if (m_viModeManager->handleKeypress(e)) { 0278 Q_EMIT view()->viewModeChanged(view(), viewMode()); 0279 return true; 0280 } 0281 0282 return false; 0283 } 0284 0285 bool KateViInputMode::blinkCaret() const 0286 { 0287 return false; 0288 } 0289 0290 KTextEditor::caretStyles KateViInputMode::caretStyle() const 0291 { 0292 return m_caret; 0293 } 0294 0295 void KateViInputMode::toggleInsert() 0296 { 0297 // do nothing 0298 } 0299 0300 void KateViInputMode::launchInteractiveCommand(const QString &) 0301 { 0302 // do nothing so far 0303 } 0304 0305 QString KateViInputMode::bookmarkLabel(int line) const 0306 { 0307 return m_viModeManager->marks()->getMarksOnTheLine(line); 0308 } 0309 0310 void KateViInputMode::setCaretStyle(const KTextEditor::caretStyles caret) 0311 { 0312 if (m_caret != caret) { 0313 m_caret = caret; 0314 0315 view()->renderer()->setCaretStyle(m_caret); 0316 view()->renderer()->setDrawCaret(true); 0317 viewInternal()->paintCursor(); 0318 } 0319 }