KTextEditor

cmds.cpp
1 /*
2  SPDX-FileCopyrightText: 2003-2005 Anders Lund <[email protected]>
3  SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <[email protected]>
4  SPDX-FileCopyrightText: 2001 Charles Samuels <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include <vimode/cmds.h>
10 
11 #include "globalstate.h"
12 #include "katecmd.h"
13 #include "katedocument.h"
14 #include "kateglobal.h"
15 #include "katepartdebug.h"
16 #include "kateview.h"
17 #include "kateviinputmode.h"
18 #include "marks.h"
19 #include <vimode/emulatedcommandbar/emulatedcommandbar.h>
20 #include <vimode/inputmodemanager.h>
21 #include <vimode/modes/normalvimode.h>
22 
23 #include <KLocalizedString>
24 
25 #include <QDir>
26 #include <QRegularExpression>
27 #include <QUrl>
28 
29 using namespace KateVi;
30 
31 // BEGIN ViCommands
32 Commands *Commands::m_instance = nullptr;
33 
34 bool Commands::exec(KTextEditor::View *view, const QString &_cmd, QString &msg, const KTextEditor::Range &range)
35 {
36  Q_UNUSED(range)
37  // cast it hardcore, we know that it is really a kateview :)
38  KTextEditor::ViewPrivate *v = static_cast<KTextEditor::ViewPrivate *>(view);
39 
40  if (!v) {
41  msg = i18n("Could not access view");
42  return false;
43  }
44 
45  // create a list of args
46 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
47  QStringList args(_cmd.split(QRegularExpression(QStringLiteral("\\s+")), QString::SkipEmptyParts));
48 #else
49  QStringList args(_cmd.split(QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts));
50 #endif
51  QString cmd(args.takeFirst());
52 
53  // ALL commands that takes no arguments.
54  if (mappingCommands().contains(cmd)) {
55  if (cmd.endsWith(QLatin1String("unmap"))) {
56  if (args.count() == 1) {
57  m_viGlobal->mappings()->remove(modeForMapCommand(cmd), args.at(0));
58  return true;
59  } else {
60  msg = i18n("Missing argument. Usage: %1 <from>", cmd);
61  return false;
62  }
63  }
64  if (args.count() == 1) {
65  msg = m_viGlobal->mappings()->get(modeForMapCommand(cmd), args.at(0), true);
66  if (msg.isEmpty()) {
67  msg = i18n("No mapping found for \"%1\"", args.at(0));
68  return false;
69  } else {
70  msg = i18n("\"%1\" is mapped to \"%2\"", args.at(0), msg);
71  }
72  } else if (args.count() == 2) {
73  Mappings::MappingRecursion mappingRecursion = (isMapCommandRecursive(cmd)) ? Mappings::Recursive : Mappings::NonRecursive;
74  m_viGlobal->mappings()->add(modeForMapCommand(cmd), args.at(0), args.at(1), mappingRecursion);
75  } else {
76  msg = i18n("Missing argument(s). Usage: %1 <from> [<to>]", cmd);
77  return false;
78  }
79 
80  return true;
81  }
82 
83  NormalViMode *nm = m_viInputModeManager->getViNormalMode();
84 
85  if (cmd == QLatin1String("d") || cmd == QLatin1String("delete") || cmd == QLatin1String("j") || cmd == QLatin1String("c") || cmd == QLatin1String("change") || cmd == QLatin1String("<") || cmd == QLatin1String(">") ||
86  cmd == QLatin1String("y") || cmd == QLatin1String("yank")) {
87  KTextEditor::Cursor start_cursor_position = v->cursorPosition();
88 
89  int count = 1;
90  if (range.isValid()) {
91  count = qAbs(range.end().line() - range.start().line()) + 1;
92  v->setCursorPosition(KTextEditor::Cursor(qMin(range.start().line(), range.end().line()), 0));
93  }
94 
95  static const QRegularExpression number(QStringLiteral("^(\\d+)$"));
96  for (int i = 0; i < args.count(); i++) {
97  auto match = number.match(args.at(i));
98  if (match.hasMatch()) {
99  count += match.captured(0).toInt() - 1;
100  }
101 
102  QChar r = args.at(i).at(0);
103  if (args.at(i).size() == 1 && ((r >= QLatin1Char('a') && r <= QLatin1Char('z')) || r == QLatin1Char('_') || r == QLatin1Char('-') || r == QLatin1Char('+') || r == QLatin1Char('*'))) {
104  nm->setRegister(r);
105  }
106  }
107 
108  nm->setCount(count);
109 
110  if (cmd == QLatin1String("d") || cmd == QLatin1String("delete")) {
111  nm->commandDeleteLine();
112  }
113  if (cmd == QLatin1String("j")) {
114  nm->commandJoinLines();
115  }
116  if (cmd == QLatin1String("c") || cmd == QLatin1String("change")) {
117  nm->commandChangeLine();
118  }
119  if (cmd == QLatin1String("<")) {
120  nm->commandUnindentLine();
121  }
122  if (cmd == QLatin1String(">")) {
123  nm->commandIndentLine();
124  }
125  if (cmd == QLatin1String("y") || cmd == QLatin1String("yank")) {
126  nm->commandYankLine();
127  v->setCursorPosition(start_cursor_position);
128  }
129 
130  // TODO - should we resetParser, here? We'd have to make it public, if so.
131  // Or maybe synthesise a KateViCommand to execute instead ... ?
132  nm->setCount(0);
133 
134  return true;
135  }
136 
137  if (cmd == QLatin1String("mark") || cmd == QLatin1String("ma") || cmd == QLatin1String("k")) {
138  if (args.count() == 0) {
139  if (cmd == QLatin1String("mark")) {
140  // TODO: show up mark list;
141  } else {
142  msg = i18n("Wrong arguments");
143  return false;
144  }
145  } else if (args.count() == 1) {
146  QChar r = args.at(0).at(0);
147  int line;
148  if ((r >= QLatin1Char('a') && r <= QLatin1Char('z')) || r == QLatin1Char('_') || r == QLatin1Char('+') || r == QLatin1Char('*')) {
149  if (range.isValid()) {
150  line = qMax(range.end().line(), range.start().line());
151  } else {
152  line = v->cursorPosition().line();
153  }
154 
155  m_viInputModeManager->marks()->setUserMark(r, KTextEditor::Cursor(line, 0));
156  }
157  } else {
158  msg = i18n("Wrong arguments");
159  return false;
160  }
161  return true;
162  }
163 
164  // should not happen :)
165  msg = i18n("Unknown command '%1'", cmd);
166  return false;
167 }
168 
170 {
171  static QStringList l;
172 
173  if (l.isEmpty())
174  l << QStringLiteral("d") << QStringLiteral("delete") << QStringLiteral("j") << QStringLiteral("c") << QStringLiteral("change") << QStringLiteral("<") << QStringLiteral(">") << QStringLiteral("y") << QStringLiteral("yank")
175  << QStringLiteral("ma") << QStringLiteral("mark") << QStringLiteral("k");
176 
177  return l.contains(range.split(QLatin1Char(' ')).at(0));
178 }
179 
181 {
182  Q_UNUSED(view)
183 
184  KTextEditor::ViewPrivate *v = static_cast<KTextEditor::ViewPrivate *>(view);
185 
186  if (v && (cmd == QLatin1String("nn") || cmd == QLatin1String("nnoremap"))) {
187  QStringList l = m_viGlobal->mappings()->getAll(Mappings::NormalModeMapping);
188 
190  co->setItems(l);
191  co->setIgnoreCase(false);
192  return co;
193  }
194  return nullptr;
195 }
196 
197 const QStringList &Commands::mappingCommands()
198 {
199  static QStringList mappingsCommands;
200  if (mappingsCommands.isEmpty()) {
201  mappingsCommands << QStringLiteral("nmap") << QStringLiteral("nm") << QStringLiteral("noremap") << QStringLiteral("nnoremap") << QStringLiteral("nn") << QStringLiteral("no") << QStringLiteral("vmap") << QStringLiteral("vm")
202  << QStringLiteral("vnoremap") << QStringLiteral("vn") << QStringLiteral("imap") << QStringLiteral("im") << QStringLiteral("inoremap") << QStringLiteral("ino") << QStringLiteral("cmap") << QStringLiteral("cm")
203  << QStringLiteral("cnoremap") << QStringLiteral("cno");
204 
205  mappingsCommands << QStringLiteral("nunmap") << QStringLiteral("vunmap") << QStringLiteral("iunmap") << QStringLiteral("cunmap");
206  }
207  return mappingsCommands;
208 }
209 
210 Mappings::MappingMode Commands::modeForMapCommand(const QString &mapCommand)
211 {
212  static QMap<QString, Mappings::MappingMode> modeForMapCommand;
213  if (modeForMapCommand.isEmpty()) {
214  // Normal is the default.
215  modeForMapCommand.insert(QStringLiteral("vmap"), Mappings::VisualModeMapping);
216  modeForMapCommand.insert(QStringLiteral("vm"), Mappings::VisualModeMapping);
217  modeForMapCommand.insert(QStringLiteral("vnoremap"), Mappings::VisualModeMapping);
218  modeForMapCommand.insert(QStringLiteral("vn"), Mappings::VisualModeMapping);
219  modeForMapCommand.insert(QStringLiteral("imap"), Mappings::InsertModeMapping);
220  modeForMapCommand.insert(QStringLiteral("im"), Mappings::InsertModeMapping);
221  modeForMapCommand.insert(QStringLiteral("inoremap"), Mappings::InsertModeMapping);
222  modeForMapCommand.insert(QStringLiteral("ino"), Mappings::InsertModeMapping);
223  modeForMapCommand.insert(QStringLiteral("cmap"), Mappings::CommandModeMapping);
224  modeForMapCommand.insert(QStringLiteral("cm"), Mappings::CommandModeMapping);
225  modeForMapCommand.insert(QStringLiteral("cnoremap"), Mappings::CommandModeMapping);
226  modeForMapCommand.insert(QStringLiteral("cno"), Mappings::CommandModeMapping);
227 
228  modeForMapCommand.insert(QStringLiteral("nunmap"), Mappings::NormalModeMapping);
229  modeForMapCommand.insert(QStringLiteral("vunmap"), Mappings::VisualModeMapping);
230  modeForMapCommand.insert(QStringLiteral("iunmap"), Mappings::InsertModeMapping);
231  modeForMapCommand.insert(QStringLiteral("cunmap"), Mappings::CommandModeMapping);
232  }
233  return modeForMapCommand.value(mapCommand);
234 }
235 
236 bool Commands::isMapCommandRecursive(const QString &mapCommand)
237 {
238  static QMap<QString, bool> isMapCommandRecursive;
239  if (isMapCommandRecursive.isEmpty()) {
240  isMapCommandRecursive.insert(QStringLiteral("nmap"), true);
241  isMapCommandRecursive.insert(QStringLiteral("nm"), true);
242  isMapCommandRecursive.insert(QStringLiteral("vmap"), true);
243  isMapCommandRecursive.insert(QStringLiteral("vm"), true);
244  isMapCommandRecursive.insert(QStringLiteral("imap"), true);
245  isMapCommandRecursive.insert(QStringLiteral("im"), true);
246  isMapCommandRecursive.insert(QStringLiteral("cmap"), true);
247  isMapCommandRecursive.insert(QStringLiteral("cm"), true);
248  }
249  return isMapCommandRecursive.value(mapCommand);
250 }
251 
252 // END ViCommands
253 
254 // BEGIN SedReplace
255 SedReplace *SedReplace::m_instance = nullptr;
256 
257 bool SedReplace::interactiveSedReplace(KTextEditor::ViewPrivate *, QSharedPointer<InteractiveSedReplacer> interactiveSedReplace)
258 {
259  EmulatedCommandBar *emulatedCommandBar = m_viInputModeManager->inputAdapter()->viModeEmulatedCommandBar();
260  emulatedCommandBar->startInteractiveSearchAndReplace(interactiveSedReplace);
261  return true;
262 }
263 // END SedReplace
QString captured(int nth) const const
QRegularExpressionMatch match(const QString &subject, int offset, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions) const const
KCompletion * completionObject(KTextEditor::View *, const QString &) override
Reimplement from KTextEditor::Command.
Definition: cmds.cpp:180
const T & at(int i) const const
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QString & remove(int position, int n)
The Cursor represents a position in a Document.
Definition: cursor.h:71
constexpr bool isValid() const Q_DECL_NOEXCEPT
Validity check.
bool supportsRange(const QString &range) override
Find out if a given command can act on a range.
Definition: cmds.cpp:169
This KTextEditor::Command provides vi &#39;ex&#39; commands.
Definition: cmds.h:31
bool exec(class KTextEditor::View *view, const QString &cmd, QString &msg, const KTextEditor::Range &range=KTextEditor::Range(-1,-0,-1, 0)) override
execute command on given range
Definition: cmds.cpp:34
int toInt(bool *ok, int base) const const
bool isEmpty() const const
bool isEmpty() const const
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
virtual void setIgnoreCase(bool ignoreCase)
constexpr Cursor start() const Q_DECL_NOEXCEPT
Get the start position of this range.
An object representing a section of text, from one Cursor to another.
SkipEmptyParts
QString i18n(const char *text, const TYPE &arg...)
constexpr Cursor end() const Q_DECL_NOEXCEPT
Get the end position of this range.
Commands for the vi normal mode.
Definition: normalvimode.h:37
A KateViewBarWidget that attempts to emulate some of the features of Vim&#39;s own command bar...
Support vim/sed style search and replace.
Definition: cmds.h:87
constexpr int line() const Q_DECL_NOEXCEPT
Retrieve the line on which this cursor is situated.
Definition: cursor.h:185
QMap::iterator insert(const Key &key, const T &value)
bool isEmpty() const const
A KCompletion object that completes last ?unquoted? word in the string passed.
Definition: katecmd.h:56
A text widget with KXMLGUIClient that represents a Document.
Definition: view.h:143
virtual void setItems(const QStringList &itemList)
const T value(const Key &key, const T &defaultValue) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat Sep 19 2020 22:57:18 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.