File indexing completed on 2024-04-14 03:55:29

0001 /*
0002     SPDX-FileCopyrightText: 2003-2005 Anders Lund <anders@alweb.dk>
0003     SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <cullmann@kde.org>
0004     SPDX-FileCopyrightText: 2001 Charles Samuels <charles@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "katecmds.h"
0010 
0011 #include "kateautoindent.h"
0012 #include "katecmd.h"
0013 #include "katedocument.h"
0014 #include "katepartdebug.h"
0015 #include "katerenderer.h"
0016 #include "katesyntaxmanager.h"
0017 #include "kateview.h"
0018 
0019 #include <KLocalizedString>
0020 
0021 #include <QDateTime>
0022 #include <QRegularExpression>
0023 
0024 // BEGIN CoreCommands
0025 KateCommands::CoreCommands *KateCommands::CoreCommands::m_instance = nullptr;
0026 
0027 // this returns whether the string s could be converted to
0028 // a bool value, one of on|off|1|0|true|false. the argument val is
0029 // set to the extracted value in case of success
0030 static bool getBoolArg(const QString &t, bool *val)
0031 {
0032     bool res(false);
0033     QString s = t.toLower();
0034     res = (s == QLatin1String("on") || s == QLatin1String("1") || s == QLatin1String("true"));
0035     if (res) {
0036         *val = true;
0037         return true;
0038     }
0039     res = (s == QLatin1String("off") || s == QLatin1String("0") || s == QLatin1String("false"));
0040     if (res) {
0041         *val = false;
0042         return true;
0043     }
0044     return false;
0045 }
0046 
0047 bool KateCommands::CoreCommands::help(KTextEditor::View *, const QString &cmd, QString &msg)
0048 {
0049     QString realcmd = cmd.trimmed();
0050     if (realcmd == QLatin1String("indent")) {
0051         msg = i18n(
0052             "<p>indent</p>"
0053             "<p>Indents the selected lines or the current line</p>");
0054         return true;
0055     } else if (realcmd == QLatin1String("unindent")) {
0056         msg = i18n(
0057             "<p>unindent</p>"
0058             "<p>Unindents the selected lines or current line.</p>");
0059         return true;
0060     } else if (realcmd == QLatin1String("cleanindent")) {
0061         msg = i18n(
0062             "<p>cleanindent</p>"
0063             "<p>Cleans up the indentation of the selected lines or current line according to the indentation settings in the document. </p>");
0064         return true;
0065     } else if (realcmd == QLatin1String("comment")) {
0066         msg = i18n(
0067             "<p>comment</p>"
0068             "<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 "
0069             "syntax highlight definition for the document.</p>");
0070         return true;
0071     } else if (realcmd == QLatin1String("uncomment")) {
0072         msg = i18n(
0073             "<p>uncomment</p>"
0074             "<p>Removes comment markers from the selection or selected lines or current line according to the text format as defined by the syntax highlight "
0075             "definition for the document.</p>");
0076         return true;
0077     } else if (realcmd == QLatin1String("goto")) {
0078         msg = i18n(
0079             "<p>goto <b>line number</b></p>"
0080             "<p>This command navigates to the specified line number.</p>");
0081         return true;
0082     } else if (realcmd == QLatin1String("set-indent-pasted-text")) {
0083         msg = i18n(
0084             "<p>set-indent-pasted-text <b>enable</b></p>"
0085             "<p>If enabled, indentation of text pasted from the clipboard is adjusted using the current indenter.</p>"
0086             "<p>Possible true values: 1 on true<br/>"
0087             "possible false values: 0 off false</p>");
0088         return true;
0089     } else if (realcmd == QLatin1String("kill-line")) {
0090         msg = i18n("Deletes the current line.");
0091         return true;
0092     } else if (realcmd == QLatin1String("set-tab-width")) {
0093         msg = i18n(
0094             "<p>set-tab-width <b>width</b></p>"
0095             "<p>Sets the tab width to the number <b>width</b></p>");
0096         return true;
0097     } else if (realcmd == QLatin1String("set-replace-tab")) {
0098         msg = i18n(
0099             "<p>set-replace-tab <b>enable</b></p>"
0100             "<p>If enabled, tabs are replaced with spaces as you type.</p>"
0101             "<p>Possible true values: 1 on true<br/>"
0102             "possible false values: 0 off false</p>");
0103         return true;
0104     } else if (realcmd == QLatin1String("set-show-tabs")) {
0105         msg = i18n(
0106             "<p>set-show-tabs <b>enable</b></p>"
0107             "<p>If enabled, TAB characters and trailing whitespace will be visualized by a small dot.</p>"
0108             "<p>Possible true values: 1 on true<br/>"
0109             "possible false values: 0 off false</p>");
0110         return true;
0111     } else if (realcmd == QLatin1String("set-remove-trailing-spaces")) {
0112         msg = i18n(
0113             "<p>set-remove-trailing-spaces <b>mode</b></p>"
0114             "<p>Removes the trailing spaces in the document depending on the <b>mode</b>.</p>"
0115             "<p>Possible values:"
0116             "<ul>"
0117             "<li><b>none</b>: never remove trailing spaces.</li>"
0118             "<li><b>modified</b>: remove trailing spaces only of modified lines.</li>"
0119             "<li><b>all</b>: remove trailing spaces in the entire document.</li>"
0120             "</ul></p>");
0121         return true;
0122     } else if (realcmd == QLatin1String("set-indent-width")) {
0123         msg = i18n(
0124             "<p>set-indent-width <b>width</b></p>"
0125             "<p>Sets the indentation width to the number <b>width</b>. Used only if you are indenting with spaces.</p>");
0126         return true;
0127     } else if (realcmd == QLatin1String("set-indent-mode")) {
0128         msg = i18n(
0129             "<p>set-indent-mode <b>mode</b></p>"
0130             "<p>The mode parameter is a value as seen in the Tools - Indentation menu</p>");
0131         return true;
0132     } else if (realcmd == QLatin1String("set-auto-indent")) {
0133         msg = i18n(
0134             "<p>set-auto-indent <b>enable</b></p>"
0135             "<p>Enable or disable autoindentation.</p>"
0136             "<p>possible true values: 1 on true<br/>"
0137             "possible false values: 0 off false</p>");
0138         return true;
0139     } else if (realcmd == QLatin1String("set-line-numbers")) {
0140         msg = i18n(
0141             "<p>set-line-numbers <b>enable</b></p>"
0142             "<p>Sets the visibility of the line numbers pane.</p>"
0143             "<p> possible true values: 1 on true<br/>"
0144             "possible false values: 0 off false</p>");
0145         return true;
0146     } else if (realcmd == QLatin1String("set-folding-markers")) {
0147         msg = i18n(
0148             "<p>set-folding-markers <b>enable</b></p>"
0149             "<p>Sets the visibility of the folding markers pane.</p>"
0150             "<p> possible true values: 1 on true<br/>"
0151             "possible false values: 0 off false</p>");
0152         return true;
0153     } else if (realcmd == QLatin1String("set-icon-border")) {
0154         msg = i18n(
0155             "<p>set-icon-border <b>enable</b></p>"
0156             "<p>Sets the visibility of the icon border.</p>"
0157             "<p> possible true values: 1 on true<br/>"
0158             "possible false values: 0 off false</p>");
0159         return true;
0160     } else if (realcmd == QLatin1String("set-word-wrap")) {
0161         msg = i18n(
0162             "<p>set-word-wrap <b>enable</b></p>"
0163             "<p>Enables dynamic word wrap according to <b>enable</b></p>"
0164             "<p> possible true values: 1 on true<br/>"
0165             "possible false values: 0 off false</p>");
0166         return true;
0167     } else if (realcmd == QLatin1String("set-word-wrap-column")) {
0168         msg = i18n(
0169             "<p>set-word-wrap-column <b>width</b></p>"
0170             "<p>Sets the line width for hard wrapping to <b>width</b>. This is used if you are having your text wrapped automatically.</p>");
0171         return true;
0172     } else if (realcmd == QLatin1String("set-replace-tabs-save")) {
0173         msg = i18n(
0174             "<p>set-replace-tabs-save <b>enable</b></p>"
0175             "<p>When enabled, tabs will be replaced with whitespace whenever the document is saved.</p>"
0176             "<p> possible true values: 1 on true<br/>"
0177             "possible false values: 0 off false</p>");
0178         return true;
0179     } else if (realcmd == QLatin1String("set-highlight")) {
0180         msg = i18n(
0181             "<p>set-highlight <b>highlight</b></p>"
0182             "<p>Sets the syntax highlighting system for the document. The argument must be a valid highlight name, as seen in the Tools → Highlighting menu. "
0183             "This command provides an autocompletion list for its argument.</p>");
0184         return true;
0185     } else if (realcmd == QLatin1String("set-mode")) {
0186         msg = i18n(
0187             "<p>set-mode <b>mode</b></p>"
0188             "<p>Sets the mode as seen in Tools - Mode</p>");
0189         return true;
0190     } else if (realcmd == QLatin1String("set-show-indent")) {
0191         msg = i18n(
0192             "<p>set-show-indent <b>enable</b></p>"
0193             "<p>If enabled, indentation will be visualized by a vertical dotted line.</p>"
0194             "<p> possible true values: 1 on true<br/>"
0195             "possible false values: 0 off false</p>");
0196         return true;
0197     } else if (realcmd == QLatin1String("print")) {
0198         msg = i18n("<p>Open the Print dialog to print the current document.</p>");
0199         return true;
0200     } else {
0201         return false;
0202     }
0203 }
0204 
0205 bool KateCommands::CoreCommands::exec(KTextEditor::View *view, const QString &_cmd, QString &errorMsg, const KTextEditor::Range &range)
0206 {
0207 #define KCC_ERR(s)                                                                                                                                             \
0208     {                                                                                                                                                          \
0209         errorMsg = s;                                                                                                                                          \
0210         return false;                                                                                                                                          \
0211     }
0212     // cast it hardcore, we know that it is really a kateview :)
0213     KTextEditor::ViewPrivate *v = static_cast<KTextEditor::ViewPrivate *>(view);
0214 
0215     if (!v) {
0216         KCC_ERR(i18n("Could not access view"));
0217     }
0218 
0219     // create a list of args
0220     QStringList args(_cmd.split(QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts));
0221     QString cmd(args.takeFirst());
0222 
0223     // ALL commands that takes no arguments.
0224     if (cmd == QLatin1String("indent")) {
0225         if (range.isValid()) {
0226             v->doc()->editStart();
0227             for (int line = range.start().line(); line <= range.end().line(); line++) {
0228                 v->doc()->indent(KTextEditor::Range(line, 0, line, 0), 1);
0229             }
0230             v->doc()->editEnd();
0231         } else {
0232             v->indent();
0233         }
0234         return true;
0235     } else if (cmd == QLatin1String("unindent")) {
0236         if (range.isValid()) {
0237             v->doc()->editStart();
0238             for (int line = range.start().line(); line <= range.end().line(); line++) {
0239                 v->doc()->indent(KTextEditor::Range(line, 0, line, 0), -1);
0240             }
0241             v->doc()->editEnd();
0242         } else {
0243             v->unIndent();
0244         }
0245         return true;
0246     } else if (cmd == QLatin1String("cleanindent")) {
0247         if (range.isValid()) {
0248             v->doc()->editStart();
0249             for (int line = range.start().line(); line <= range.end().line(); line++) {
0250                 v->doc()->indent(KTextEditor::Range(line, 0, line, 0), 0);
0251             }
0252             v->doc()->editEnd();
0253         } else {
0254             v->cleanIndent();
0255         }
0256         return true;
0257     } else if (cmd == QLatin1String("fold")) {
0258         return (v->textFolding().newFoldingRange(range.isValid() ? range : v->selectionRange(), Kate::TextFolding::Persistent | Kate::TextFolding::Folded)
0259                 != -1);
0260     } else if (cmd == QLatin1String("tfold")) {
0261         return (v->textFolding().newFoldingRange(range.isValid() ? range : v->selectionRange(), Kate::TextFolding::Folded) != -1);
0262     } else if (cmd == QLatin1String("unfold")) {
0263         QList<QPair<qint64, Kate::TextFolding::FoldingRangeFlags>> startingRanges = v->textFolding().foldingRangesStartingOnLine(v->cursorPosition().line());
0264         bool unfolded = false;
0265         for (int i = 0; i < startingRanges.size(); ++i) {
0266             if (startingRanges[i].second & Kate::TextFolding::Folded) {
0267                 unfolded = v->textFolding().unfoldRange(startingRanges[i].first) || unfolded;
0268             }
0269         }
0270         return unfolded;
0271     } else if (cmd == QLatin1String("comment")) {
0272         if (range.isValid()) {
0273             v->doc()->editStart();
0274             for (int line = range.start().line(); line <= range.end().line(); line++) {
0275                 v->doc()->comment(v, line, 0, KTextEditor::DocumentPrivate::Comment);
0276             }
0277             v->doc()->editEnd();
0278         } else {
0279             v->comment();
0280         }
0281         return true;
0282     } else if (cmd == QLatin1String("uncomment")) {
0283         if (range.isValid()) {
0284             v->doc()->editStart();
0285             for (int line = range.start().line(); line <= range.end().line(); line++) {
0286                 v->doc()->comment(v, line, 0, KTextEditor::DocumentPrivate::UnComment);
0287             }
0288             v->doc()->editEnd();
0289         } else {
0290             v->uncomment();
0291         }
0292         return true;
0293     } else if (cmd == QLatin1String("kill-line")) {
0294         if (range.isValid()) {
0295             v->doc()->editStart();
0296             for (int line = range.start().line(); line <= range.end().line(); line++) {
0297                 v->doc()->removeLine(range.start().line());
0298             }
0299             v->doc()->editEnd();
0300         } else {
0301             v->killLine();
0302         }
0303         return true;
0304     } else if (cmd == QLatin1String("print")) {
0305         v->print();
0306         return true;
0307     }
0308 
0309     // ALL commands that take a string argument
0310     else if (cmd == QLatin1String("set-indent-mode") || cmd == QLatin1String("set-highlight") || cmd == QLatin1String("set-mode")) {
0311         // need at least one item, otherwise args.first() crashes
0312         if (args.isEmpty()) {
0313             KCC_ERR(i18n("Missing argument. Usage: %1 <value>", cmd));
0314         }
0315 
0316         if (cmd == QLatin1String("set-indent-mode")) {
0317             v->doc()->config()->setIndentationMode(args.join(QLatin1Char(' ')));
0318             v->doc()->rememberUserDidSetIndentationMode();
0319             return true;
0320         } else if (cmd == QLatin1String("set-highlight")) {
0321             if (v->doc()->setHighlightingMode(args.join(QLatin1Char(' ')))) {
0322                 static_cast<KTextEditor::DocumentPrivate *>(v->doc())->setDontChangeHlOnSave();
0323                 return true;
0324             }
0325 
0326             KCC_ERR(i18n("No such highlighting '%1'", args.first()));
0327         } else if (cmd == QLatin1String("set-mode")) {
0328             if (v->doc()->setMode(args.first())) {
0329                 return true;
0330             }
0331 
0332             KCC_ERR(i18n("No such mode '%1'", args.first()));
0333         }
0334     }
0335     // ALL commands that takes exactly one integer argument.
0336     else if (cmd == QLatin1String("set-tab-width") || cmd == QLatin1String("set-indent-width") || cmd == QLatin1String("set-word-wrap-column")
0337              || cmd == QLatin1String("goto")) {
0338         // find a integer value > 0
0339         if (args.isEmpty()) {
0340             KCC_ERR(i18n("Missing argument. Usage: %1 <value>", cmd));
0341         }
0342         bool ok;
0343         int val(args.first().toInt(&ok, 10)); // use base 10 even if the string starts with '0'
0344         if (!ok)
0345             KCC_ERR(i18n("Failed to convert argument '%1' to integer.", args.first()));
0346 
0347         if (cmd == QLatin1String("set-tab-width")) {
0348             if (val < 1) {
0349                 KCC_ERR(i18n("Width must be at least 1."));
0350             }
0351             v->doc()->config()->setTabWidth(val);
0352         } else if (cmd == QLatin1String("set-indent-width")) {
0353             if (val < 1) {
0354                 KCC_ERR(i18n("Width must be at least 1."));
0355             }
0356             v->doc()->config()->setIndentationWidth(val);
0357         } else if (cmd == QLatin1String("set-word-wrap-column")) {
0358             if (val < 2) {
0359                 KCC_ERR(i18n("Column must be at least 1."));
0360             }
0361             v->doc()->setWordWrapAt(val);
0362         } else if (cmd == QLatin1String("goto")) {
0363             if (args.first().at(0) == QLatin1Char('-') || args.first().at(0) == QLatin1Char('+')) {
0364                 // if the number starts with a minus or plus sign, add/subtract the number
0365                 val = v->cursorPosition().line() + val;
0366             } else {
0367                 val--; // convert given line number to the internal representation of line numbers
0368             }
0369 
0370             // constrain cursor to the range [0, number of lines]
0371             if (val < 0) {
0372                 val = 0;
0373             } else if (val > v->doc()->lines() - 1) {
0374                 val = v->doc()->lines() - 1;
0375             }
0376 
0377             v->setCursorPosition(KTextEditor::Cursor(val, 0));
0378             return true;
0379         }
0380         return true;
0381     }
0382 
0383     // ALL commands that takes 1 boolean argument.
0384     else if (cmd == QLatin1String("set-icon-border") || cmd == QLatin1String("set-folding-markers") || cmd == QLatin1String("set-indent-pasted-text")
0385              || cmd == QLatin1String("set-line-numbers") || cmd == QLatin1String("set-replace-tabs") || cmd == QLatin1String("set-show-tabs")
0386              || cmd == QLatin1String("set-word-wrap") || cmd == QLatin1String("set-wrap-cursor") || cmd == QLatin1String("set-replace-tabs-save")
0387              || cmd == QLatin1String("set-show-indent")) {
0388         if (args.isEmpty()) {
0389             KCC_ERR(i18n("Usage: %1 on|off|1|0|true|false", cmd));
0390         }
0391         bool enable = false;
0392         KateDocumentConfig *const config = v->doc()->config();
0393         if (getBoolArg(args.first(), &enable)) {
0394             if (cmd == QLatin1String("set-icon-border")) {
0395                 v->setIconBorder(enable);
0396             } else if (cmd == QLatin1String("set-folding-markers")) {
0397                 v->setFoldingMarkersOn(enable);
0398             } else if (cmd == QLatin1String("set-line-numbers")) {
0399                 v->setLineNumbersOn(enable);
0400             } else if (cmd == QLatin1String("set-show-indent")) {
0401                 v->renderer()->setShowIndentLines(enable);
0402             } else if (cmd == QLatin1String("set-indent-pasted-text")) {
0403                 config->setIndentPastedText(enable);
0404             } else if (cmd == QLatin1String("set-replace-tabs")) {
0405                 config->setReplaceTabsDyn(enable);
0406             } else if (cmd == QLatin1String("set-show-tabs")) {
0407                 config->setShowTabs(enable);
0408             } else if (cmd == QLatin1String("set-show-trailing-spaces")) {
0409                 config->setShowSpaces(enable ? KateDocumentConfig::Trailing : KateDocumentConfig::None);
0410             } else if (cmd == QLatin1String("set-word-wrap")) {
0411                 v->doc()->setWordWrap(enable);
0412             }
0413 
0414             return true;
0415         } else
0416             KCC_ERR(i18n("Bad argument '%1'. Usage: %2 on|off|1|0|true|false", args.first(), cmd));
0417     } else if (cmd == QLatin1String("set-remove-trailing-spaces")) {
0418         // need at least one item, otherwise args.first() crashes
0419         if (args.count() != 1) {
0420             KCC_ERR(i18n("Usage: set-remove-trailing-spaces 0|-|none or 1|+|mod|modified or 2|*|all"));
0421         }
0422 
0423         QString tmp = args.first().toLower().trimmed();
0424         if (tmp == QLatin1String("1") || tmp == QLatin1String("modified") || tmp == QLatin1String("mod") || tmp == QLatin1String("+")) {
0425             v->doc()->config()->setRemoveSpaces(1);
0426         } else if (tmp == QLatin1String("2") || tmp == QLatin1String("all") || tmp == QLatin1String("*")) {
0427             v->doc()->config()->setRemoveSpaces(2);
0428         } else {
0429             v->doc()->config()->setRemoveSpaces(0);
0430         }
0431     }
0432 
0433     // unlikely..
0434     KCC_ERR(i18n("Unknown command '%1'", cmd));
0435 }
0436 
0437 bool KateCommands::CoreCommands::supportsRange(const QString &range)
0438 {
0439     static QStringList l;
0440 
0441     if (l.isEmpty()) {
0442         l << QStringLiteral("indent") << QStringLiteral("unindent") << QStringLiteral("cleanindent") << QStringLiteral("comment") << QStringLiteral("uncomment")
0443           << QStringLiteral("kill-line") << QStringLiteral("fold") << QStringLiteral("tfold");
0444     }
0445 
0446     return l.contains(range);
0447 }
0448 
0449 KCompletion *KateCommands::CoreCommands::completionObject(KTextEditor::View *view, const QString &cmd)
0450 {
0451     Q_UNUSED(view)
0452 
0453     if (cmd == QLatin1String("set-highlight")) {
0454         QStringList l;
0455         l.reserve(KateHlManager::self()->modeList().size());
0456         const auto modeList = KateHlManager::self()->modeList();
0457         for (const auto &hl : modeList) {
0458             l << hl.name();
0459         }
0460 
0461         KateCmdShellCompletion *co = new KateCmdShellCompletion();
0462         co->setItems(l);
0463         co->setIgnoreCase(true);
0464         return co;
0465     } else if (cmd == QLatin1String("set-remove-trailing-spaces")) {
0466         QStringList l;
0467         l << QStringLiteral("none") << QStringLiteral("modified") << QStringLiteral("all");
0468 
0469         KateCmdShellCompletion *co = new KateCmdShellCompletion();
0470         co->setItems(l);
0471         co->setIgnoreCase(true);
0472         return co;
0473     } else if (cmd == QLatin1String("set-indent-mode")) {
0474         QStringList l = KateAutoIndent::listIdentifiers();
0475         KateCmdShellCompletion *co = new KateCmdShellCompletion();
0476         co->setItems(l);
0477         co->setIgnoreCase(true);
0478         return co;
0479     }
0480 
0481     return nullptr;
0482 }
0483 // END CoreCommands
0484 
0485 // BEGIN Character
0486 KateCommands::Character *KateCommands::Character::m_instance = nullptr;
0487 
0488 bool KateCommands::Character::help(class KTextEditor::View *, const QString &cmd, QString &msg)
0489 {
0490     if (cmd.trimmed() == QLatin1String("char")) {
0491         msg = i18n(
0492             "<p> char <b>identifier</b> </p>"
0493             "<p>This command allows you to insert literal characters by their numerical identifier, in decimal, octal or hexadecimal form.</p>"
0494             "<p>Examples:<ul>"
0495             "<li>char <b>234</b></li>"
0496             "<li>char <b>0x1234</b></li>"
0497             "</ul></p>");
0498         return true;
0499     }
0500     return false;
0501 }
0502 
0503 bool KateCommands::Character::exec(KTextEditor::View *view, const QString &_cmd, QString &, const KTextEditor::Range &)
0504 {
0505     QString cmd = _cmd;
0506 
0507     // hex, octal, base 9+1
0508     static const QRegularExpression num(QStringLiteral("^char *(0?x[0-9A-Fa-f]{1,4}|0[0-7]{1,6}|[0-9]{1,5})$"));
0509     const QRegularExpressionMatch match = num.match(cmd);
0510     if (!match.hasMatch()) {
0511         return false;
0512     }
0513 
0514     cmd = match.captured(1);
0515 
0516     // identify the base
0517 
0518     unsigned short int number = 0;
0519     int base = 10;
0520     if (cmd.startsWith(QLatin1Char('x'))) {
0521         cmd.remove(0, 1);
0522         base = 16;
0523     } else if (cmd.startsWith(QLatin1String("0x"))) {
0524         cmd.remove(0, 2);
0525         base = 16;
0526     } else if (cmd[0] == QLatin1Char('0')) {
0527         base = 8;
0528     }
0529     bool ok;
0530     number = cmd.toUShort(&ok, base);
0531     if (!ok || number == 0) {
0532         return false;
0533     }
0534     if (number <= 255) {
0535         char buf[2];
0536         buf[0] = (char)number;
0537         buf[1] = 0;
0538 
0539         view->document()->insertText(view->cursorPosition(), QString::fromLatin1(buf));
0540     } else {
0541         // do the unicode thing
0542         QChar c(number);
0543 
0544         view->document()->insertText(view->cursorPosition(), QString(&c, 1));
0545     }
0546 
0547     return true;
0548 }
0549 
0550 // END Character
0551 
0552 // BEGIN Date
0553 KateCommands::Date *KateCommands::Date::m_instance = nullptr;
0554 
0555 bool KateCommands::Date::help(class KTextEditor::View *, const QString &cmd, QString &msg)
0556 {
0557     if (cmd.trimmed() == QLatin1String("date")) {
0558         msg = i18n(
0559             "<p>date or date <b>format</b></p>"
0560             "<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>"
0561             "<p>Possible format specifiers are:"
0562             "<table>"
0563             "<tr><td>d</td><td>The day as number without a leading zero (1-31).</td></tr>"
0564             "<tr><td>dd</td><td>The day as number with a leading zero (01-31).</td></tr>"
0565             "<tr><td>ddd</td><td>The abbreviated localized day name (e.g. 'Mon'..'Sun').</td></tr>"
0566             "<tr><td>dddd</td><td>The long localized day name (e.g. 'Monday'..'Sunday').</td></tr>"
0567             "<tr><td>M</td><td>The month as number without a leading zero (1-12).</td></tr>"
0568             "<tr><td>MM</td><td>The month as number with a leading zero (01-12).</td></tr>"
0569             "<tr><td>MMM</td><td>The abbreviated localized month name (e.g. 'Jan'..'Dec').</td></tr>"
0570             "<tr><td>yy</td><td>The year as two digit number (00-99).</td></tr>"
0571             "<tr><td>yyyy</td><td>The year as four digit number (1752-8000).</td></tr>"
0572             "<tr><td>h</td><td>The hour without a leading zero (0..23 or 1..12 if AM/PM display).</td></tr>"
0573             "<tr><td>hh</td><td>The hour with a leading zero (00..23 or 01..12 if AM/PM display).</td></tr>"
0574             "<tr><td>m</td><td>The minute without a leading zero (0..59).</td></tr>"
0575             "<tr><td>mm</td><td>The minute with a leading zero (00..59).</td></tr>"
0576             "<tr><td>s</td><td>The second without a leading zero (0..59).</td></tr>"
0577             "<tr><td>ss</td><td>The second with a leading zero (00..59).</td></tr>"
0578             "<tr><td>z</td><td>The milliseconds without leading zeroes (0..999).</td></tr>"
0579             "<tr><td>zzz</td><td>The milliseconds with leading zeroes (000..999).</td></tr>"
0580             "<tr><td>AP</td><td>Use AM/PM display. AP will be replaced by either \"AM\" or \"PM\".</td></tr>"
0581             "<tr><td>ap</td><td>Use am/pm display. ap will be replaced by either \"am\" or \"pm\".</td></tr>"
0582             "</table></p>");
0583         return true;
0584     }
0585     return false;
0586 }
0587 
0588 bool KateCommands::Date::exec(KTextEditor::View *view, const QString &cmd, QString &, const KTextEditor::Range &)
0589 {
0590     if (!cmd.startsWith(QLatin1String("date"))) {
0591         return false;
0592     }
0593 
0594     if (QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length() - 5)).length() > 0) {
0595         view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length() - 5)));
0596     } else {
0597         view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd hh:mm:ss")));
0598     }
0599 
0600     return true;
0601 }
0602 
0603 // END Date