1/*
2 SPDX-FileCopyrightText: KDE Developers
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "macros.h"
8#include <vimode/keyparser.h>
9
10#include <KConfigGroup>
11
12using namespace KateVi;
13
14Macros::Macros() = default;
15
16Macros::~Macros() = default;
17
18void Macros::writeConfig(KConfigGroup &config) const
19{
20 const auto macroKeys = m_macros.keys();
21 QStringList macroRegisters;
22 for (const QChar macroRegister : macroKeys) {
23 macroRegisters.append(t: macroRegister);
24 }
25 QStringList macroContents;
26 for (const QChar macroRegister : macroKeys) {
27 macroContents.append(t: KeyParser::self()->decodeKeySequence(keys: m_macros[macroRegister]));
28 }
29 QStringList macroCompletions;
30 for (const QChar macroRegister : macroKeys) {
31 macroCompletions.append(t: QString::number(m_completions[macroRegister].length()));
32 for (const Completion &completionForMacro : m_completions[macroRegister]) {
33 macroCompletions.append(t: encodeMacroCompletionForConfig(completionForMacro));
34 }
35 }
36 config.writeEntry(key: "Macro Registers", value: macroRegisters);
37 config.writeEntry(key: "Macro Contents", value: macroContents);
38 config.writeEntry(key: "Macro Completions", value: macroCompletions);
39}
40
41void Macros::readConfig(const KConfigGroup &config)
42{
43 const QStringList macroRegisters = config.readEntry(key: "Macro Registers", aDefault: QStringList());
44 const QStringList macroContents = config.readEntry(key: "Macro Contents", aDefault: QStringList());
45 const QStringList macroCompletions = config.readEntry(key: "Macro Completions", aDefault: QStringList());
46 int macroCompletionsIndex = 0;
47 if (macroRegisters.length() == macroContents.length()) {
48 for (int macroIndex = 0; macroIndex < macroRegisters.length(); macroIndex++) {
49 const QChar macroRegister = macroRegisters[macroIndex].at(i: 0);
50 m_macros[macroRegister] = KeyParser::self()->encodeKeySequence(keys: macroContents[macroIndex]);
51 macroCompletionsIndex = readMacroCompletions(reg: macroRegister, encodedMacroCompletions: macroCompletions, macroCompletionIndex: macroCompletionsIndex);
52 }
53 }
54}
55
56void Macros::clear()
57{
58 m_macros.clear();
59}
60
61void Macros::remove(const QChar &reg)
62{
63 m_macros.remove(key: reg);
64}
65
66void Macros::store(const QChar &reg, const QList<KeyEvent> &macroKeyEventLog, const CompletionList &completions)
67{
68 m_macros[reg].clear();
69 QList<KeyEvent> withoutClosingQ = macroKeyEventLog;
70 Q_ASSERT(!macroKeyEventLog.isEmpty() && macroKeyEventLog.last().key() == Qt::Key_Q);
71 withoutClosingQ.pop_back();
72 for (const KeyEvent &keyEvent : std::as_const(t&: withoutClosingQ)) {
73 const QChar key = KeyParser::self()->KeyEventToQChar(keyEvent);
74 m_macros[reg].append(c: key);
75 }
76 m_completions[reg] = completions;
77}
78
79QString Macros::get(const QChar &reg) const
80{
81 return m_macros.contains(key: reg) ? m_macros[reg] : QString();
82}
83
84CompletionList Macros::getCompletions(const QChar &reg) const
85{
86 return m_completions.contains(key: reg) ? m_completions[reg] : CompletionList();
87}
88
89int Macros::readMacroCompletions(const QChar &reg, const QStringList &encodedMacroCompletions, int macroCompletionsIndex)
90{
91 if (macroCompletionsIndex < encodedMacroCompletions.length()) {
92 bool parsedNumCompletionsSuccessfully = false;
93 const QString numCompletionsAsString = encodedMacroCompletions[macroCompletionsIndex++];
94 const int numCompletions = numCompletionsAsString.toInt(ok: &parsedNumCompletionsSuccessfully);
95 int count = 0;
96 m_completions[reg].clear();
97 while (count < numCompletions && macroCompletionsIndex < encodedMacroCompletions.length()) {
98 const QString encodedMacroCompletion = encodedMacroCompletions[macroCompletionsIndex++];
99 count++;
100 m_completions[reg].append(t: decodeMacroCompletionFromConfig(encodedMacroCompletion));
101 }
102 }
103 return macroCompletionsIndex;
104}
105
106QString Macros::encodeMacroCompletionForConfig(const Completion &completionForMacro)
107{
108 const bool endedWithSemiColon = completionForMacro.completedText().endsWith(c: QLatin1Char(';'));
109 QString encodedMacroCompletion = completionForMacro.completedText().remove(QStringLiteral("()")).remove(c: QLatin1Char(';'));
110 if (completionForMacro.completionType() == Completion::FunctionWithArgs) {
111 encodedMacroCompletion += QLatin1String("(...)");
112 } else if (completionForMacro.completionType() == Completion::FunctionWithoutArgs) {
113 encodedMacroCompletion += QLatin1String("()");
114 }
115 if (endedWithSemiColon) {
116 encodedMacroCompletion += QLatin1Char(';');
117 }
118 if (completionForMacro.removeTail()) {
119 encodedMacroCompletion += QLatin1Char('|');
120 }
121 return encodedMacroCompletion;
122}
123
124Completion Macros::decodeMacroCompletionFromConfig(const QString &encodedMacroCompletion)
125{
126 const bool removeTail = encodedMacroCompletion.endsWith(c: QLatin1Char('|'));
127 Completion::CompletionType completionType = Completion::PlainText;
128 if (encodedMacroCompletion.contains(s: QLatin1String("(...)"))) {
129 completionType = Completion::FunctionWithArgs;
130 } else if (encodedMacroCompletion.contains(s: QLatin1String("()"))) {
131 completionType = Completion::FunctionWithoutArgs;
132 }
133 QString completionText = encodedMacroCompletion;
134 completionText.replace(before: QLatin1String("(...)"), after: QLatin1String("()")).remove(c: QLatin1Char('|'));
135
136 return Completion(completionText, removeTail, completionType);
137}
138

source code of ktexteditor/src/vimode/macros.cpp