KTextEditor

katecmds.cpp
1/*
2 SPDX-FileCopyrightText: 2003-2005 Anders Lund <anders@alweb.dk>
3 SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <cullmann@kde.org>
4 SPDX-FileCopyrightText: 2001 Charles Samuels <charles@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "katecmds.h"
10
11#include "kateautoindent.h"
12#include "katecmd.h"
13#include "katedocument.h"
14#include "katepartdebug.h"
15#include "katerenderer.h"
16#include "katesyntaxmanager.h"
17#include "kateview.h"
18
19#include <KLocalizedString>
20
21#include <QCollator>
22#include <QDateTime>
23#include <QRegularExpression>
24
25// BEGIN CoreCommands
26KateCommands::CoreCommands *KateCommands::CoreCommands::m_instance = nullptr;
27
28// this returns whether the string s could be converted to
29// a bool value, one of on|off|1|0|true|false. the argument val is
30// set to the extracted value in case of success
31static bool getBoolArg(const QString &t, bool *val)
32{
33 bool res(false);
34 QString s = t.toLower();
35 res = (s == QLatin1String("on") || s == QLatin1String("1") || s == QLatin1String("true"));
36 if (res) {
37 *val = true;
38 return true;
39 }
40 res = (s == QLatin1String("off") || s == QLatin1String("0") || s == QLatin1String("false"));
41 if (res) {
42 *val = false;
43 return true;
44 }
45 return false;
46}
47
49{
50 QString realcmd = cmd.trimmed();
51 if (realcmd == QLatin1String("indent")) {
52 msg = i18n(
53 "<p>indent</p>"
54 "<p>Indents the selected lines or the current line</p>");
55 return true;
56 } else if (realcmd == QLatin1String("unindent")) {
57 msg = i18n(
58 "<p>unindent</p>"
59 "<p>Unindents the selected lines or current line.</p>");
60 return true;
61 } else if (realcmd == QLatin1String("cleanindent")) {
62 msg = i18n(
63 "<p>cleanindent</p>"
64 "<p>Cleans up the indentation of the selected lines or current line according to the indentation settings in the document. </p>");
65 return true;
66 } else if (realcmd == QLatin1String("comment")) {
67 msg = i18n(
68 "<p>comment</p>"
69 "<p>Inserts comment markers to make the selection or selected lines or current line a comment according to the text format as defined by the "
70 "syntax highlight definition for the document.</p>");
71 return true;
72 } else if (realcmd == QLatin1String("uncomment")) {
73 msg = i18n(
74 "<p>uncomment</p>"
75 "<p>Removes comment markers from the selection or selected lines or current line according to the text format as defined by the syntax highlight "
76 "definition for the document.</p>");
77 return true;
78 } else if (realcmd == QLatin1String("goto")) {
79 msg = i18n(
80 "<p>goto <b>line number</b></p>"
81 "<p>This command navigates to the specified line number.</p>");
82 return true;
83 } else if (realcmd == QLatin1String("set-indent-pasted-text")) {
84 msg = i18n(
85 "<p>set-indent-pasted-text <b>enable</b></p>"
86 "<p>If enabled, indentation of text pasted from the clipboard is adjusted using the current indenter.</p>"
87 "<p>Possible true values: 1 on true<br/>"
88 "possible false values: 0 off false</p>");
89 return true;
90 } else if (realcmd == QLatin1String("kill-line")) {
91 msg = i18n("Deletes the current line.");
92 return true;
93 } else if (realcmd == QLatin1String("set-tab-width")) {
94 msg = i18n(
95 "<p>set-tab-width <b>width</b></p>"
96 "<p>Sets the tab width to the number <b>width</b></p>");
97 return true;
98 } else if (realcmd == QLatin1String("set-replace-tab")) {
99 msg = i18n(
100 "<p>set-replace-tab <b>enable</b></p>"
101 "<p>If enabled, tabs are replaced with spaces as you type.</p>"
102 "<p>Possible true values: 1 on true<br/>"
103 "possible false values: 0 off false</p>");
104 return true;
105 } else if (realcmd == QLatin1String("set-show-tabs")) {
106 msg = i18n(
107 "<p>set-show-tabs <b>enable</b></p>"
108 "<p>If enabled, TAB characters and trailing whitespace will be visualized by a small dot.</p>"
109 "<p>Possible true values: 1 on true<br/>"
110 "possible false values: 0 off false</p>");
111 return true;
112 } else if (realcmd == QLatin1String("set-remove-trailing-spaces")) {
113 msg = i18n(
114 "<p>set-remove-trailing-spaces <b>mode</b></p>"
115 "<p>Removes the trailing spaces in the document depending on the <b>mode</b>.</p>"
116 "<p>Possible values:"
117 "<ul>"
118 "<li><b>none</b>: never remove trailing spaces.</li>"
119 "<li><b>modified</b>: remove trailing spaces only of modified lines.</li>"
120 "<li><b>all</b>: remove trailing spaces in the entire document.</li>"
121 "</ul></p>");
122 return true;
123 } else if (realcmd == QLatin1String("set-indent-width")) {
124 msg = i18n(
125 "<p>set-indent-width <b>width</b></p>"
126 "<p>Sets the indentation width to the number <b>width</b>. Used only if you are indenting with spaces.</p>");
127 return true;
128 } else if (realcmd == QLatin1String("set-indent-mode")) {
129 msg = i18n(
130 "<p>set-indent-mode <b>mode</b></p>"
131 "<p>The mode parameter is a value as seen in the Tools - Indentation menu</p>");
132 return true;
133 } else if (realcmd == QLatin1String("set-auto-indent")) {
134 msg = i18n(
135 "<p>set-auto-indent <b>enable</b></p>"
136 "<p>Enable or disable autoindentation.</p>"
137 "<p>possible true values: 1 on true<br/>"
138 "possible false values: 0 off false</p>");
139 return true;
140 } else if (realcmd == QLatin1String("set-line-numbers")) {
141 msg = i18n(
142 "<p>set-line-numbers <b>enable</b></p>"
143 "<p>Sets the visibility of the line numbers pane.</p>"
144 "<p> possible true values: 1 on true<br/>"
145 "possible false values: 0 off false</p>");
146 return true;
147 } else if (realcmd == QLatin1String("set-folding-markers")) {
148 msg = i18n(
149 "<p>set-folding-markers <b>enable</b></p>"
150 "<p>Sets the visibility of the folding markers pane.</p>"
151 "<p> possible true values: 1 on true<br/>"
152 "possible false values: 0 off false</p>");
153 return true;
154 } else if (realcmd == QLatin1String("set-icon-border")) {
155 msg = i18n(
156 "<p>set-icon-border <b>enable</b></p>"
157 "<p>Sets the visibility of the icon border.</p>"
158 "<p> possible true values: 1 on true<br/>"
159 "possible false values: 0 off false</p>");
160 return true;
161 } else if (realcmd == QLatin1String("set-word-wrap")) {
162 msg = i18n(
163 "<p>set-word-wrap <b>enable</b></p>"
164 "<p>Enables dynamic word wrap according to <b>enable</b></p>"
165 "<p> possible true values: 1 on true<br/>"
166 "possible false values: 0 off false</p>");
167 return true;
168 } else if (realcmd == QLatin1String("set-word-wrap-column")) {
169 msg = i18n(
170 "<p>set-word-wrap-column <b>width</b></p>"
171 "<p>Sets the line width for hard wrapping to <b>width</b>. This is used if you are having your text wrapped automatically.</p>");
172 return true;
173 } else if (realcmd == QLatin1String("set-replace-tabs-save")) {
174 msg = i18n(
175 "<p>set-replace-tabs-save <b>enable</b></p>"
176 "<p>When enabled, tabs will be replaced with whitespace whenever the document is saved.</p>"
177 "<p> possible true values: 1 on true<br/>"
178 "possible false values: 0 off false</p>");
179 return true;
180 } else if (realcmd == QLatin1String("set-highlight")) {
181 msg = i18n(
182 "<p>set-highlight <b>highlight</b></p>"
183 "<p>Sets the syntax highlighting system for the document. The argument must be a valid highlight name, as seen in the Tools → Highlighting menu. "
184 "This command provides an autocompletion list for its argument.</p>");
185 return true;
186 } else if (realcmd == QLatin1String("set-mode")) {
187 msg = i18n(
188 "<p>set-mode <b>mode</b></p>"
189 "<p>Sets the mode as seen in Tools - Mode</p>");
190 return true;
191 } else if (realcmd == QLatin1String("set-show-indent")) {
192 msg = i18n(
193 "<p>set-show-indent <b>enable</b></p>"
194 "<p>If enabled, indentation will be visualized by a vertical dotted line.</p>"
195 "<p> possible true values: 1 on true<br/>"
196 "possible false values: 0 off false</p>");
197 return true;
198 } else if (realcmd == QLatin1String("print")) {
199 msg = i18n("<p>Open the Print dialog to print the current document.</p>");
200 return true;
201 } else {
202 return false;
203 }
204}
205
207{
208#define KCC_ERR(s) \
209 { \
210 errorMsg = s; \
211 return false; \
212 }
213 // cast it hardcore, we know that it is really a kateview :)
214 KTextEditor::ViewPrivate *v = static_cast<KTextEditor::ViewPrivate *>(view);
215
216 if (!v) {
217 KCC_ERR(i18n("Could not access view"));
218 }
219
220 // create a list of args
221 QStringList args(_cmd.split(QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts));
222 QString cmd(args.takeFirst());
223
224 // ALL commands that takes no arguments.
225 if (cmd == QLatin1String("indent")) {
226 if (range.isValid()) {
227 v->doc()->editStart();
228 for (int line = range.start().line(); line <= range.end().line(); line++) {
229 v->doc()->indent(KTextEditor::Range(line, 0, line, 0), 1);
230 }
231 v->doc()->editEnd();
232 } else {
233 v->indent();
234 }
235 return true;
236 } else if (cmd == QLatin1String("unindent")) {
237 if (range.isValid()) {
238 v->doc()->editStart();
239 for (int line = range.start().line(); line <= range.end().line(); line++) {
240 v->doc()->indent(KTextEditor::Range(line, 0, line, 0), -1);
241 }
242 v->doc()->editEnd();
243 } else {
244 v->unIndent();
245 }
246 return true;
247 } else if (cmd == QLatin1String("cleanindent")) {
248 if (range.isValid()) {
249 v->doc()->editStart();
250 for (int line = range.start().line(); line <= range.end().line(); line++) {
251 v->doc()->indent(KTextEditor::Range(line, 0, line, 0), 0);
252 }
253 v->doc()->editEnd();
254 } else {
255 v->cleanIndent();
256 }
257 return true;
258 } else if (cmd == QLatin1String("fold")) {
259 return (v->textFolding().newFoldingRange(range.isValid() ? range : v->selectionRange(), Kate::TextFolding::Persistent | Kate::TextFolding::Folded)
260 != -1);
261 } else if (cmd == QLatin1String("tfold")) {
262 return (v->textFolding().newFoldingRange(range.isValid() ? range : v->selectionRange(), Kate::TextFolding::Folded) != -1);
263 } else if (cmd == QLatin1String("unfold")) {
264 QList<QPair<qint64, Kate::TextFolding::FoldingRangeFlags>> startingRanges = v->textFolding().foldingRangesStartingOnLine(v->cursorPosition().line());
265 bool unfolded = false;
266 for (int i = 0; i < startingRanges.size(); ++i) {
267 if (startingRanges[i].second & Kate::TextFolding::Folded) {
268 unfolded = v->textFolding().unfoldRange(startingRanges[i].first) || unfolded;
269 }
270 }
271 return unfolded;
272 } else if (cmd == QLatin1String("comment")) {
273 if (range.isValid()) {
274 v->doc()->editStart();
275 for (int line = range.start().line(); line <= range.end().line(); line++) {
276 v->doc()->comment(v, line, 0, KTextEditor::DocumentPrivate::Comment);
277 }
278 v->doc()->editEnd();
279 } else {
280 v->comment();
281 }
282 return true;
283 } else if (cmd == QLatin1String("uncomment")) {
284 if (range.isValid()) {
285 v->doc()->editStart();
286 for (int line = range.start().line(); line <= range.end().line(); line++) {
287 v->doc()->comment(v, line, 0, KTextEditor::DocumentPrivate::UnComment);
288 }
289 v->doc()->editEnd();
290 } else {
291 v->uncomment();
292 }
293 return true;
294 } else if (cmd == QLatin1String("kill-line")) {
295 if (range.isValid()) {
296 v->doc()->editStart();
297 for (int line = range.start().line(); line <= range.end().line(); line++) {
298 v->doc()->removeLine(range.start().line());
299 }
300 v->doc()->editEnd();
301 } else {
302 v->killLine();
303 }
304 return true;
305 } else if (cmd == QLatin1String("print")) {
306 v->print();
307 return true;
308 }
309
310 // ALL commands that take a string argument
311 else if (cmd == QLatin1String("set-indent-mode") || cmd == QLatin1String("set-highlight") || cmd == QLatin1String("set-mode")) {
312 // need at least one item, otherwise args.first() crashes
313 if (args.isEmpty()) {
314 KCC_ERR(i18n("Missing argument. Usage: %1 <value>", cmd));
315 }
316
317 if (cmd == QLatin1String("set-indent-mode")) {
318 v->doc()->config()->setIndentationMode(args.join(QLatin1Char(' ')));
320 return true;
321 } else if (cmd == QLatin1String("set-highlight")) {
322 if (v->doc()->setHighlightingMode(args.join(QLatin1Char(' ')))) {
323 static_cast<KTextEditor::DocumentPrivate *>(v->doc())->setDontChangeHlOnSave();
324 return true;
325 }
326
327 KCC_ERR(i18n("No such highlighting '%1'", args.first()));
328 } else if (cmd == QLatin1String("set-mode")) {
329 if (v->doc()->setMode(args.first())) {
330 return true;
331 }
332
333 KCC_ERR(i18n("No such mode '%1'", args.first()));
334 }
335 }
336 // ALL commands that takes exactly one integer argument.
337 else if (cmd == QLatin1String("set-tab-width") || cmd == QLatin1String("set-indent-width") || cmd == QLatin1String("set-word-wrap-column")
338 || cmd == QLatin1String("goto")) {
339 // find a integer value > 0
340 if (args.isEmpty()) {
341 KCC_ERR(i18n("Missing argument. Usage: %1 <value>", cmd));
342 }
343 bool ok;
344 int val(args.first().toInt(&ok, 10)); // use base 10 even if the string starts with '0'
345 if (!ok)
346 KCC_ERR(i18n("Failed to convert argument '%1' to integer.", args.first()));
347
348 if (cmd == QLatin1String("set-tab-width")) {
349 if (val < 1) {
350 KCC_ERR(i18n("Width must be at least 1."));
351 }
352 v->doc()->config()->setTabWidth(val);
353 } else if (cmd == QLatin1String("set-indent-width")) {
354 if (val < 1) {
355 KCC_ERR(i18n("Width must be at least 1."));
356 }
357 v->doc()->config()->setIndentationWidth(val);
358 } else if (cmd == QLatin1String("set-word-wrap-column")) {
359 if (val < 2) {
360 KCC_ERR(i18n("Column must be at least 1."));
361 }
362 v->doc()->setWordWrapAt(val);
363 } else if (cmd == QLatin1String("goto")) {
364 if (args.first().at(0) == QLatin1Char('-') || args.first().at(0) == QLatin1Char('+')) {
365 // if the number starts with a minus or plus sign, add/subtract the number
366 val = v->cursorPosition().line() + val;
367 } else {
368 val--; // convert given line number to the internal representation of line numbers
369 }
370
371 // constrain cursor to the range [0, number of lines]
372 if (val < 0) {
373 val = 0;
374 } else if (val > v->doc()->lines() - 1) {
375 val = v->doc()->lines() - 1;
376 }
377
378 v->setCursorPosition(KTextEditor::Cursor(val, 0));
379 return true;
380 }
381 return true;
382 }
383
384 // ALL commands that takes 1 boolean argument.
385 else if (cmd == QLatin1String("set-icon-border") || cmd == QLatin1String("set-folding-markers") || cmd == QLatin1String("set-indent-pasted-text")
386 || cmd == QLatin1String("set-line-numbers") || cmd == QLatin1String("set-replace-tabs") || cmd == QLatin1String("set-show-tabs")
387 || cmd == QLatin1String("set-word-wrap") || cmd == QLatin1String("set-wrap-cursor") || cmd == QLatin1String("set-replace-tabs-save")
388 || cmd == QLatin1String("set-show-indent")) {
389 if (args.isEmpty()) {
390 KCC_ERR(i18n("Usage: %1 on|off|1|0|true|false", cmd));
391 }
392 bool enable = false;
393 KateDocumentConfig *const config = v->doc()->config();
394 if (getBoolArg(args.first(), &enable)) {
395 if (cmd == QLatin1String("set-icon-border")) {
396 v->setIconBorder(enable);
397 } else if (cmd == QLatin1String("set-folding-markers")) {
398 v->setFoldingMarkersOn(enable);
399 } else if (cmd == QLatin1String("set-line-numbers")) {
400 v->setLineNumbersOn(enable);
401 } else if (cmd == QLatin1String("set-show-indent")) {
402 v->renderer()->setShowIndentLines(enable);
403 } else if (cmd == QLatin1String("set-indent-pasted-text")) {
404 config->setIndentPastedText(enable);
405 } else if (cmd == QLatin1String("set-replace-tabs")) {
406 config->setReplaceTabsDyn(enable);
407 } else if (cmd == QLatin1String("set-show-tabs")) {
408 config->setShowTabs(enable);
409 } else if (cmd == QLatin1String("set-show-trailing-spaces")) {
410 config->setShowSpaces(enable ? KateDocumentConfig::Trailing : KateDocumentConfig::None);
411 } else if (cmd == QLatin1String("set-word-wrap")) {
412 v->doc()->setWordWrap(enable);
413 }
414
415 return true;
416 } else
417 KCC_ERR(i18n("Bad argument '%1'. Usage: %2 on|off|1|0|true|false", args.first(), cmd));
418 } else if (cmd == QLatin1String("set-remove-trailing-spaces")) {
419 // need at least one item, otherwise args.first() crashes
420 if (args.count() != 1) {
421 KCC_ERR(i18n("Usage: set-remove-trailing-spaces 0|-|none or 1|+|mod|modified or 2|*|all"));
422 }
423
424 QString tmp = args.first().toLower().trimmed();
425 if (tmp == QLatin1String("1") || tmp == QLatin1String("modified") || tmp == QLatin1String("mod") || tmp == QLatin1String("+")) {
426 v->doc()->config()->setRemoveSpaces(1);
427 } else if (tmp == QLatin1String("2") || tmp == QLatin1String("all") || tmp == QLatin1String("*")) {
428 v->doc()->config()->setRemoveSpaces(2);
429 } else {
430 v->doc()->config()->setRemoveSpaces(0);
431 }
432 }
433
434 // unlikely..
435 KCC_ERR(i18n("Unknown command '%1'", cmd));
436}
437
439{
440 static QStringList l;
441
442 if (l.isEmpty()) {
443 l << QStringLiteral("indent") << QStringLiteral("unindent") << QStringLiteral("cleanindent") << QStringLiteral("comment") << QStringLiteral("uncomment")
444 << QStringLiteral("kill-line") << QStringLiteral("fold") << QStringLiteral("tfold");
445 }
446
447 return l.contains(range);
448}
449
451{
452 Q_UNUSED(view)
453
454 if (cmd == QLatin1String("set-highlight")) {
455 QStringList l;
456 l.reserve(KateHlManager::self()->modeList().size());
457 const auto modeList = KateHlManager::self()->modeList();
458 for (const auto &hl : modeList) {
459 l << hl.name();
460 }
461
463 co->setItems(l);
464 co->setIgnoreCase(true);
465 return co;
466 } else if (cmd == QLatin1String("set-remove-trailing-spaces")) {
467 QStringList l;
468 l << QStringLiteral("none") << QStringLiteral("modified") << QStringLiteral("all");
469
471 co->setItems(l);
472 co->setIgnoreCase(true);
473 return co;
474 } else if (cmd == QLatin1String("set-indent-mode")) {
477 co->setItems(l);
478 co->setIgnoreCase(true);
479 return co;
480 }
481
482 return nullptr;
483}
484// END CoreCommands
485
486// BEGIN Character
487KateCommands::Character *KateCommands::Character::m_instance = nullptr;
488
490{
491 if (cmd.trimmed() == QLatin1String("char")) {
492 msg = i18n(
493 "<p> char <b>identifier</b> </p>"
494 "<p>This command allows you to insert literal characters by their numerical identifier, in decimal, octal or hexadecimal form.</p>"
495 "<p>Examples:<ul>"
496 "<li>char <b>234</b></li>"
497 "<li>char <b>0x1234</b></li>"
498 "</ul></p>");
499 return true;
500 }
501 return false;
502}
503
505{
506 QString cmd = _cmd;
507
508 // hex, octal, base 9+1
509 static const QRegularExpression num(QStringLiteral("^char *(0?x[0-9A-Fa-f]{1,4}|0[0-7]{1,6}|[0-9]{1,5})$"));
510 const QRegularExpressionMatch match = num.match(cmd);
511 if (!match.hasMatch()) {
512 return false;
513 }
514
515 cmd = match.captured(1);
516
517 // identify the base
518
519 unsigned short int number = 0;
520 int base = 10;
521 if (cmd.startsWith(QLatin1Char('x'))) {
522 cmd.remove(0, 1);
523 base = 16;
524 } else if (cmd.startsWith(QLatin1String("0x"))) {
525 cmd.remove(0, 2);
526 base = 16;
527 } else if (cmd[0] == QLatin1Char('0')) {
528 base = 8;
529 }
530 bool ok;
531 number = cmd.toUShort(&ok, base);
532 if (!ok || number == 0) {
533 return false;
534 }
535 if (number <= 255) {
536 char buf[2];
537 buf[0] = (char)number;
538 buf[1] = 0;
539
541 } else {
542 // do the unicode thing
543 QChar c(number);
544
545 view->document()->insertText(view->cursorPosition(), QString(&c, 1));
546 }
547
548 return true;
549}
550
551// END Character
552
553// BEGIN Date
554KateCommands::Date *KateCommands::Date::m_instance = nullptr;
555
557{
558 if (cmd.trimmed() == QLatin1String("date")) {
559 msg = i18n(
560 "<p>date or date <b>format</b></p>"
561 "<p>Inserts a date/time string as defined by the specified format, or the format yyyy-MM-dd hh:mm:ss if none is specified.</p>"
562 "<p>Possible format specifiers are:"
563 "<table>"
564 "<tr><td>d</td><td>The day as number without a leading zero (1-31).</td></tr>"
565 "<tr><td>dd</td><td>The day as number with a leading zero (01-31).</td></tr>"
566 "<tr><td>ddd</td><td>The abbreviated localized day name (e.g. 'Mon'..'Sun').</td></tr>"
567 "<tr><td>dddd</td><td>The long localized day name (e.g. 'Monday'..'Sunday').</td></tr>"
568 "<tr><td>M</td><td>The month as number without a leading zero (1-12).</td></tr>"
569 "<tr><td>MM</td><td>The month as number with a leading zero (01-12).</td></tr>"
570 "<tr><td>MMM</td><td>The abbreviated localized month name (e.g. 'Jan'..'Dec').</td></tr>"
571 "<tr><td>yy</td><td>The year as two digit number (00-99).</td></tr>"
572 "<tr><td>yyyy</td><td>The year as four digit number (1752-8000).</td></tr>"
573 "<tr><td>h</td><td>The hour without a leading zero (0..23 or 1..12 if AM/PM display).</td></tr>"
574 "<tr><td>hh</td><td>The hour with a leading zero (00..23 or 01..12 if AM/PM display).</td></tr>"
575 "<tr><td>m</td><td>The minute without a leading zero (0..59).</td></tr>"
576 "<tr><td>mm</td><td>The minute with a leading zero (00..59).</td></tr>"
577 "<tr><td>s</td><td>The second without a leading zero (0..59).</td></tr>"
578 "<tr><td>ss</td><td>The second with a leading zero (00..59).</td></tr>"
579 "<tr><td>z</td><td>The milliseconds without leading zeroes (0..999).</td></tr>"
580 "<tr><td>zzz</td><td>The milliseconds with leading zeroes (000..999).</td></tr>"
581 "<tr><td>AP</td><td>Use AM/PM display. AP will be replaced by either \"AM\" or \"PM\".</td></tr>"
582 "<tr><td>ap</td><td>Use am/pm display. ap will be replaced by either \"am\" or \"pm\".</td></tr>"
583 "</table></p>");
584 return true;
585 }
586 return false;
587}
588
590{
591 if (!cmd.startsWith(QLatin1String("date"))) {
592 return false;
593 }
594
595 if (QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length() - 5)).length() > 0) {
596 view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length() - 5)));
597 } else {
598 view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss")));
599 }
600
601 return true;
602}
603
604// END Date
605
606KateCommands::EditingCommands *KateCommands::EditingCommands::s_instance = nullptr;
607
608KateCommands::EditingCommands::EditingCommands()
609 : KTextEditor::Command({
610 QStringLiteral("uniq"),
611 QStringLiteral("sortuniq"),
612 QStringLiteral("natsort"),
613 QStringLiteral("sort"),
614 })
615{
616}
617
618QList<KateCommands::EditingCommands::EditingCommand> KateCommands::EditingCommands::allCommands()
619{
620 static QList<EditingCommand> cmds{
621 {.name = i18n("Remove Duplicate Lines"), .cmd = QStringLiteral("uniq")},
622 {.name = i18n("Remove Duplicates and Sort Text Alphabetically"), .cmd = QStringLiteral("sortuniq")},
623 {.name = i18n("Sort Text Naturally"), .cmd = QStringLiteral("natsort")},
624 {.name = i18n("Sort Selected Text Alphabetically"), .cmd = QStringLiteral("sort")},
625 };
626 return cmds;
627}
628
629bool KateCommands::EditingCommands::exec(KTextEditor::View *view, const QString &cmd, QString &, const KTextEditor::Range &)
630{
631 auto getDocAndRange = [view]() -> std::pair<KTextEditor::Document *, KTextEditor::Range> {
633 if (view->selection()) {
634 return {view->document(), view->selectionRange()};
635 }
636 return {view->document(), r};
637 };
638
639 auto apply = [](KTextEditor::Range range, KTextEditor::Document *doc, const QStringList &lines) {
640 if (range == doc->documentRange()) {
641 doc->setText(lines);
642 } else {
643 doc->replaceText(range, lines);
644 }
645 };
646
647 if (cmd == QStringLiteral("uniq")) {
648 const auto [doc, range] = getDocAndRange();
649 const QStringList lines = doc->textLines(range);
650 QSet<QString> seenLines;
651 QStringList uniqueLines;
652 for (const auto &line : lines) {
653 auto it = seenLines.find(line);
654 if (it == seenLines.end()) {
655 seenLines.insert(line);
656 uniqueLines.push_back(line);
657 }
658 }
659 apply(range, doc, uniqueLines);
660 return true;
661 } else if (cmd == QStringLiteral("sortuniq")) {
662 const auto [doc, range] = getDocAndRange();
663 QStringList lines = doc->textLines(range);
664 std::sort(lines.begin(), lines.end());
665 auto it = std::unique(lines.begin(), lines.end());
666 if (it != lines.end()) {
667 lines.erase(it, lines.end());
668 }
669 apply(range, doc, lines);
670 return true;
671 } else if (cmd == QStringLiteral("natsort")) {
672 const auto [doc, range] = getDocAndRange();
673 QStringList lines = doc->textLines(range);
674 QCollator col;
675 col.setNumericMode(true);
676 std::sort(lines.begin(), lines.end(), col);
677 apply(range, doc, lines);
678 return true;
679 } else if (cmd == QStringLiteral("sort")) {
680 const auto [doc, range] = getDocAndRange();
681 QStringList lines = doc->textLines(range);
682 std::sort(lines.begin(), lines.end());
683 apply(range, doc, lines);
684 return true;
685 }
686
687 return false;
688}
689bool KateCommands::EditingCommands::help(class KTextEditor::View *, const QString &cmd, QString &msg)
690{
691 if (cmd == QStringLiteral("sort")) {
692 msg = i18n(
693 "<p>sort</p>"
694 "<p>Sort the selected text or whole document if there is no selection</p>");
695 } else if (cmd == QStringLiteral("uniq")) {
696 msg = i18n(
697 "<p>uniq</p>"
698 "<p>Remove duplicate lines from the selected text or whole document if there is no selection.</p>");
699 } else if (cmd == QStringLiteral("sortuniq")) {
700 msg = i18n(
701 "<p>sortuniq</p>"
702 "<p>Sort the selected text or whole document and then remove all duplicate lines.</p>");
703 } else if (cmd == QStringLiteral("natsort")) {
704 msg = i18n(
705 "<p>natsort</p>"
706 "<p>Sort the selected text or whole document in natural order.<br>Here is an example to show the difference to the normal sort "
707 "method:<br>sort(a10, a1, a2) => a1, a10, a2<br>natsort(a10, a1, a2) => a1, a2, a10</p>");
708 } else {
709 return false;
710 }
711 return true;
712}
virtual void setIgnoreCase(bool ignoreCase)
virtual void setItems(const QStringList &itemList)
The Cursor represents a position in a Document.
Definition cursor.h:75
constexpr int line() const noexcept
Retrieve the line on which this cursor is situated.
Definition cursor.h:174
Backend of KTextEditor::Document related public KTextEditor interfaces.
bool setHighlightingMode(const QString &name) override
Set the current mode of the document by giving its name.
bool setMode(const QString &name) override
Set the current mode of the document by giving its name.
int lines() const override
Get the count of lines of the document.
bool editStart()
Enclose editor actions with editStart() and editEnd() to group them.
KateDocumentConfig * config()
Configuration.
void setDontChangeHlOnSave()
allow to mark, that we changed hl on user wish and should not reset it atm used for the user visible ...
bool editEnd()
End a editor operation.
void rememberUserDidSetIndentationMode()
set indentation mode by user this will remember that a user did set it and will avoid reset on save
A KParts derived class representing a text document.
Definition document.h:284
Range documentRange() const
A Range which encompasses the whole document.
Definition document.h:785
virtual bool insertText(KTextEditor::Cursor position, const QString &text, bool block=false)=0
Insert text at position.
An object representing a section of text, from one Cursor to another.
constexpr Cursor end() const noexcept
Get the end position of this range.
constexpr Cursor start() const noexcept
Get the start position of this range.
constexpr bool isValid() const noexcept
Validity check.
A text widget with KXMLGUIClient that represents a Document.
Definition view.h:244
virtual Document * document() const =0
Get the view's document, that means the view is a view of the returned document.
virtual Cursor cursorPosition() const =0
Get the view's current cursor position.
virtual bool selection() const =0
Query the view whether it has selected text, i.e.
virtual Range selectionRange() const =0
Get the range occupied by the current selection.
static QStringList listIdentifiers()
List all possible names, i.e.
A KCompletion object that completes last ?unquoted? word in the string passed.
Definition katecmd.h:58
insert a unicode or ascii character base 9+1: 1234 hex: 0x1234 or x1234 octal: 01231
Definition katecmds.h:118
bool help(class KTextEditor::View *, const QString &, QString &) override
This command does not have help.
Definition katecmds.cpp:489
bool exec(class KTextEditor::View *view, const QString &cmd, QString &errorMsg, const KTextEditor::Range &range=KTextEditor::Range(-1, -0, -1, 0)) override
execute command
Definition katecmds.cpp:504
This KTextEditor::Command provides access to a lot of the core functionality of kate part,...
Definition katecmds.h:31
bool help(class KTextEditor::View *, const QString &, QString &) override
This command does not have help.
Definition katecmds.cpp:48
bool exec(class KTextEditor::View *view, const QString &cmd, QString &errorMsg)
execute command
bool supportsRange(const QString &range) override
Find out if a given command can act on a range.
Definition katecmds.cpp:438
KCompletion * completionObject(KTextEditor::View *, const QString &) override
override from KTextEditor::Command
Definition katecmds.cpp:450
insert the current date/time in the given format
Definition katecmds.h:158
bool help(class KTextEditor::View *, const QString &, QString &) override
This command does not have help.
Definition katecmds.cpp:556
bool exec(class KTextEditor::View *view, const QString &cmd, QString &errorMsg, const KTextEditor::Range &range=KTextEditor::Range(-1, -0, -1, 0)) override
execute command
Definition katecmds.cpp:589
void setShowIndentLines(bool showLines)
Set whether a guide should be painted to help identifying indent lines.
bool unfoldRange(qint64 id, bool remove=false)
Unfold the given range.
QList< QPair< qint64, FoldingRangeFlags > > foldingRangesStartingOnLine(int line) const
Queries which folding ranges start at the given line and returns the id + flags for all of them.
qint64 newFoldingRange(KTextEditor::Range range, FoldingRangeFlags flags=FoldingRangeFlags())
Create a new folding range.
@ Folded
Range is folded away.
@ Persistent
Range is persistent, e.g.
QString i18n(const char *text, const TYPE &arg...)
KGuiItem apply()
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
void setNumericMode(bool on)
QDateTime currentDateTime()
QString toString(QStringView format, QCalendar cal) const const
iterator begin()
qsizetype count() const const
iterator end()
iterator erase(const_iterator begin, const_iterator end)
T & first()
bool isEmpty() const const
void push_back(parameter_type value)
void reserve(qsizetype size)
qsizetype size() const const
value_type takeFirst()
QRegularExpressionMatch match(QStringView subjectView, qsizetype offset, MatchType matchType, MatchOptions matchOptions) const const
iterator end()
iterator find(const T &value)
iterator insert(const T &value)
QString fromLatin1(QByteArrayView str)
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toLower() const const
ushort toUShort(bool *ok, int base) const const
QString trimmed() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QString join(QChar separator) const const
SkipEmptyParts
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 25 2024 11:56:26 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.