File indexing completed on 2024-04-21 03:57:37

0001 /*
0002     SPDX-FileCopyrightText: 2009-2018 Dominik Haumann <dhaumann@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "katecommandlinescript.h"
0008 
0009 #include <QJSEngine>
0010 #include <QJSValue>
0011 
0012 #include <KLocalizedString>
0013 #include <KShell>
0014 
0015 #include "katecmd.h"
0016 #include "katedocument.h"
0017 #include "katepartdebug.h"
0018 #include "kateview.h"
0019 
0020 KateCommandLineScript::KateCommandLineScript(const QString &url, const KateCommandLineScriptHeader &header)
0021     : KateScript(url)
0022     , KTextEditor::Command(header.functions())
0023     , m_commandHeader(header)
0024 {
0025 }
0026 
0027 const KateCommandLineScriptHeader &KateCommandLineScript::commandHeader()
0028 {
0029     return m_commandHeader;
0030 }
0031 
0032 bool KateCommandLineScript::callFunction(const QString &cmd, const QStringList &args, QString &errorMessage)
0033 {
0034     clearExceptions();
0035     QJSValue command = function(cmd);
0036     if (!command.isCallable()) {
0037         errorMessage = i18n("Function '%1' not found in script: %2", cmd, url());
0038         return false;
0039     }
0040 
0041     // add the arguments that we are going to pass to the function
0042     QJSValueList arguments;
0043     arguments.reserve(args.size());
0044     for (const QString &arg : args) {
0045         arguments << QJSValue(arg);
0046     }
0047 
0048     QJSValue result = command.call(arguments);
0049     // error during the calling?
0050     if (result.isError()) {
0051         errorMessage = backtrace(result, i18n("Error calling %1", cmd));
0052         return false;
0053     }
0054 
0055     return true;
0056 }
0057 
0058 bool KateCommandLineScript::exec(KTextEditor::View *view, const QString &cmd, QString &msg, const KTextEditor::Range &range)
0059 {
0060     if (range.isValid()) {
0061         view->setSelection(range);
0062     }
0063 
0064     KShell::Errors errorCode;
0065     QStringList args(KShell::splitArgs(cmd, KShell::NoOptions, &errorCode));
0066 
0067     if (errorCode != KShell::NoError) {
0068         msg = i18n("Bad quoting in call: %1. Please escape single quotes with a backslash.", cmd);
0069         return false;
0070     }
0071 
0072     QString _cmd(args.first());
0073     args.removeFirst();
0074 
0075     if (!view) {
0076         msg = i18n("Could not access view");
0077         return false;
0078     }
0079 
0080     if (setView(qobject_cast<KTextEditor::ViewPrivate *>(view))) {
0081         // setView fails if the script cannot be loaded
0082         // balance edit stack in any case!
0083         qobject_cast<KTextEditor::ViewPrivate *>(view)->doc()->pushEditState();
0084         bool success = callFunction(_cmd, args, msg);
0085         qobject_cast<KTextEditor::ViewPrivate *>(view)->doc()->popEditState();
0086         return success;
0087     }
0088 
0089     return false;
0090 }
0091 
0092 bool KateCommandLineScript::supportsRange(const QString &)
0093 {
0094     return true;
0095 }
0096 
0097 bool KateCommandLineScript::help(KTextEditor::View *view, const QString &cmd, QString &msg)
0098 {
0099     if (!setView(qobject_cast<KTextEditor::ViewPrivate *>(view))) {
0100         // setView fails, if the script cannot be loaded
0101         return false;
0102     }
0103 
0104     clearExceptions();
0105     QJSValue helpFunction = function(QStringLiteral("help"));
0106     if (!helpFunction.isCallable()) {
0107         return false;
0108     }
0109 
0110     // add the arguments that we are going to pass to the function
0111     QJSValueList arguments;
0112     arguments << QJSValue(cmd);
0113 
0114     QJSValue result = helpFunction.call(arguments);
0115 
0116     // error during the calling?
0117     if (result.isError()) {
0118         msg = backtrace(result, i18n("Error calling 'help %1'", cmd));
0119         return false;
0120     }
0121 
0122     if (result.isUndefined() || !result.isString()) {
0123         qCDebug(LOG_KTE) << i18n("No help specified for command '%1' in script %2", cmd, url());
0124         return false;
0125     }
0126     msg = result.toString();
0127 
0128     return !msg.isEmpty();
0129 }