diff --git a/src/vimode/lastchangerecorder.cpp b/src/vimode/lastchangerecorder.cpp index 77fe24c9..ff44f63d 100644 --- a/src/vimode/lastchangerecorder.cpp +++ b/src/vimode/lastchangerecorder.cpp @@ -1,105 +1,122 @@ /* * This file is part of the KDE libraries * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "lastchangerecorder.h" #include #include #include "completionreplayer.h" using namespace KateVi; +bool KateVi::isRepeatOfLastShortcutOverrideAsKeyPress(const QKeyEvent& currentKeyPress, const QList& keyEventLog) +{ + if (keyEventLog.empty()) + return false; + const QKeyEvent& lastKeyPress = keyEventLog.last(); + if (lastKeyPress.type() == QEvent::ShortcutOverride && currentKeyPress.type() == QEvent::KeyPress && + lastKeyPress.key() == currentKeyPress.key() && + lastKeyPress.modifiers() == currentKeyPress.modifiers()) + { + return true; + } + return false; +} + LastChangeRecorder::LastChangeRecorder(InputModeManager *viInputModeManager) : m_viInputModeManager(viInputModeManager) , m_isReplaying(false) { } LastChangeRecorder::~LastChangeRecorder() { } void LastChangeRecorder::record(const QKeyEvent &e) { + if (isRepeatOfLastShortcutOverrideAsKeyPress(e, m_changeLog)) + return; + if (e.key() != Qt::Key_Shift && e.key() != Qt::Key_Control && e.key() != Qt::Key_Meta && e.key() != Qt::Key_Alt) { m_changeLog.append(e); } } void LastChangeRecorder::dropLast() { Q_ASSERT(!m_changeLog.isEmpty()); m_changeLog.pop_back(); } void LastChangeRecorder::clear() { m_changeLog.clear(); } QString LastChangeRecorder::encodedChanges() const { QString result; QList keyLog = m_changeLog; for (int i = 0; i < keyLog.size(); i++) { int keyCode = keyLog.at(i).key(); QString text = keyLog.at(i).text(); int mods = keyLog.at(i).modifiers(); QChar key; if (text.length() > 0) { key = text.at(0); } if (text.isEmpty() || (text.length() == 1 && text.at(0) < 0x20) || (mods != Qt::NoModifier && mods != Qt::ShiftModifier)) { QString keyPress; keyPress.append(QLatin1Char('<')); keyPress.append((mods & Qt::ShiftModifier) ? QStringLiteral("s-") : QString()); keyPress.append((mods & Qt::ControlModifier) ? QStringLiteral("c-") : QString()); keyPress.append((mods & Qt::AltModifier) ? QStringLiteral("a-") : QString()); keyPress.append((mods & Qt::MetaModifier) ? QStringLiteral("m-") : QString()); keyPress.append(keyCode <= 0xFF ? QChar(keyCode) : KeyParser::self()->qt2vi(keyCode)); keyPress.append(QLatin1Char('>')); key = KeyParser::self()->encodeKeySequence(keyPress).at(0); } result.append(key); } return result; } bool LastChangeRecorder::isReplaying() const { return m_isReplaying; } void LastChangeRecorder::replay(const QString &commands, const CompletionList &completions) { m_isReplaying = true; m_viInputModeManager->completionReplayer()->start(completions); m_viInputModeManager->feedKeyPresses(commands); m_viInputModeManager->completionReplayer()->stop(); m_isReplaying = false; } diff --git a/src/vimode/lastchangerecorder.h b/src/vimode/lastchangerecorder.h index 2cfdf338..4a9efffa 100644 --- a/src/vimode/lastchangerecorder.h +++ b/src/vimode/lastchangerecorder.h @@ -1,58 +1,65 @@ /* * This file is part of the KDE libraries * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef KATEVI_LASTCHANGERECORDER_H #define KATEVI_LASTCHANGERECORDER_H #include "completion.h" #include #include #include namespace KateVi { class InputModeManager; +/** + * In e.g. Insert mode, Qt seems to feed each keypress through twice; once as a ShortcutOverride (even if the key + * doesn't actually appear to be a ShortcutOverride) and then, whether the "ShortcutOverride" was accepted or not, + * again as a KeyPress. We don't want to store both, so this helper helps to decide what to do. + */ +bool isRepeatOfLastShortcutOverrideAsKeyPress(const QKeyEvent& currentKeyPress, const QList& keyEventLog); + class LastChangeRecorder { public: explicit LastChangeRecorder(InputModeManager *viInputModeManager); ~LastChangeRecorder(); void record(const QKeyEvent &event); void dropLast(); void clear(); QString encodedChanges() const; void replay(const QString &commands, const CompletionList &completions); bool isReplaying() const; private: InputModeManager *m_viInputModeManager; QList m_changeLog; bool m_isReplaying; }; } #endif // KATEVI_LASTCHANGERECORDER_H diff --git a/src/vimode/macrorecorder.cpp b/src/vimode/macrorecorder.cpp index 24e54874..9a8d6c15 100644 --- a/src/vimode/macrorecorder.cpp +++ b/src/vimode/macrorecorder.cpp @@ -1,106 +1,109 @@ /* * This file is part of the KDE libraries * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "macrorecorder.h" #include #include "completionrecorder.h" #include "kateview.h" #include #include "globalstate.h" #include "macros.h" #include "completionreplayer.h" +#include "lastchangerecorder.h" namespace { const QChar LastPlayedRegister = QLatin1Char('@'); } using namespace KateVi; MacroRecorder::MacroRecorder(InputModeManager *viInputModeManager) : m_viInputModeManager(viInputModeManager) , m_isRecording(false) , m_macrosBeingReplayedCount(0) , m_lastPlayedMacroRegister(QChar::Null) { } MacroRecorder::~MacroRecorder() { } void MacroRecorder::start(const QChar ¯oRegister) { Q_ASSERT(!m_isRecording); m_isRecording = true; m_register = macroRegister; m_viInputModeManager->globalState()->macros()->remove(macroRegister); m_eventsLog.clear(); m_viInputModeManager->completionRecorder()->start(); } void MacroRecorder::stop() { Q_ASSERT(m_isRecording); m_isRecording = false; CompletionList completions = m_viInputModeManager->completionRecorder()->stop(); m_viInputModeManager->globalState()->macros()->store(m_register, m_eventsLog, completions); } bool MacroRecorder::isRecording() const { return m_isRecording; } void MacroRecorder::record(const QKeyEvent &event) { + if (isRepeatOfLastShortcutOverrideAsKeyPress(event, m_eventsLog)) + return; m_eventsLog.append(event); } void MacroRecorder::dropLast() { if (m_isRecording) { Q_ASSERT(!m_eventsLog.isEmpty()); m_eventsLog.pop_back(); } } void MacroRecorder::replay(const QChar ¯oRegister) { const QChar reg = (macroRegister == LastPlayedRegister) ? m_lastPlayedMacroRegister : macroRegister; m_lastPlayedMacroRegister = reg; const QString macroAsFeedableKeypresses = m_viInputModeManager->globalState()->macros()->get(reg); QSharedPointer mapper(new KeyMapper(m_viInputModeManager, m_viInputModeManager->view()->doc(), m_viInputModeManager->view())); CompletionList completions = m_viInputModeManager->globalState()->macros()->getCompletions(reg); m_macrosBeingReplayedCount++; m_viInputModeManager->completionReplayer()->start(completions); m_viInputModeManager->pushKeyMapper(mapper); m_viInputModeManager->feedKeyPresses(macroAsFeedableKeypresses); m_viInputModeManager->popKeyMapper(); m_viInputModeManager->completionReplayer()->stop(); m_macrosBeingReplayedCount--; } bool MacroRecorder::isReplaying() { return m_macrosBeingReplayedCount > 0; }