File indexing completed on 2024-04-28 11:45:58

0001 /*
0002     SPDX-FileCopyrightText: KDE Developers
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "macros.h"
0008 #include <vimode/keyparser.h>
0009 
0010 #include <KConfigGroup>
0011 
0012 using namespace KateVi;
0013 
0014 Macros::Macros() = default;
0015 
0016 Macros::~Macros() = default;
0017 
0018 void Macros::writeConfig(KConfigGroup &config) const
0019 {
0020     const auto macroKeys = m_macros.keys();
0021     QStringList macroRegisters;
0022     for (const QChar macroRegister : macroKeys) {
0023         macroRegisters.append(macroRegister);
0024     }
0025     QStringList macroContents;
0026     for (const QChar macroRegister : macroKeys) {
0027         macroContents.append(KeyParser::self()->decodeKeySequence(m_macros[macroRegister]));
0028     }
0029     QStringList macroCompletions;
0030     for (const QChar macroRegister : macroKeys) {
0031         macroCompletions.append(QString::number(m_completions[macroRegister].length()));
0032         for (const Completion &completionForMacro : m_completions[macroRegister]) {
0033             macroCompletions.append(encodeMacroCompletionForConfig(completionForMacro));
0034         }
0035     }
0036     config.writeEntry("Macro Registers", macroRegisters);
0037     config.writeEntry("Macro Contents", macroContents);
0038     config.writeEntry("Macro Completions", macroCompletions);
0039 }
0040 
0041 void Macros::readConfig(const KConfigGroup &config)
0042 {
0043     const QStringList macroRegisters = config.readEntry("Macro Registers", QStringList());
0044     const QStringList macroContents = config.readEntry("Macro Contents", QStringList());
0045     const QStringList macroCompletions = config.readEntry("Macro Completions", QStringList());
0046     int macroCompletionsIndex = 0;
0047     if (macroRegisters.length() == macroContents.length()) {
0048         for (int macroIndex = 0; macroIndex < macroRegisters.length(); macroIndex++) {
0049             const QChar macroRegister = macroRegisters[macroIndex].at(0);
0050             m_macros[macroRegister] = KeyParser::self()->encodeKeySequence(macroContents[macroIndex]);
0051             macroCompletionsIndex = readMacroCompletions(macroRegister, macroCompletions, macroCompletionsIndex);
0052         }
0053     }
0054 }
0055 
0056 void Macros::clear()
0057 {
0058     m_macros.clear();
0059 }
0060 
0061 void Macros::remove(const QChar &reg)
0062 {
0063     m_macros.remove(reg);
0064 }
0065 
0066 void Macros::store(const QChar &reg, const QList<KeyEvent> &macroKeyEventLog, const CompletionList &completions)
0067 {
0068     m_macros[reg].clear();
0069     QList<KeyEvent> withoutClosingQ = macroKeyEventLog;
0070     Q_ASSERT(!macroKeyEventLog.isEmpty() && macroKeyEventLog.last().key() == Qt::Key_Q);
0071     withoutClosingQ.pop_back();
0072     for (const KeyEvent &keyEvent : std::as_const(withoutClosingQ)) {
0073         const QChar key = KeyParser::self()->KeyEventToQChar(keyEvent);
0074         m_macros[reg].append(key);
0075     }
0076     m_completions[reg] = completions;
0077 }
0078 
0079 QString Macros::get(const QChar &reg) const
0080 {
0081     return m_macros.contains(reg) ? m_macros[reg] : QString();
0082 }
0083 
0084 CompletionList Macros::getCompletions(const QChar &reg) const
0085 {
0086     return m_completions.contains(reg) ? m_completions[reg] : CompletionList();
0087 }
0088 
0089 int Macros::readMacroCompletions(const QChar &reg, const QStringList &encodedMacroCompletions, int macroCompletionsIndex)
0090 {
0091     if (macroCompletionsIndex < encodedMacroCompletions.length()) {
0092         bool parsedNumCompletionsSuccessfully = false;
0093         const QString numCompletionsAsString = encodedMacroCompletions[macroCompletionsIndex++];
0094         const int numCompletions = numCompletionsAsString.toInt(&parsedNumCompletionsSuccessfully);
0095         int count = 0;
0096         m_completions[reg].clear();
0097         while (count < numCompletions && macroCompletionsIndex < encodedMacroCompletions.length()) {
0098             const QString encodedMacroCompletion = encodedMacroCompletions[macroCompletionsIndex++];
0099             count++;
0100             m_completions[reg].append(decodeMacroCompletionFromConfig(encodedMacroCompletion));
0101         }
0102     }
0103     return macroCompletionsIndex;
0104 }
0105 
0106 QString Macros::encodeMacroCompletionForConfig(const Completion &completionForMacro)
0107 {
0108     const bool endedWithSemiColon = completionForMacro.completedText().endsWith(QLatin1Char(';'));
0109     QString encodedMacroCompletion = completionForMacro.completedText().remove(QStringLiteral("()")).remove(QLatin1Char(';'));
0110     if (completionForMacro.completionType() == Completion::FunctionWithArgs) {
0111         encodedMacroCompletion += QLatin1String("(...)");
0112     } else if (completionForMacro.completionType() == Completion::FunctionWithoutArgs) {
0113         encodedMacroCompletion += QLatin1String("()");
0114     }
0115     if (endedWithSemiColon) {
0116         encodedMacroCompletion += QLatin1Char(';');
0117     }
0118     if (completionForMacro.removeTail()) {
0119         encodedMacroCompletion += QLatin1Char('|');
0120     }
0121     return encodedMacroCompletion;
0122 }
0123 
0124 Completion Macros::decodeMacroCompletionFromConfig(const QString &encodedMacroCompletion)
0125 {
0126     const bool removeTail = encodedMacroCompletion.endsWith(QLatin1Char('|'));
0127     Completion::CompletionType completionType = Completion::PlainText;
0128     if (encodedMacroCompletion.contains(QLatin1String("(...)"))) {
0129         completionType = Completion::FunctionWithArgs;
0130     } else if (encodedMacroCompletion.contains(QLatin1String("()"))) {
0131         completionType = Completion::FunctionWithoutArgs;
0132     }
0133     QString completionText = encodedMacroCompletion;
0134     completionText.replace(QLatin1String("(...)"), QLatin1String("()")).remove(QLatin1Char('|'));
0135 
0136     return Completion(completionText, removeTail, completionType);
0137 }