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 <QDateTime>
22#include <QRegularExpression>
23
24// BEGIN CoreCommands
25KateCommands::CoreCommands *KateCommands::CoreCommands::m_instance = nullptr;
26
27// this returns whether the string s could be converted to
28// a bool value, one of on|off|1|0|true|false. the argument val is
29// set to the extracted value in case of success
30static bool getBoolArg(const QString &t, bool *val)
31{
32 bool res(false);
33 QString s = t.toLower();
34 res = (s == QLatin1String("on") || s == QLatin1String("1") || s == QLatin1String("true"));
35 if (res) {
36 *val = true;
37 return true;
38 }
39 res = (s == QLatin1String("off") || s == QLatin1String("0") || s == QLatin1String("false"));
40 if (res) {
41 *val = false;
42 return true;
43 }
44 return false;
45}
46
47bool KateCommands::CoreCommands::help(KTextEditor::View *, const QString &cmd, QString &msg)
48{
49 QString realcmd = cmd.trimmed();
50 if (realcmd == QLatin1String("indent")) {
51 msg = i18n(
52 "<p>indent</p>"
53 "<p>Indents the selected lines or the current line</p>");
54 return true;
55 } else if (realcmd == QLatin1String("unindent")) {
56 msg = i18n(
57 "<p>unindent</p>"
58 "<p>Unindents the selected lines or current line.</p>");
59 return true;
60 } else if (realcmd == QLatin1String("cleanindent")) {
61 msg = i18n(
62 "<p>cleanindent</p>"
63 "<p>Cleans up the indentation of the selected lines or current line according to the indentation settings in the document. </p>");
64 return true;
65 } else if (realcmd == QLatin1String("comment")) {
66 msg = i18n(
67 "<p>comment</p>"
68 "<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 "
69 "syntax highlight definition for the document.</p>");
70 return true;
71 } else if (realcmd == QLatin1String("uncomment")) {
72 msg = i18n(
73 "<p>uncomment</p>"
74 "<p>Removes comment markers from the selection or selected lines or current line according to the text format as defined by the syntax highlight "
75 "definition for the document.</p>");
76 return true;
77 } else if (realcmd == QLatin1String("goto")) {
78 msg = i18n(
79 "<p>goto <b>line number</b></p>"
80 "<p>This command navigates to the specified line number.</p>");
81 return true;
82 } else if (realcmd == QLatin1String("set-indent-pasted-text")) {
83 msg = i18n(
84 "<p>set-indent-pasted-text <b>enable</b></p>"
85 "<p>If enabled, indentation of text pasted from the clipboard is adjusted using the current indenter.</p>"
86 "<p>Possible true values: 1 on true<br/>"
87 "possible false values: 0 off false</p>");
88 return true;
89 } else if (realcmd == QLatin1String("kill-line")) {
90 msg = i18n("Deletes the current line.");
91 return true;
92 } else if (realcmd == QLatin1String("set-tab-width")) {
93 msg = i18n(
94 "<p>set-tab-width <b>width</b></p>"
95 "<p>Sets the tab width to the number <b>width</b></p>");
96 return true;
97 } else if (realcmd == QLatin1String("set-replace-tab")) {
98 msg = i18n(
99 "<p>set-replace-tab <b>enable</b></p>"
100 "<p>If enabled, tabs are replaced with spaces as you type.</p>"
101 "<p>Possible true values: 1 on true<br/>"
102 "possible false values: 0 off false</p>");
103 return true;
104 } else if (realcmd == QLatin1String("set-show-tabs")) {
105 msg = i18n(
106 "<p>set-show-tabs <b>enable</b></p>"
107 "<p>If enabled, TAB characters and trailing whitespace will be visualized by a small dot.</p>"
108 "<p>Possible true values: 1 on true<br/>"
109 "possible false values: 0 off false</p>");
110 return true;
111 } else if (realcmd == QLatin1String("set-remove-trailing-spaces")) {
112 msg = i18n(
113 "<p>set-remove-trailing-spaces <b>mode</b></p>"
114 "<p>Removes the trailing spaces in the document depending on the <b>mode</b>.</p>"
115 "<p>Possible values:"
116 "<ul>"
117 "<li><b>none</b>: never remove trailing spaces.</li>"
118 "<li><b>modified</b>: remove trailing spaces only of modified lines.</li>"
119 "<li><b>all</b>: remove trailing spaces in the entire document.</li>"
120 "</ul></p>");
121 return true;
122 } else if (realcmd == QLatin1String("set-indent-width")) {
123 msg = i18n(
124 "<p>set-indent-width <b>width</b></p>"
125 "<p>Sets the indentation width to the number <b>width</b>. Used only if you are indenting with spaces.</p>");
126 return true;
127 } else if (realcmd == QLatin1String("set-indent-mode")) {
128 msg = i18n(
129 "<p>set-indent-mode <b>mode</b></p>"
130 "<p>The mode parameter is a value as seen in the Tools - Indentation menu</p>");
131 return true;
132 } else if (realcmd == QLatin1String("set-auto-indent")) {
133 msg = i18n(
134 "<p>set-auto-indent <b>enable</b></p>"
135 "<p>Enable or disable autoindentation.</p>"
136 "<p>possible true values: 1 on true<br/>"
137 "possible false values: 0 off false</p>");
138 return true;
139 } else if (realcmd == QLatin1String("set-line-numbers")) {
140 msg = i18n(
141 "<p>set-line-numbers <b>enable</b></p>"
142 "<p>Sets the visibility of the line numbers pane.</p>"
143 "<p> possible true values: 1 on true<br/>"
144 "possible false values: 0 off false</p>");
145 return true;
146 } else if (realcmd == QLatin1String("set-folding-markers")) {
147 msg = i18n(
148 "<p>set-folding-markers <b>enable</b></p>"
149 "<p>Sets the visibility of the folding markers pane.</p>"
150 "<p> possible true values: 1 on true<br/>"
151 "possible false values: 0 off false</p>");
152 return true;
153 } else if (realcmd == QLatin1String("set-icon-border")) {
154 msg = i18n(
155 "<p>set-icon-border <b>enable</b></p>"
156 "<p>Sets the visibility of the icon border.</p>"
157 "<p> possible true values: 1 on true<br/>"
158 "possible false values: 0 off false</p>");
159 return true;
160 } else if (realcmd == QLatin1String("set-word-wrap")) {
161 msg = i18n(
162 "<p>set-word-wrap <b>enable</b></p>"
163 "<p>Enables dynamic word wrap according to <b>enable</b></p>"
164 "<p> possible true values: 1 on true<br/>"
165 "possible false values: 0 off false</p>");
166 return true;
167 } else if (realcmd == QLatin1String("set-word-wrap-column")) {
168 msg = i18n(
169 "<p>set-word-wrap-column <b>width</b></p>"
170 "<p>Sets the line width for hard wrapping to <b>width</b>. This is used if you are having your text wrapped automatically.</p>");
171 return true;
172 } else if (realcmd == QLatin1String("set-replace-tabs-save")) {
173 msg = i18n(
174 "<p>set-replace-tabs-save <b>enable</b></p>"
175 "<p>When enabled, tabs will be replaced with whitespace whenever the document is saved.</p>"
176 "<p> possible true values: 1 on true<br/>"
177 "possible false values: 0 off false</p>");
178 return true;
179 } else if (realcmd == QLatin1String("set-highlight")) {
180 msg = i18n(
181 "<p>set-highlight <b>highlight</b></p>"
182 "<p>Sets the syntax highlighting system for the document. The argument must be a valid highlight name, as seen in the Tools → Highlighting menu. "
183 "This command provides an autocompletion list for its argument.</p>");
184 return true;
185 } else if (realcmd == QLatin1String("set-mode")) {
186 msg = i18n(
187 "<p>set-mode <b>mode</b></p>"
188 "<p>Sets the mode as seen in Tools - Mode</p>");
189 return true;
190 } else if (realcmd == QLatin1String("set-show-indent")) {
191 msg = i18n(
192 "<p>set-show-indent <b>enable</b></p>"
193 "<p>If enabled, indentation will be visualized by a vertical dotted line.</p>"
194 "<p> possible true values: 1 on true<br/>"
195 "possible false values: 0 off false</p>");
196 return true;
197 } else if (realcmd == QLatin1String("print")) {
198 msg = i18n("<p>Open the Print dialog to print the current document.</p>");
199 return true;
200 } else {
201 return false;
202 }
203}
204
205bool KateCommands::CoreCommands::exec(KTextEditor::View *view, const QString &_cmd, QString &errorMsg, const KTextEditor::Range &range)
206{
207#define KCC_ERR(s) \
208 { \
209 errorMsg = s; \
210 return false; \
211 }
212 // cast it hardcore, we know that it is really a kateview :)
213 KTextEditor::ViewPrivate *v = static_cast<KTextEditor::ViewPrivate *>(view);
214
215 if (!v) {
216 KCC_ERR(i18n("Could not access view"));
217 }
218
219 // create a list of args
220 QStringList args(_cmd.split(sep: QRegularExpression(QStringLiteral("\\s+")), behavior: Qt::SkipEmptyParts));
221 QString cmd(args.takeFirst());
222
223 // ALL commands that takes no arguments.
224 if (cmd == QLatin1String("indent")) {
225 if (range.isValid()) {
226 v->doc()->editStart();
227 for (int line = range.start().line(); line <= range.end().line(); line++) {
228 v->doc()->indent(range: KTextEditor::Range(line, 0, line, 0), change: 1);
229 }
230 v->doc()->editEnd();
231 } else {
232 v->indent();
233 }
234 return true;
235 } else if (cmd == QLatin1String("unindent")) {
236 if (range.isValid()) {
237 v->doc()->editStart();
238 for (int line = range.start().line(); line <= range.end().line(); line++) {
239 v->doc()->indent(range: KTextEditor::Range(line, 0, line, 0), change: -1);
240 }
241 v->doc()->editEnd();
242 } else {
243 v->unIndent();
244 }
245 return true;
246 } else if (cmd == QLatin1String("cleanindent")) {
247 if (range.isValid()) {
248 v->doc()->editStart();
249 for (int line = range.start().line(); line <= range.end().line(); line++) {
250 v->doc()->indent(range: KTextEditor::Range(line, 0, line, 0), change: 0);
251 }
252 v->doc()->editEnd();
253 } else {
254 v->cleanIndent();
255 }
256 return true;
257 } else if (cmd == QLatin1String("fold")) {
258 return (v->textFolding().newFoldingRange(range: range.isValid() ? range : v->selectionRange(), flags: Kate::TextFolding::Persistent | Kate::TextFolding::Folded)
259 != -1);
260 } else if (cmd == QLatin1String("tfold")) {
261 return (v->textFolding().newFoldingRange(range: range.isValid() ? range : v->selectionRange(), flags: Kate::TextFolding::Folded) != -1);
262 } else if (cmd == QLatin1String("unfold")) {
263 QList<QPair<qint64, Kate::TextFolding::FoldingRangeFlags>> startingRanges = v->textFolding().foldingRangesStartingOnLine(line: v->cursorPosition().line());
264 bool unfolded = false;
265 for (int i = 0; i < startingRanges.size(); ++i) {
266 if (startingRanges[i].second & Kate::TextFolding::Folded) {
267 unfolded = v->textFolding().unfoldRange(id: startingRanges[i].first) || unfolded;
268 }
269 }
270 return unfolded;
271 } else if (cmd == QLatin1String("comment")) {
272 if (range.isValid()) {
273 v->doc()->editStart();
274 for (int line = range.start().line(); line <= range.end().line(); line++) {
275 v->doc()->comment(view: v, line, column: 0, change: KTextEditor::DocumentPrivate::Comment);
276 }
277 v->doc()->editEnd();
278 } else {
279 v->comment();
280 }
281 return true;
282 } else if (cmd == QLatin1String("uncomment")) {
283 if (range.isValid()) {
284 v->doc()->editStart();
285 for (int line = range.start().line(); line <= range.end().line(); line++) {
286 v->doc()->comment(view: v, line, column: 0, change: KTextEditor::DocumentPrivate::UnComment);
287 }
288 v->doc()->editEnd();
289 } else {
290 v->uncomment();
291 }
292 return true;
293 } else if (cmd == QLatin1String("kill-line")) {
294 if (range.isValid()) {
295 v->doc()->editStart();
296 for (int line = range.start().line(); line <= range.end().line(); line++) {
297 v->doc()->removeLine(line: range.start().line());
298 }
299 v->doc()->editEnd();
300 } else {
301 v->killLine();
302 }
303 return true;
304 } else if (cmd == QLatin1String("print")) {
305 v->print();
306 return true;
307 }
308
309 // ALL commands that take a string argument
310 else if (cmd == QLatin1String("set-indent-mode") || cmd == QLatin1String("set-highlight") || cmd == QLatin1String("set-mode")) {
311 // need at least one item, otherwise args.first() crashes
312 if (args.isEmpty()) {
313 KCC_ERR(i18n("Missing argument. Usage: %1 <value>", cmd));
314 }
315
316 if (cmd == QLatin1String("set-indent-mode")) {
317 v->doc()->config()->setIndentationMode(args.join(sep: QLatin1Char(' ')));
318 v->doc()->rememberUserDidSetIndentationMode();
319 return true;
320 } else if (cmd == QLatin1String("set-highlight")) {
321 if (v->doc()->setHighlightingMode(args.join(sep: QLatin1Char(' ')))) {
322 static_cast<KTextEditor::DocumentPrivate *>(v->doc())->setDontChangeHlOnSave();
323 return true;
324 }
325
326 KCC_ERR(i18n("No such highlighting '%1'", args.first()));
327 } else if (cmd == QLatin1String("set-mode")) {
328 if (v->doc()->setMode(args.first())) {
329 return true;
330 }
331
332 KCC_ERR(i18n("No such mode '%1'", args.first()));
333 }
334 }
335 // ALL commands that takes exactly one integer argument.
336 else if (cmd == QLatin1String("set-tab-width") || cmd == QLatin1String("set-indent-width") || cmd == QLatin1String("set-word-wrap-column")
337 || cmd == QLatin1String("goto")) {
338 // find a integer value > 0
339 if (args.isEmpty()) {
340 KCC_ERR(i18n("Missing argument. Usage: %1 <value>", cmd));
341 }
342 bool ok;
343 int val(args.first().toInt(ok: &ok, base: 10)); // use base 10 even if the string starts with '0'
344 if (!ok)
345 KCC_ERR(i18n("Failed to convert argument '%1' to integer.", args.first()));
346
347 if (cmd == QLatin1String("set-tab-width")) {
348 if (val < 1) {
349 KCC_ERR(i18n("Width must be at least 1."));
350 }
351 v->doc()->config()->setTabWidth(val);
352 } else if (cmd == QLatin1String("set-indent-width")) {
353 if (val < 1) {
354 KCC_ERR(i18n("Width must be at least 1."));
355 }
356 v->doc()->config()->setIndentationWidth(val);
357 } else if (cmd == QLatin1String("set-word-wrap-column")) {
358 if (val < 2) {
359 KCC_ERR(i18n("Column must be at least 1."));
360 }
361 v->doc()->setWordWrapAt(val);
362 } else if (cmd == QLatin1String("goto")) {
363 if (args.first().at(i: 0) == QLatin1Char('-') || args.first().at(i: 0) == QLatin1Char('+')) {
364 // if the number starts with a minus or plus sign, add/subtract the number
365 val = v->cursorPosition().line() + val;
366 } else {
367 val--; // convert given line number to the internal representation of line numbers
368 }
369
370 // constrain cursor to the range [0, number of lines]
371 if (val < 0) {
372 val = 0;
373 } else if (val > v->doc()->lines() - 1) {
374 val = v->doc()->lines() - 1;
375 }
376
377 v->setCursorPosition(KTextEditor::Cursor(val, 0));
378 return true;
379 }
380 return true;
381 }
382
383 // ALL commands that takes 1 boolean argument.
384 else if (cmd == QLatin1String("set-icon-border") || cmd == QLatin1String("set-folding-markers") || cmd == QLatin1String("set-indent-pasted-text")
385 || cmd == QLatin1String("set-line-numbers") || cmd == QLatin1String("set-replace-tabs") || cmd == QLatin1String("set-show-tabs")
386 || cmd == QLatin1String("set-word-wrap") || cmd == QLatin1String("set-wrap-cursor") || cmd == QLatin1String("set-replace-tabs-save")
387 || cmd == QLatin1String("set-show-indent")) {
388 if (args.isEmpty()) {
389 KCC_ERR(i18n("Usage: %1 on|off|1|0|true|false", cmd));
390 }
391 bool enable = false;
392 KateDocumentConfig *const config = v->doc()->config();
393 if (getBoolArg(t: args.first(), val: &enable)) {
394 if (cmd == QLatin1String("set-icon-border")) {
395 v->setIconBorder(enable);
396 } else if (cmd == QLatin1String("set-folding-markers")) {
397 v->setFoldingMarkersOn(enable);
398 } else if (cmd == QLatin1String("set-line-numbers")) {
399 v->setLineNumbersOn(enable);
400 } else if (cmd == QLatin1String("set-show-indent")) {
401 v->renderer()->setShowIndentLines(enable);
402 } else if (cmd == QLatin1String("set-indent-pasted-text")) {
403 config->setIndentPastedText(enable);
404 } else if (cmd == QLatin1String("set-replace-tabs")) {
405 config->setReplaceTabsDyn(enable);
406 } else if (cmd == QLatin1String("set-show-tabs")) {
407 config->setShowTabs(enable);
408 } else if (cmd == QLatin1String("set-show-trailing-spaces")) {
409 config->setShowSpaces(enable ? KateDocumentConfig::Trailing : KateDocumentConfig::None);
410 } else if (cmd == QLatin1String("set-word-wrap")) {
411 v->doc()->setWordWrap(enable);
412 }
413
414 return true;
415 } else
416 KCC_ERR(i18n("Bad argument '%1'. Usage: %2 on|off|1|0|true|false", args.first(), cmd));
417 } else if (cmd == QLatin1String("set-remove-trailing-spaces")) {
418 // need at least one item, otherwise args.first() crashes
419 if (args.count() != 1) {
420 KCC_ERR(i18n("Usage: set-remove-trailing-spaces 0|-|none or 1|+|mod|modified or 2|*|all"));
421 }
422
423 QString tmp = args.first().toLower().trimmed();
424 if (tmp == QLatin1String("1") || tmp == QLatin1String("modified") || tmp == QLatin1String("mod") || tmp == QLatin1String("+")) {
425 v->doc()->config()->setRemoveSpaces(1);
426 } else if (tmp == QLatin1String("2") || tmp == QLatin1String("all") || tmp == QLatin1String("*")) {
427 v->doc()->config()->setRemoveSpaces(2);
428 } else {
429 v->doc()->config()->setRemoveSpaces(0);
430 }
431 }
432
433 // unlikely..
434 KCC_ERR(i18n("Unknown command '%1'", cmd));
435}
436
437bool KateCommands::CoreCommands::supportsRange(const QString &range)
438{
439 static QStringList l;
440
441 if (l.isEmpty()) {
442 l << QStringLiteral("indent") << QStringLiteral("unindent") << QStringLiteral("cleanindent") << QStringLiteral("comment") << QStringLiteral("uncomment")
443 << QStringLiteral("kill-line") << QStringLiteral("fold") << QStringLiteral("tfold");
444 }
445
446 return l.contains(str: range);
447}
448
449KCompletion *KateCommands::CoreCommands::completionObject(KTextEditor::View *view, const QString &cmd)
450{
451 Q_UNUSED(view)
452
453 if (cmd == QLatin1String("set-highlight")) {
454 QStringList l;
455 l.reserve(asize: KateHlManager::self()->modeList().size());
456 const auto modeList = KateHlManager::self()->modeList();
457 for (const auto &hl : modeList) {
458 l << hl.name();
459 }
460
461 KateCmdShellCompletion *co = new KateCmdShellCompletion();
462 co->setItems(l);
463 co->setIgnoreCase(true);
464 return co;
465 } else if (cmd == QLatin1String("set-remove-trailing-spaces")) {
466 QStringList l;
467 l << QStringLiteral("none") << QStringLiteral("modified") << QStringLiteral("all");
468
469 KateCmdShellCompletion *co = new KateCmdShellCompletion();
470 co->setItems(l);
471 co->setIgnoreCase(true);
472 return co;
473 } else if (cmd == QLatin1String("set-indent-mode")) {
474 QStringList l = KateAutoIndent::listIdentifiers();
475 KateCmdShellCompletion *co = new KateCmdShellCompletion();
476 co->setItems(l);
477 co->setIgnoreCase(true);
478 return co;
479 }
480
481 return nullptr;
482}
483// END CoreCommands
484
485// BEGIN Character
486KateCommands::Character *KateCommands::Character::m_instance = nullptr;
487
488bool KateCommands::Character::help(class KTextEditor::View *, const QString &cmd, QString &msg)
489{
490 if (cmd.trimmed() == QLatin1String("char")) {
491 msg = i18n(
492 "<p> char <b>identifier</b> </p>"
493 "<p>This command allows you to insert literal characters by their numerical identifier, in decimal, octal or hexadecimal form.</p>"
494 "<p>Examples:<ul>"
495 "<li>char <b>234</b></li>"
496 "<li>char <b>0x1234</b></li>"
497 "</ul></p>");
498 return true;
499 }
500 return false;
501}
502
503bool KateCommands::Character::exec(KTextEditor::View *view, const QString &_cmd, QString &, const KTextEditor::Range &)
504{
505 QString cmd = _cmd;
506
507 // hex, octal, base 9+1
508 static const QRegularExpression num(QStringLiteral("^char *(0?x[0-9A-Fa-f]{1,4}|0[0-7]{1,6}|[0-9]{1,5})$"));
509 const QRegularExpressionMatch match = num.match(subject: cmd);
510 if (!match.hasMatch()) {
511 return false;
512 }
513
514 cmd = match.captured(nth: 1);
515
516 // identify the base
517
518 unsigned short int number = 0;
519 int base = 10;
520 if (cmd.startsWith(c: QLatin1Char('x'))) {
521 cmd.remove(i: 0, len: 1);
522 base = 16;
523 } else if (cmd.startsWith(s: QLatin1String("0x"))) {
524 cmd.remove(i: 0, len: 2);
525 base = 16;
526 } else if (cmd[0] == QLatin1Char('0')) {
527 base = 8;
528 }
529 bool ok;
530 number = cmd.toUShort(ok: &ok, base);
531 if (!ok || number == 0) {
532 return false;
533 }
534 if (number <= 255) {
535 char buf[2];
536 buf[0] = (char)number;
537 buf[1] = 0;
538
539 view->document()->insertText(position: view->cursorPosition(), text: QString::fromLatin1(ba: buf));
540 } else {
541 // do the unicode thing
542 QChar c(number);
543
544 view->document()->insertText(position: view->cursorPosition(), text: QString(&c, 1));
545 }
546
547 return true;
548}
549
550// END Character
551
552// BEGIN Date
553KateCommands::Date *KateCommands::Date::m_instance = nullptr;
554
555bool KateCommands::Date::help(class KTextEditor::View *, const QString &cmd, QString &msg)
556{
557 if (cmd.trimmed() == QLatin1String("date")) {
558 msg = i18n(
559 "<p>date or date <b>format</b></p>"
560 "<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>"
561 "<p>Possible format specifiers are:"
562 "<table>"
563 "<tr><td>d</td><td>The day as number without a leading zero (1-31).</td></tr>"
564 "<tr><td>dd</td><td>The day as number with a leading zero (01-31).</td></tr>"
565 "<tr><td>ddd</td><td>The abbreviated localized day name (e.g. 'Mon'..'Sun').</td></tr>"
566 "<tr><td>dddd</td><td>The long localized day name (e.g. 'Monday'..'Sunday').</td></tr>"
567 "<tr><td>M</td><td>The month as number without a leading zero (1-12).</td></tr>"
568 "<tr><td>MM</td><td>The month as number with a leading zero (01-12).</td></tr>"
569 "<tr><td>MMM</td><td>The abbreviated localized month name (e.g. 'Jan'..'Dec').</td></tr>"
570 "<tr><td>yy</td><td>The year as two digit number (00-99).</td></tr>"
571 "<tr><td>yyyy</td><td>The year as four digit number (1752-8000).</td></tr>"
572 "<tr><td>h</td><td>The hour without a leading zero (0..23 or 1..12 if AM/PM display).</td></tr>"
573 "<tr><td>hh</td><td>The hour with a leading zero (00..23 or 01..12 if AM/PM display).</td></tr>"
574 "<tr><td>m</td><td>The minute without a leading zero (0..59).</td></tr>"
575 "<tr><td>mm</td><td>The minute with a leading zero (00..59).</td></tr>"
576 "<tr><td>s</td><td>The second without a leading zero (0..59).</td></tr>"
577 "<tr><td>ss</td><td>The second with a leading zero (00..59).</td></tr>"
578 "<tr><td>z</td><td>The milliseconds without leading zeroes (0..999).</td></tr>"
579 "<tr><td>zzz</td><td>The milliseconds with leading zeroes (000..999).</td></tr>"
580 "<tr><td>AP</td><td>Use AM/PM display. AP will be replaced by either \"AM\" or \"PM\".</td></tr>"
581 "<tr><td>ap</td><td>Use am/pm display. ap will be replaced by either \"am\" or \"pm\".</td></tr>"
582 "</table></p>");
583 return true;
584 }
585 return false;
586}
587
588bool KateCommands::Date::exec(KTextEditor::View *view, const QString &cmd, QString &, const KTextEditor::Range &)
589{
590 if (!cmd.startsWith(s: QLatin1String("date"))) {
591 return false;
592 }
593
594 if (QDateTime::currentDateTime().toString(format: cmd.mid(position: 5, n: cmd.length() - 5)).length() > 0) {
595 view->document()->insertText(position: view->cursorPosition(), text: QDateTime::currentDateTime().toString(format: cmd.mid(position: 5, n: cmd.length() - 5)));
596 } else {
597 view->document()->insertText(position: view->cursorPosition(), text: QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss")));
598 }
599
600 return true;
601}
602
603// END Date
604

source code of ktexteditor/src/utils/katecmds.cpp