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 "katetextline.h"
18 #include "kateview.h"
19
20 #include <KLocalizedString>
21
22 #include <QDateTime>
23 #include <QRegularExpression>
24
25 // BEGIN CoreCommands
26 KateCommands::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
getBoolArg(const QString & t,bool * val)31 static 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
help(KTextEditor::View *,const QString & cmd,QString & msg)48 bool KateCommands::CoreCommands::help(KTextEditor::View *, const QString &cmd, QString &msg)
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
exec(KTextEditor::View * view,const QString & _cmd,QString & errorMsg,const KTextEditor::Range & range)206 bool KateCommands::CoreCommands::exec(KTextEditor::View *view, const QString &_cmd, QString &errorMsg, const KTextEditor::Range &range)
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 QVector<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, 1);
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, -1);
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(' ')));
319 v->doc()->rememberUserDidSetIndentationMode();
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
supportsRange(const QString & range)438 bool KateCommands::CoreCommands::supportsRange(const QString &range)
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
completionObject(KTextEditor::View * view,const QString & cmd)450 KCompletion *KateCommands::CoreCommands::completionObject(KTextEditor::View *view, const QString &cmd)
451 {
452 Q_UNUSED(view)
453
454 if (cmd == QLatin1String("set-highlight")) {
455 QStringList l;
456 l.reserve(KateHlManager::self()->modeList().size());
457 for (const auto &hl : KateHlManager::self()->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
486 KateCommands::Character *KateCommands::Character::m_instance = nullptr;
487
help(class KTextEditor::View *,const QString & cmd,QString & msg)488 bool 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
exec(KTextEditor::View * view,const QString & _cmd,QString &,const KTextEditor::Range &)503 bool 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(cmd);
510 if (!match.hasMatch()) {
511 return false;
512 }
513
514 cmd = match.captured(1);
515
516 // identify the base
517
518 unsigned short int number = 0;
519 int base = 10;
520 if (cmd.startsWith(QLatin1Char('x'))) {
521 cmd.remove(0, 1);
522 base = 16;
523 } else if (cmd.startsWith(QLatin1String("0x"))) {
524 cmd.remove(0, 2);
525 base = 16;
526 } else if (cmd[0] == QLatin1Char('0')) {
527 base = 8;
528 }
529 bool ok;
530 number = cmd.toUShort(&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(view->cursorPosition(), QString::fromLatin1(buf));
540 } else {
541 // do the unicode thing
542 QChar c(number);
543
544 view->document()->insertText(view->cursorPosition(), QString(&c, 1));
545 }
546
547 return true;
548 }
549
550 // END Character
551
552 // BEGIN Date
553 KateCommands::Date *KateCommands::Date::m_instance = nullptr;
554
help(class KTextEditor::View *,const QString & cmd,QString & msg)555 bool 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
exec(KTextEditor::View * view,const QString & cmd,QString &,const KTextEditor::Range &)588 bool KateCommands::Date::exec(KTextEditor::View *view, const QString &cmd, QString &, const KTextEditor::Range &)
589 {
590 if (!cmd.startsWith(QLatin1String("date"))) {
591 return false;
592 }
593
594 if (QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length() - 5)).length() > 0) {
595 view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length() - 5)));
596 } else {
597 view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss")));
598 }
599
600 return true;
601 }
602
603 // END Date
604