Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -39,7 +39,7 @@ set(REQUIRED_QT_VERSION 5.6.0) # Required Qt5 components to build this framework -find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED Core Widgets Script PrintSupport Xml XmlPatterns) +find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED Core Widgets Qml PrintSupport Xml XmlPatterns) find_package(KF5Archive ${KF5_DEP_VERSION} REQUIRED) find_package(KF5Config ${KF5_DEP_VERSION} REQUIRED) Index: autotests/CMakeLists.txt =================================================================== --- autotests/CMakeLists.txt +++ autotests/CMakeLists.txt @@ -38,7 +38,7 @@ KF5::I18n KF5::IconThemes KF5::GuiAddons - Qt5::Script + Qt5::Qml ) include(ECMMarkAsTest) Index: autotests/src/bug313759.cpp =================================================================== --- autotests/src/bug313759.cpp +++ autotests/src/bug313759.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include "testutils.h" @@ -66,9 +66,8 @@ QFile scriptFile(QLatin1String(JS_DATA_DIR "commands/utils.js")); QVERIFY(scriptFile.exists()); QVERIFY(scriptFile.open(QFile::ReadOnly)); - QScriptValue result = env->engine()->evaluate(QString::fromLatin1(scriptFile.readAll()), scriptFile.fileName()); - QVERIFY2(!result.isError(), qPrintable(QString(result.toString() + QLatin1String("\nat ") - + env->engine()->uncaughtExceptionBacktrace().join(QStringLiteral("\n"))))); + QJSValue result = env->engine()->evaluate(QString::fromLatin1(scriptFile.readAll()), scriptFile.fileName()); + QVERIFY2(!result.isError(), result.toString().toUtf8().constData()); // enable on the fly spell checking doc->onTheFlySpellCheckingEnabled(true); Index: autotests/src/bug317111.cpp =================================================================== --- autotests/src/bug317111.cpp +++ autotests/src/bug317111.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include "testutils.h" @@ -66,9 +66,8 @@ QFile scriptFile(QLatin1String(JS_DATA_DIR"commands/utils.js")); QVERIFY(scriptFile.exists()); QVERIFY(scriptFile.open(QFile::ReadOnly)); - QScriptValue result = env->engine()->evaluate(QString::fromLatin1(scriptFile.readAll()), scriptFile.fileName()); - QVERIFY2(!result.isError(), qPrintable(QString(result.toString() + QLatin1String("\nat ") - + env->engine()->uncaughtExceptionBacktrace().join(QStringLiteral("\n"))))); + QJSValue result = env->engine()->evaluate(QString::fromLatin1(scriptFile.readAll()), scriptFile.fileName()); + QVERIFY2(!result.isError(), result.toString().toUtf8().constData()); // view must be visible... view->show(); Index: autotests/src/script_test_base.cpp =================================================================== --- autotests/src/script_test_base.cpp +++ autotests/src/script_test_base.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include @@ -79,9 +79,8 @@ QFile scriptFile(QLatin1String(JS_DATA_DIR) + m_script_dir + QLatin1Char('/') + script + QLatin1String(".js")); if (scriptFile.exists()) { QVERIFY(scriptFile.open(QFile::ReadOnly)); - QScriptValue result = m_env->engine()->evaluate(QString::fromLatin1(scriptFile.readAll()), scriptFile.fileName()); - QVERIFY2(!result.isError(), qPrintable(QString(result.toString() + QLatin1String("\nat ") - + m_env->engine()->uncaughtExceptionBacktrace().join(QLatin1String("\n"))))); + QJSValue result = m_env->engine()->evaluate(QString::fromLatin1(scriptFile.readAll()), scriptFile.fileName()); + QVERIFY2(!result.isError(), (result.toString() + QLatin1String(" in file ") + scriptFile.fileName()).toUtf8().constData()); } } @@ -131,7 +130,7 @@ sourceFile.close(); // Execute script - QScriptValue result = m_env->engine()->evaluate(code, testcase + QLatin1String("/input.js"), 1); + QJSValue result = m_env->engine()->evaluate(code, testcase + QLatin1String("/input.js"), 1); QVERIFY2(!result.isError(), result.toString().toUtf8().constData()); const QString fileExpected = testcase + QLatin1String("/expected"); Index: autotests/src/scriptdocument_test.cpp =================================================================== --- autotests/src/scriptdocument_test.cpp +++ autotests/src/scriptdocument_test.cpp @@ -20,10 +20,12 @@ #include "scriptdocument_test.h" #include +#include "ktexteditor/cursor.h" #include #include #include +#include #include QTEST_MAIN(ScriptDocumentTest) @@ -68,7 +70,7 @@ { m_doc = new KTextEditor::DocumentPrivate; m_view = m_doc->createView(nullptr); - m_scriptDoc = new KateScriptDocument(this); + m_scriptDoc = new KateScriptDocument(nullptr, this); m_scriptDoc->setDocument(m_doc); } @@ -122,7 +124,8 @@ m_scriptDoc->setText("a a a a a a a a a a a a"); - QCOMPARE(m_scriptDoc->rfind(searchStart.line(), searchStart.column(), "a a a"), result); + KTextEditor::Cursor cursor = m_scriptDoc->rfind(searchStart, "a a a"); + QCOMPARE(cursor, result); } #include "moc_scriptdocument_test.cpp" Index: autotests/src/templatehandler_test.cpp =================================================================== --- autotests/src/templatehandler_test.cpp +++ autotests/src/templatehandler_test.cpp @@ -54,7 +54,7 @@ doc->config()->setIndentationWidth(4); doc->config()->setReplaceTabsDyn(true); - view->insertTemplate({0, 0}, snippet); + view->insertTemplate(KTextEditor::Cursor(0, 0), snippet); const QString result = "for (int i = ; i < ; ++i)\n" "{\n" @@ -359,7 +359,7 @@ QFETCH(QString, input); QFETCH(QString, function); - view->insertTemplate({0, 0}, input, function); + view->insertTemplate(KTextEditor::Cursor(0, 0), input, function); QTEST(doc->text(), "expected"); view->selectAll(); Index: autotests/src/testutils.h =================================================================== --- autotests/src/testutils.h +++ autotests/src/testutils.h @@ -24,9 +24,9 @@ #define TESTUTILS_H #include "katescriptview.h" -#include "katescriptdocument.h" -#include +#include "katescriptdocument.h" +#include namespace KTextEditor { class ViewPrivate; } class RegressionTest; @@ -45,7 +45,7 @@ explicit TestScriptEnv(KTextEditor::DocumentPrivate *part, bool &cflag); virtual ~TestScriptEnv(); - QScriptEngine *engine() const + QJSEngine *engine() const { return m_engine; } @@ -57,7 +57,7 @@ } private: - QScriptEngine *m_engine; + QJSEngine *m_engine; KateViewObject *m_viewObj; KateDocumentObject *m_docObj; @@ -73,7 +73,7 @@ public: - explicit KateViewObject(KTextEditor::ViewPrivate *view); + explicit KateViewObject(QJSEngine *engine, KTextEditor::ViewPrivate *view); virtual ~KateViewObject(); // Edit functions @@ -155,7 +155,7 @@ Q_OBJECT public: - explicit KateDocumentObject(KTextEditor::DocumentPrivate *doc); + explicit KateDocumentObject(QJSEngine *engine, KTextEditor::DocumentPrivate *doc); virtual ~KateDocumentObject(); private: @@ -168,7 +168,7 @@ * enabling one to check for coordinates and the like. * @internal */ -class OutputObject : public QObject, protected QScriptable +class OutputObject : public QObject { Q_OBJECT @@ -201,5 +201,4 @@ KTextEditor::ViewPrivate *view; bool &cflag; }; - #endif // TESTUTILS_H Index: autotests/src/testutils.cpp =================================================================== --- autotests/src/testutils.cpp +++ autotests/src/testutils.cpp @@ -30,92 +30,55 @@ #include "kateconfig.h" #include "katedocument.h" #include "katescripthelpers.h" +#include "ktexteditor/cursor.h" +#include "ktexteditor/range.h" -#include +#include +#include +#include #include //END Includes //BEGIN TestScriptEnv -//BEGIN conversion functions for Cursors and Ranges -/** Converstion function from KTextEditor::Cursor to QtScript cursor */ -static QScriptValue cursorToScriptValue(QScriptEngine *engine, const KTextEditor::Cursor &cursor) -{ - QString code = QStringLiteral("new Cursor(%1, %2);").arg(cursor.line()) - .arg(cursor.column()); - return engine->evaluate(code); -} - -/** Converstion function from QtScript cursor to KTextEditor::Cursor */ -static void cursorFromScriptValue(const QScriptValue &obj, KTextEditor::Cursor &cursor) -{ - cursor.setPosition(obj.property(QStringLiteral("line")).toInt32(), - obj.property(QStringLiteral("column")).toInt32()); -} - -/** Converstion function from QtScript range to KTextEditor::Range */ -static QScriptValue rangeToScriptValue(QScriptEngine *engine, const KTextEditor::Range &range) -{ - QString code = QStringLiteral("new Range(%1, %2, %3, %4);").arg(range.start().line()) - .arg(range.start().column()) - .arg(range.end().line()) - .arg(range.end().column()); - return engine->evaluate(code); -} - -/** Converstion function from QtScript range to KTextEditor::Range */ -static void rangeFromScriptValue(const QScriptValue &obj, KTextEditor::Range &range) -{ - range.setStart(KTextEditor::Cursor( - obj.property(QStringLiteral("start")).property(QStringLiteral("line")).toInt32(), - obj.property(QStringLiteral("start")).property(QStringLiteral("column")).toInt32() - )); - range.setEnd(KTextEditor::Cursor( - obj.property(QStringLiteral("end")).property(QStringLiteral("line")).toInt32(), - obj.property(QStringLiteral("end")).property(QLatin1String("column")).toInt32() - )); -} -//END - TestScriptEnv::TestScriptEnv(KTextEditor::DocumentPrivate *part, bool &cflag) : m_engine(nullptr), m_viewObj(nullptr), m_docObj(nullptr), m_output(nullptr) { - m_engine = new QScriptEngine(this); - - qScriptRegisterMetaType(m_engine, cursorToScriptValue, cursorFromScriptValue); - qScriptRegisterMetaType(m_engine, rangeToScriptValue, rangeFromScriptValue); + m_engine = new QJSEngine(this); // export read & require function and add the require guard object - m_engine->globalObject().setProperty(QStringLiteral("read"), m_engine->newFunction(Kate::Script::read)); - m_engine->globalObject().setProperty(QStringLiteral("require"), m_engine->newFunction(Kate::Script::require)); + QJSValue functions = m_engine->newQObject(new Kate::ScriptHelper(m_engine)); + m_engine->globalObject().setProperty(QStringLiteral("functions"), functions); + m_engine->globalObject().setProperty(QStringLiteral("read"), functions.property(QStringLiteral("read"))); + m_engine->globalObject().setProperty(QStringLiteral("require"), functions.property(QStringLiteral("require"))); m_engine->globalObject().setProperty(QStringLiteral("require_guard"), m_engine->newObject()); - - // export debug function - m_engine->globalObject().setProperty(QStringLiteral("debug"), m_engine->newFunction(Kate::Script::debug)); + + // export debug function + m_engine->globalObject().setProperty(QStringLiteral("debug"), functions.property(QStringLiteral("debug"))); // export translation functions - m_engine->globalObject().setProperty(QStringLiteral("i18n"), m_engine->newFunction(Kate::Script::i18n)); - m_engine->globalObject().setProperty(QStringLiteral("i18nc"), m_engine->newFunction(Kate::Script::i18nc)); - m_engine->globalObject().setProperty(QStringLiteral("i18ncp"), m_engine->newFunction(Kate::Script::i18ncp)); - m_engine->globalObject().setProperty(QStringLiteral("i18np"), m_engine->newFunction(Kate::Script::i18np)); + m_engine->globalObject().setProperty(QStringLiteral("i18n"), functions.property(QStringLiteral("_i18n"))); + m_engine->globalObject().setProperty(QStringLiteral("i18nc"), functions.property(QStringLiteral("_i18nc"))); + m_engine->globalObject().setProperty(QStringLiteral("i18np"), functions.property(QStringLiteral("_i18np"))); + m_engine->globalObject().setProperty(QStringLiteral("i18ncp"), functions.property(QStringLiteral("_i18ncp"))); KTextEditor::ViewPrivate *view = qobject_cast(part->widget()); - m_viewObj = new KateViewObject(view); - QScriptValue sv = m_engine->newQObject(m_viewObj); + m_viewObj = new KateViewObject(m_engine, view); + QJSValue sv = m_engine->newQObject(m_viewObj); m_engine->globalObject().setProperty(QStringLiteral("view"), sv); m_engine->globalObject().setProperty(QStringLiteral("v"), sv); - m_docObj = new KateDocumentObject(view->doc()); - QScriptValue sd = m_engine->newQObject(m_docObj); + m_docObj = new KateDocumentObject(m_engine, view->doc()); + QJSValue sd = m_engine->newQObject(m_docObj); m_engine->globalObject().setProperty(QStringLiteral("document"), sd); m_engine->globalObject().setProperty(QStringLiteral("d"), sd); m_output = new OutputObject(view, cflag); - QScriptValue so = m_engine->newQObject(m_output); + QJSValue so = m_engine->newQObject(m_output); m_engine->globalObject().setProperty(QStringLiteral("output"), so); m_engine->globalObject().setProperty(QStringLiteral("out"), so); @@ -139,8 +102,8 @@ //BEGIN KateViewObject -KateViewObject::KateViewObject(KTextEditor::ViewPrivate *view) - : KateScriptView() +KateViewObject::KateViewObject(QJSEngine *engine, KTextEditor::ViewPrivate *view) + : KateScriptView(engine) { setView(view); } @@ -234,8 +197,8 @@ //BEGIN KateDocumentObject -KateDocumentObject::KateDocumentObject(KTextEditor::DocumentPrivate *doc) - : KateScriptDocument() +KateDocumentObject::KateDocumentObject(QJSEngine *engine, KTextEditor::DocumentPrivate *doc) + : KateScriptDocument(engine) { setDocument(doc); } @@ -247,7 +210,6 @@ //END KateDocumentObject //BEGIN OutputObject - OutputObject::OutputObject(KTextEditor::ViewPrivate *v, bool &cflag) : view(v), cflag(cflag) { @@ -261,10 +223,11 @@ void OutputObject::output(bool cp, bool ln) { QString str; - for (int i = 0; i < context()->argumentCount(); ++i) { - QScriptValue arg = context()->argument(i); - str += arg.toString(); - } +// FIXME: This is not available with QtQml, but not sure if we need it +// for (int i = 0; i < context()->argumentCount(); ++i) { +// QJSValue arg = context()->argument(i); +// str += arg.toString(); +// } if (cp) { KTextEditor::Cursor c = view->cursorPosition(); @@ -349,5 +312,4 @@ { output(true, true); } - //END OutputObject Index: autotests/src/vimode/CMakeLists.txt =================================================================== --- autotests/src/vimode/CMakeLists.txt +++ autotests/src/vimode/CMakeLists.txt @@ -6,7 +6,6 @@ set (VIMODE_TEST_LINK_LIBS KF5TextEditor KF5::I18n - Qt5::Script Qt5::Test ) Index: src/CMakeLists.txt =================================================================== --- src/CMakeLists.txt +++ src/CMakeLists.txt @@ -305,7 +305,7 @@ PUBLIC KF5::Parts PRIVATE - Qt5::Script + Qt5::Qml Qt5::PrintSupport KF5::I18n KF5::Archive Index: src/include/ktexteditor/cursor.h =================================================================== --- src/include/ktexteditor/cursor.h +++ src/include/ktexteditor/cursor.h @@ -381,7 +381,7 @@ int m_column; }; -} +} // namespace KTextEditor Q_DECLARE_TYPEINFO(KTextEditor::Cursor, Q_MOVABLE_TYPE); Q_DECLARE_METATYPE(KTextEditor::Cursor) Index: src/script/data/indentation/ada.js =================================================================== --- src/script/data/indentation/ada.js +++ src/script/data/indentation/ada.js @@ -49,8 +49,6 @@ // TODO: 'protected', 'task', 'select' & // possibly other keywords not recognised -"use strict"; - // required katepart js libraries require ("range.js"); require ("cursor.js"); @@ -64,11 +62,11 @@ //END USER CONFIGURATION -const AdaComment = /\s*--.*$/; -const unfStmt = /([.=\(]|:=[^;]*)\s*$/; -const unfLoop = /^\s*(for|while)\b(?!.*\bloop\b)/i; -const AdaBlockStart = /^\s*(if\b|while\b|else\b|elsif\b|loop\b|for\b.*\b(loop|use)\b|declare\b|begin\b|type\b.*\bis\b[^;]*$|(type\b.*)?\brecord\b|procedure\b|function\b|with\s+function\b|accept\b|do\b|task\b|generic\b|package\b|private\b|then\b|when\b|is\b)/i; -const StatementStart = /^\s*(if|when|while|else|elsif|loop|for\b.*\b(loop|use)|begin)\b/i; +var AdaComment = /\s*--.*$/; +var unfStmt = /([.=\(]|:=[^;]*)\s*$/; +var unfLoop = /^\s*(for|while)\b(?!.*\bloop\b)/i; +var AdaBlockStart = /^\s*(if\b|while\b|else\b|elsif\b|loop\b|for\b.*\b(loop|use)\b|declare\b|begin\b|type\b.*\bis\b[^;]*$|(type\b.*)?\brecord\b|procedure\b|function\b|with\s+function\b|accept\b|do\b|task\b|generic\b|package\b|private\b|then\b|when\b|is\b)/i; +var StatementStart = /^\s*(if|when|while|else|elsif|loop|for\b.*\b(loop|use)|begin)\b/i; function dbg() { if (debugMode) { @@ -85,7 +83,7 @@ // regexp of keywords & patterns that cause reindenting of the current line. -const AdaReIndent = /^\s*((then|end|elsif|when|exception|begin|is|record|private)\s+|<<\w+>>|end;|[#\)])(.*)$/; +var AdaReIndent = /^\s*((then|end|elsif|when|exception|begin|is|record|private)\s+|<<\w+>>|end;|[#\)])(.*)$/; // characters which trigger indent, beside the default '\n' var triggerCharacters = " \t)#>;"; Index: src/script/data/indentation/cstyle.js =================================================================== --- src/script/data/indentation/cstyle.js +++ src/script/data/indentation/cstyle.js @@ -756,8 +756,9 @@ var prevFirstPos = document.firstColumn(line - 1); var lastPos = document.lastColumn(line); - dbg("firstPos: " + firstPos); - dbg("column..: " + column); + dbg("firstPos: " + firstPos); + dbg("column..: " + column); + dbg("char : " + c); if (firstPos == column - 1 && c == '{') { // todo: maybe look for if etc. @@ -785,7 +786,10 @@ } else if (cfgSnapSlash && c == '/' && lastPos == column - 1) { // try to snap the string "* /" to "*/" var currentString = document.line(line); - if (currentString.search(/^(\s*)\*\s+\/\s*$/) != -1) { + var regex = /^(\s*)\*\s+\/\s*$/; + // Doing the follow test as (currentString.search(/^(\s*)\*\s+\/\s*$/) != -1) + // triggers a bug in QtQml where RegExp.$1 ends up empty. + if (regex.test(currentString)) { currentString = RegExp.$1 + "*/"; document.editBegin(); document.removeLine(line); Index: src/script/data/indentation/pascal.js =================================================================== --- src/script/data/indentation/pascal.js +++ src/script/data/indentation/pascal.js @@ -94,11 +94,8 @@ - procedure/function declarations in 'interface' should be indented */ -"use strict"; - // required katepart js libraries require ("range.js"); -require ("cursor.js"); require ("string.js"); //BEGIN USER CONFIGURATION @@ -110,13 +107,13 @@ //END USER CONFIGURATION -const patTrailingSemi = /;\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/; -const patMatchEnd = /\b(begin|case|record)\b/i; -const patDeclaration = /^\s*(program|module|unit|uses|import|implementation|interface|label|const|type|var|function|procedure|operator)\b/i; -const patTrailingBegin = /\bbegin\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/i; -const patTrailingEnd = /\bend;?\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/i; -const patCaseValue = /^(\s*[^,:;]+\s*(,\s*[^,:;]+\s*)*):(?!=)/; -const patEndOfStatement = /(;|end)\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/i; +var patTrailingSemi = /;\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/; +var patMatchEnd = /\b(begin|case|record)\b/i; +var patDeclaration = /^\s*(program|module|unit|uses|import|implementation|interface|label|const|type|var|function|procedure|operator)\b/i; +var patTrailingBegin = /\bbegin\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/i; +var patTrailingEnd = /\bend;?\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/i; +var patCaseValue = /^(\s*[^,:;]+\s*(,\s*[^,:;]+\s*)*):(?!=)/; +var patEndOfStatement = /(;|end)\s*(\/\/.*|\{.*\}|\(\*.*\*\))?\s*$/i; function dbg() { if (debugMode) { @@ -1392,7 +1389,7 @@ triggerCharacters = " \t)]}#;"; // possible outdent for lines that match this regexp -const PascalReIndent = /^\s*((end|const|type|var|begin|until|function|procedure|operator|else|otherwise|\w+\s*:)\s+|[#\)\]\}]|end;)(.*)$/; +var PascalReIndent = /^\s*((end|const|type|var|begin|until|function|procedure|operator|else|otherwise|\w+\s*:)\s+|[#\)\]\}]|end;)(.*)$/; // check if the trigger characters are in the right context, // otherwise running the indenter might be annoying to the user Index: src/script/data/indentation/ruby.js =================================================================== --- src/script/data/indentation/ruby.js +++ src/script/data/indentation/ruby.js @@ -27,6 +27,7 @@ */ // required katepart js libraries +require ("cursor.js"); require ("range.js"); //BEGIN USER CONFIGURATION @@ -42,6 +43,13 @@ // Unindent lines that match this regexp var rxUnindent = /^\s*((end|when|else|elsif|rescue|ensure)\b|[\]\}])(.*)$/; +var debugMode = true; +function dbg() { + if (debugMode) { + debug.apply(this, arguments); + } +} + function assert(cond) { if (!cond) @@ -149,7 +157,7 @@ while (line < this.end && document.lineLength(line) < offset) { offset -= document.lineLength(line++) + 1; } - return {line: line, column: offset}; + return new Cursor(line, offset); // {line: line, column: offset}; } // Return document.attribute at the given offset in a statement @@ -172,7 +180,7 @@ // Return the indent at the beginning of the statement this.indent = function() { - return document.firstVirtualColumn(this.start) + return document.firstVirtualColumn(this.start); } // Return the content of the statement from the document @@ -270,11 +278,12 @@ // containing the type of bracket. function lastAnchor(line, column) { - var anch = document.anchor(line, column, '('); + var cursor = new Cursor(line, column); + var anch = document.anchor(cursor, '('); anch.ch = '('; - var tmp1 = document.anchor(line, column, '{'); + var tmp1 = document.anchor(cursor, '{'); tmp1.ch = '{'; - var tmp2 = document.anchor(line, column, '['); + var tmp2 = document.anchor(cursor, '['); tmp2.ch = '['; if (compare(tmp1, anch) == 1) Index: src/script/katecommandlinescript.cpp =================================================================== --- src/script/katecommandlinescript.cpp +++ src/script/katecommandlinescript.cpp @@ -20,8 +20,8 @@ #include "katecommandlinescript.h" -#include -#include +#include +#include #include #include @@ -50,24 +50,24 @@ bool KateCommandLineScript::callFunction(const QString &cmd, const QStringList args, QString &errorMessage) { clearExceptions(); - QScriptValue command = function(cmd); - if (!command.isValid()) { + QJSValue command = function(cmd); + if (!command.isCallable()) { errorMessage = i18n("Function '%1' not found in script: %2", cmd, url()); return false; } // add the arguments that we are going to pass to the function - QScriptValueList arguments; - foreach (const QString &arg, args) { - arguments << QScriptValue(m_engine, arg); + QJSValueList arguments; + for (const QString &arg : args) { + arguments << QJSValue(arg); } - QScriptValue result = command.call(QScriptValue(), arguments); + QJSValue result = command.call(arguments); // error during the calling? - if (m_engine->hasUncaughtException()) { - errorMessage = backtrace(result, i18n("Error calling %1", cmd)); - return false; - } + if (result.isError()) { + errorMessage = backtrace(result, i18n("Error calling %1", cmd)); + return false; + } return true; } @@ -119,19 +119,19 @@ } clearExceptions(); - QScriptValue helpFunction = function(QStringLiteral("help")); - if (!helpFunction.isValid()) { + QJSValue helpFunction = function(QStringLiteral("help")); + if (!helpFunction.isCallable()) { return false; } // add the arguments that we are going to pass to the function - QScriptValueList arguments; - arguments << QScriptValue(m_engine, cmd); + QJSValueList arguments; + arguments << QJSValue(cmd); - QScriptValue result = helpFunction.call(QScriptValue(), arguments); + QJSValue result = helpFunction.call(arguments); // error during the calling? - if (m_engine->hasUncaughtException()) { + if (result.isError()) { msg = backtrace(result, i18n("Error calling 'help %1'", cmd)); return false; } Index: src/script/kateindentscript.cpp =================================================================== --- src/script/kateindentscript.cpp +++ src/script/kateindentscript.cpp @@ -19,8 +19,8 @@ #include "kateindentscript.h" -#include -#include +#include +#include #include "katedocument.h" #include "kateview.h" @@ -62,34 +62,31 @@ } clearExceptions(); - QScriptValue indentFunction = function(QStringLiteral("indent")); - if (!indentFunction.isValid()) { + QJSValue indentFunction = function(QStringLiteral("indent")); + if (!indentFunction.isCallable()) { return qMakePair(-2, -2); } // add the arguments that we are going to pass to the function - QScriptValueList arguments; - arguments << QScriptValue(m_engine, position.line()); - arguments << QScriptValue(m_engine, indentWidth); - arguments << QScriptValue(m_engine, typedCharacter.isNull() ? QString() : QString(typedCharacter)); + QJSValueList arguments; + arguments << QJSValue(position.line()); + arguments << QJSValue(indentWidth); + arguments << (typedCharacter.isNull() ? QJSValue(QString()) : QJSValue(QString(typedCharacter))); // get the required indent - QScriptValue result = indentFunction.call(QScriptValue(), arguments); + QJSValue result = indentFunction.call(arguments); // error during the calling? - if (m_engine->hasUncaughtException()) { + if (result.isError()) { displayBacktrace(result, QStringLiteral("Error calling indent()")); return qMakePair(-2, -2); } int indentAmount = -2; int alignAmount = -2; if (result.isArray()) { - indentAmount = result.property(0).toInt32(); - alignAmount = result.property(1).toInt32(); + indentAmount = result.property(0).toInt(); + alignAmount = result.property(1).toInt(); } else { - indentAmount = result.toInt32(); - } - if (m_engine->hasUncaughtException()) { - displayBacktrace(QScriptValue(), QStringLiteral("Bad return type (must be integer)")); - return qMakePair(-2, -2); + indentAmount = result.toInt(); } + return qMakePair(indentAmount, alignAmount); } Index: src/script/katescript.h =================================================================== --- src/script/katescript.h +++ src/script/katescript.h @@ -21,11 +21,11 @@ #ifndef KATE_SCRIPT_H #define KATE_SCRIPT_H -#include -#include -#include +#include +#include +#include -class QScriptEngine; +class QJSEngine; namespace KTextEditor { class ViewPrivate; } @@ -122,7 +122,7 @@ InputSCRIPT }; - typedef QMap FieldMap; + typedef QMap FieldMap; /** * Create a new script representation, passing either a file or the script @@ -154,16 +154,16 @@ bool setView(KTextEditor::ViewPrivate *view); /** - * Get a QScriptValue for a global item in the script given its name, or an - * invalid QScriptValue if no such global item exists. + * Get a QJSValue for a global item in the script given its name, or an + * invalid QJSValue if no such global item exists. */ - QScriptValue global(const QString &name); + QJSValue global(const QString &name); /** - * Return a function in the script of the given name, or an invalid QScriptValue + * Return a function in the script of the given name, or an invalid QJSValue * if no such function exists. */ - QScriptValue function(const QString &name); + QJSValue function(const QString &name); /** Return a context-specific error message */ const QString &errorMessage() @@ -172,13 +172,13 @@ } /** Returns the backtrace when a script has errored out */ - QString backtrace(const QScriptValue &error, const QString &header = QString()); + QString backtrace(const QJSValue &error, const QString &header = QString()); /** Execute a piece of code **/ - QScriptValue evaluate(const QString& program, const FieldMap& env = FieldMap()); + QJSValue evaluate(const QString& program, const FieldMap& env = FieldMap()); /** Displays the backtrace when a script has errored out */ - void displayBacktrace(const QScriptValue &error, const QString &header = QString()); + void displayBacktrace(const QJSValue &error, const QString &header = QString()); /** Clears any uncaught exceptions in the script engine. */ void clearExceptions(); @@ -190,7 +190,7 @@ protected: /** Checks for exception and gives feedback on the console. */ - bool hasException(const QScriptValue &object, const QString &file); + bool hasException(const QJSValue &object, const QString &file); private: /** Whether or not there has been a call to load */ @@ -207,7 +207,7 @@ protected: /** The Qt interpreter for this script */ - QScriptEngine *m_engine; + QJSEngine *m_engine; private: /** general header data */ Index: src/script/katescript.cpp =================================================================== --- src/script/katescript.cpp +++ src/script/katescript.cpp @@ -31,45 +31,13 @@ #include #include -#include -#include -#include +#include +#include #include +#include //BEGIN conversion functions for Cursors and Ranges -/** Converstion function from KTextEditor::Cursor to QtScript cursor */ -static QScriptValue cursorToScriptValue(QScriptEngine *engine, const KTextEditor::Cursor &cursor) -{ - QString code = QStringLiteral("new Cursor(%1, %2);").arg(cursor.line()) - .arg(cursor.column()); - return engine->evaluate(code); -} - -/** Converstion function from QtScript cursor to KTextEditor::Cursor */ -static void cursorFromScriptValue(const QScriptValue &obj, KTextEditor::Cursor &cursor) -{ - cursor.setPosition(obj.property(QStringLiteral("line")).toInt32(), - obj.property(QStringLiteral("column")).toInt32()); -} - -/** Converstion function from QtScript range to KTextEditor::Range */ -static QScriptValue rangeToScriptValue(QScriptEngine *engine, const KTextEditor::Range &range) -{ - QString code = QStringLiteral("new Range(%1, %2, %3, %4);").arg(range.start().line()) - .arg(range.start().column()) - .arg(range.end().line()) - .arg(range.end().column()); - return engine->evaluate(code); -} -/** Converstion function from QtScript range to KTextEditor::Range */ -static void rangeFromScriptValue(const QScriptValue &obj, KTextEditor::Range &range) -{ - range.setRange(KTextEditor::Cursor(obj.property(QStringLiteral("start")).property(QStringLiteral("line")).toInt32(), - obj.property(QStringLiteral("start")).property(QStringLiteral("column")).toInt32()), - KTextEditor::Cursor(obj.property(QStringLiteral("end")).property(QStringLiteral("line")).toInt32(), - obj.property(QStringLiteral("end")).property(QStringLiteral("column")).toInt32())); -} //END KateScript::KateScript(const QString &urlOrScript, enum InputType inputType) @@ -88,13 +56,13 @@ { if (m_loadSuccessful) { // remove data... - delete m_engine; delete m_document; delete m_view; + delete m_engine; } } -QString KateScript::backtrace(const QScriptValue &error, const QString &header) +QString KateScript::backtrace(const QJSValue &error, const QString &header) { QString bt; if (!header.isNull()) { @@ -104,12 +72,10 @@ bt += error.toString() + QLatin1Char('\n'); } - bt += m_engine->uncaughtExceptionBacktrace().join(QStringLiteral("\n")) + QLatin1Char('\n'); - return bt; } -void KateScript::displayBacktrace(const QScriptValue &error, const QString &header) +void KateScript::displayBacktrace(const QJSValue &error, const QString &header) { if (!m_engine) { std::cerr << "KateScript::displayBacktrace: no engine, cannot display error\n"; @@ -123,23 +89,22 @@ if (!load()) { return; } - m_engine->clearExceptions(); } -QScriptValue KateScript::global(const QString &name) +QJSValue KateScript::global(const QString &name) { // load the script if necessary if (!load()) { - return QScriptValue(); + return QJSValue::UndefinedValue; } return m_engine->globalObject().property(name); } -QScriptValue KateScript::function(const QString &name) +QJSValue KateScript::function(const QString &name) { - QScriptValue value = global(name); - if (!value.isFunction()) { - return QScriptValue(); + QJSValue value = global(name); + if (!value.isCallable()) { + return QJSValue::UndefinedValue; } return value; } @@ -164,23 +129,23 @@ } // create script engine, register meta types - m_engine = new QScriptEngine(); - qScriptRegisterMetaType(m_engine, cursorToScriptValue, cursorFromScriptValue); - qScriptRegisterMetaType(m_engine, rangeToScriptValue, rangeFromScriptValue); + m_engine = new QJSEngine(); // export read & require function and add the require guard object - m_engine->globalObject().setProperty(QStringLiteral("read"), m_engine->newFunction(Kate::Script::read)); - m_engine->globalObject().setProperty(QStringLiteral("require"), m_engine->newFunction(Kate::Script::require)); + QJSValue functions = m_engine->newQObject(new Kate::ScriptHelper(m_engine)); + m_engine->globalObject().setProperty(QStringLiteral("functions"), functions); + m_engine->globalObject().setProperty(QStringLiteral("read"), functions.property(QStringLiteral("read"))); + m_engine->globalObject().setProperty(QStringLiteral("require"), functions.property(QStringLiteral("require"))); m_engine->globalObject().setProperty(QStringLiteral("require_guard"), m_engine->newObject()); // export debug function - m_engine->globalObject().setProperty(QStringLiteral("debug"), m_engine->newFunction(Kate::Script::debug)); + m_engine->globalObject().setProperty(QStringLiteral("debug"), functions.property(QStringLiteral("debug"))); // export translation functions - m_engine->globalObject().setProperty(QStringLiteral("i18n"), m_engine->newFunction(Kate::Script::i18n)); - m_engine->globalObject().setProperty(QStringLiteral("i18nc"), m_engine->newFunction(Kate::Script::i18nc)); - m_engine->globalObject().setProperty(QStringLiteral("i18ncp"), m_engine->newFunction(Kate::Script::i18ncp)); - m_engine->globalObject().setProperty(QStringLiteral("i18np"), m_engine->newFunction(Kate::Script::i18np)); + m_engine->globalObject().setProperty(QStringLiteral("i18n"), functions.property(QStringLiteral("_i18n"))); + m_engine->globalObject().setProperty(QStringLiteral("i18nc"), functions.property(QStringLiteral("_i18nc"))); + m_engine->globalObject().setProperty(QStringLiteral("i18np"), functions.property(QStringLiteral("_i18np"))); + m_engine->globalObject().setProperty(QStringLiteral("i18ncp"), functions.property(QStringLiteral("_i18ncp"))); // register default styles as ds* global properties m_engine->globalObject().setProperty(QStringLiteral("dsNormal"), KTextEditor::dsNormal); @@ -216,14 +181,14 @@ m_engine->globalObject().setProperty(QStringLiteral("dsError"), KTextEditor::dsError); // register scripts itself - QScriptValue result = m_engine->evaluate(source, m_url); + QJSValue result = m_engine->evaluate(source, m_url); if (hasException(result, m_url)) { return false; } // AFTER SCRIPT: set the view/document objects as necessary - m_engine->globalObject().setProperty(QStringLiteral("document"), m_engine->newQObject(m_document = new KateScriptDocument())); - m_engine->globalObject().setProperty(QStringLiteral("view"), m_engine->newQObject(m_view = new KateScriptView())); + m_engine->globalObject().setProperty(QStringLiteral("document"), m_engine->newQObject(m_document = new KateScriptDocument(m_engine))); + m_engine->globalObject().setProperty(QStringLiteral("view"), m_engine->newQObject(m_view = new KateScriptView(m_engine))); // yip yip! m_loadSuccessful = true; @@ -231,29 +196,37 @@ return true; } -QScriptValue KateScript::evaluate(const QString& program, const FieldMap& env) +QJSValue KateScript::evaluate(const QString& program, const FieldMap& env) { if ( !load() ) { qWarning() << "load of script failed:" << program; - return QScriptValue(); + return QJSValue(); } - // set up stuff in a new context, to not pollute the global stuff - auto context = m_engine->pushContext(); + // Wrap the arguments in a function to avoid poluting the global object + QString programWithContext = QStringLiteral("function(") + + QStringList(env.keys()).join(QLatin1Char(',')) + + QStringLiteral(") { return ") + + program + + QStringLiteral("}"); + QJSValue programFunction = m_engine->evaluate(programWithContext); + Q_ASSERT(programFunction.isCallable()); - auto obj = context->activationObject(); + QJSValueList args; for ( auto it = env.begin(); it != env.end(); it++ ) { - obj.setProperty(it.key(), *it); + args << it.value(); } - auto result = m_engine->evaluate(program); - m_engine->popContext(); + QJSValue result = programFunction.call(args); + if (result.isError()) + qWarning() << "Error evaluating script: " << result.toString(); + return result; } -bool KateScript::hasException(const QScriptValue &object, const QString &file) +bool KateScript::hasException(const QJSValue &object, const QString &file) { - if (m_engine->hasUncaughtException()) { + if (object.isError()) { displayBacktrace(object, i18n("Error loading script %1\n", file)); m_errorMessage = i18n("Error loading script %1", file); delete m_engine; @@ -284,4 +257,3 @@ { return m_generalHeader; } - Index: src/script/katescriptdocument.h =================================================================== --- src/script/katescriptdocument.h +++ src/script/katescriptdocument.h @@ -22,11 +22,10 @@ #include #include -#include #include -#include +#include #include #include @@ -37,19 +36,16 @@ * Thinish wrapping around KTextEditor::DocumentPrivate, exposing the methods we want exposed * and adding some helper methods. * - * We inherit from QScriptable to have more thight access to the scripting - * engine. - * * setDocument _must_ be called before using any other method. This is not checked * for the sake of speed. */ -class KTEXTEDITOR_EXPORT KateScriptDocument : public QObject, protected QScriptable +class KTEXTEDITOR_EXPORT KateScriptDocument : public QObject { Q_OBJECT // Note: we have no Q_PROPERTIES due to consistency: everything is a function. public: - KateScriptDocument(QObject *parent = nullptr); + KateScriptDocument(QJSEngine *, QObject *parent = nullptr); void setDocument(KTextEditor::DocumentPrivate *document); KTextEditor::DocumentPrivate *document(); @@ -60,38 +56,45 @@ Q_INVOKABLE QString encoding(); Q_INVOKABLE QString highlightingMode(); Q_INVOKABLE QStringList embeddedHighlightingModes(); - Q_INVOKABLE QString highlightingModeAt(const KTextEditor::Cursor &pos); + Q_INVOKABLE QString highlightingModeAt(const QJSValue &pos); Q_INVOKABLE bool isModified(); Q_INVOKABLE QString text(); Q_INVOKABLE QString text(int fromLine, int fromColumn, int toLine, int toColumn); Q_INVOKABLE QString text(const KTextEditor::Cursor &from, const KTextEditor::Cursor &to); Q_INVOKABLE QString text(const KTextEditor::Range &range); + Q_INVOKABLE QString text(const QJSValue &jsrange); Q_INVOKABLE QString line(int line); Q_INVOKABLE QString wordAt(int line, int column); Q_INVOKABLE QString wordAt(const KTextEditor::Cursor &cursor); - Q_INVOKABLE KTextEditor::Range wordRangeAt(int line, int column); - Q_INVOKABLE KTextEditor::Range wordRangeAt(const KTextEditor::Cursor &cursor); + Q_INVOKABLE QJSValue wordRangeAt(int line, int column); + Q_INVOKABLE QJSValue wordRangeAt(const KTextEditor::Cursor &cursor); Q_INVOKABLE QString charAt(int line, int column); Q_INVOKABLE QString charAt(const KTextEditor::Cursor &cursor); + Q_INVOKABLE QString charAt(const QJSValue &cursor); Q_INVOKABLE QString firstChar(int line); Q_INVOKABLE QString lastChar(int line); Q_INVOKABLE bool isSpace(int line, int column); Q_INVOKABLE bool isSpace(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool isSpace(const QJSValue &jscursor); Q_INVOKABLE bool matchesAt(int line, int column, const QString &s); Q_INVOKABLE bool matchesAt(const KTextEditor::Cursor &cursor, const QString &s); + Q_INVOKABLE bool matchesAt(const QJSValue &cursor, const QString &s); Q_INVOKABLE bool setText(const QString &s); Q_INVOKABLE bool clear(); Q_INVOKABLE bool truncate(int line, int column); Q_INVOKABLE bool truncate(const KTextEditor::Cursor &cursor); Q_INVOKABLE bool insertText(int line, int column, const QString &s); Q_INVOKABLE bool insertText(const KTextEditor::Cursor &cursor, const QString &s); + Q_INVOKABLE bool insertText(const QJSValue &jscursor, const QString &s); Q_INVOKABLE bool removeText(int fromLine, int fromColumn, int toLine, int toColumn); Q_INVOKABLE bool removeText(const KTextEditor::Cursor &from, const KTextEditor::Cursor &to); Q_INVOKABLE bool removeText(const KTextEditor::Range &range); + Q_INVOKABLE bool removeText(const QJSValue &range); Q_INVOKABLE bool insertLine(int line, const QString &s); Q_INVOKABLE bool removeLine(int line); Q_INVOKABLE bool wrapLine(int line, int column); Q_INVOKABLE bool wrapLine(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool wrapLine(const QJSValue &cursor); Q_INVOKABLE void joinLines(int startLine, int endLine); Q_INVOKABLE int lines(); Q_INVOKABLE bool isLineModified(int line); @@ -117,8 +120,8 @@ Q_INVOKABLE QString commentStart(int attribute); Q_INVOKABLE QString commentEnd(int attribute); - Q_INVOKABLE KTextEditor::Range documentRange(); - Q_INVOKABLE KTextEditor::Cursor documentEnd(); + Q_INVOKABLE QJSValue documentRange(); + Q_INVOKABLE QJSValue documentEnd(); Q_INVOKABLE bool isValidTextPosition(int line, int column); Q_INVOKABLE bool isValidTextPosition(const KTextEditor::Cursor& cursor); @@ -139,12 +142,14 @@ */ Q_INVOKABLE QString attributeName(int line, int column); Q_INVOKABLE QString attributeName(const KTextEditor::Cursor &cursor); + Q_INVOKABLE QString attributeName(const QJSValue &jscursor); /** * Return true is the name of the syntax attribute equals @p name. */ Q_INVOKABLE bool isAttributeName(int line, int column, const QString &name); Q_INVOKABLE bool isAttributeName(const KTextEditor::Cursor &cursor, const QString &name); + Q_INVOKABLE bool isAttributeName(const QJSValue &cursor, const QString &name); Q_INVOKABLE QString variable(const QString &s); Q_INVOKABLE void setVariable(const QString &s, const QString &v); @@ -154,40 +159,53 @@ Q_INVOKABLE int lastVirtualColumn(int line); Q_INVOKABLE int toVirtualColumn(int line, int column); Q_INVOKABLE int toVirtualColumn(const KTextEditor::Cursor &cursor); + Q_INVOKABLE int toVirtualColumn(const QJSValue &cursor); Q_INVOKABLE KTextEditor::Cursor toVirtualCursor(const KTextEditor::Cursor &cursor); Q_INVOKABLE int fromVirtualColumn(int line, int virtualColumn); Q_INVOKABLE int fromVirtualColumn(const KTextEditor::Cursor &virtualCursor); Q_INVOKABLE KTextEditor::Cursor fromVirtualCursor(const KTextEditor::Cursor &virtualCursor); - Q_INVOKABLE KTextEditor::Cursor anchor(int line, int column, QChar character); + KTextEditor::Cursor anchorInternal(int line, int column, QChar character); Q_INVOKABLE KTextEditor::Cursor anchor(const KTextEditor::Cursor &cursor, QChar character); - Q_INVOKABLE KTextEditor::Cursor rfind(int line, int column, const QString &text, int attribute = -1); + Q_INVOKABLE QJSValue anchor(int line, int column, QChar character); + Q_INVOKABLE QJSValue anchor(const QJSValue &cursor, QChar character); + KTextEditor::Cursor rfindInternal(int line, int column, const QString &text, int attribute = -1); Q_INVOKABLE KTextEditor::Cursor rfind(const KTextEditor::Cursor &cursor, const QString &text, int attribute = -1); + Q_INVOKABLE QJSValue rfind(int line, int column, const QString &text, int attribute = -1); + Q_INVOKABLE QJSValue rfind(const QJSValue &cursor, const QString &text, int attribute = -1); Q_INVOKABLE int defStyleNum(int line, int column); Q_INVOKABLE int defStyleNum(const KTextEditor::Cursor &cursor); Q_INVOKABLE bool isCode(int line, int column); Q_INVOKABLE bool isCode(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool isCode(const QJSValue &cursor); Q_INVOKABLE bool isComment(int line, int column); Q_INVOKABLE bool isComment(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool isComment(const QJSValue &cursor); Q_INVOKABLE bool isString(int line, int column); Q_INVOKABLE bool isString(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool isString(const QJSValue &cursor); Q_INVOKABLE bool isRegionMarker(int line, int column); Q_INVOKABLE bool isRegionMarker(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool isRegionMarker(const QJSValue &cursor); Q_INVOKABLE bool isChar(int line, int column); Q_INVOKABLE bool isChar(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool isChar(const QJSValue &cursor); Q_INVOKABLE bool isOthers(int line, int column); Q_INVOKABLE bool isOthers(const KTextEditor::Cursor &cursor); + Q_INVOKABLE bool isOthers(const QJSValue &cursor); Q_INVOKABLE bool startsWith(int line, const QString &pattern, bool skipWhiteSpaces); Q_INVOKABLE bool endsWith(int line, const QString &pattern, bool skipWhiteSpaces); Q_INVOKABLE void indent(KTextEditor::Range range, int change); + Q_INVOKABLE void indent(const QJSValue &jsrange, int change); private: bool _isCode(int defaultStyle); KTextEditor::DocumentPrivate *m_document; + QJSEngine *m_engine; }; #endif Index: src/script/katescriptdocument.cpp =================================================================== --- src/script/katescriptdocument.cpp +++ src/script/katescriptdocument.cpp @@ -26,13 +26,14 @@ #include "katehighlight.h" #include "katescript.h" #include "katepartdebug.h" +#include "scriptcursor.h" +#include "scriptrange.h" #include +#include -#include - -KateScriptDocument::KateScriptDocument(QObject *parent) - : QObject(parent), m_document(nullptr) +KateScriptDocument::KateScriptDocument(QJSEngine *engine, QObject *parent) + : QObject(parent), m_document(nullptr), m_engine(engine) { } @@ -67,6 +68,13 @@ return isCode(cursor.line(), cursor.column()); } +bool KateScriptDocument::isCode(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isCode(cursor); +} + bool KateScriptDocument::isComment(int line, int column) { return m_document->isComment(line, column); @@ -77,6 +85,13 @@ return isComment(cursor.line(), cursor.column()); } +bool KateScriptDocument::isComment(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isComment(cursor); +} + bool KateScriptDocument::isString(int line, int column) { const int defaultStyle = defStyleNum(line, column); @@ -88,6 +103,13 @@ return isString(cursor.line(), cursor.column()); } +bool KateScriptDocument::isString(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isString(cursor); +} + bool KateScriptDocument::isRegionMarker(int line, int column) { const int defaultStyle = defStyleNum(line, column); @@ -99,6 +121,13 @@ return isRegionMarker(cursor.line(), cursor.column()); } +bool KateScriptDocument::isRegionMarker(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isRegionMarker(cursor); +} + bool KateScriptDocument::isChar(int line, int column) { const int defaultStyle = defStyleNum(line, column); @@ -110,6 +139,13 @@ return isChar(cursor.line(), cursor.column()); } +bool KateScriptDocument::isChar(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isChar(cursor); +} + bool KateScriptDocument::isOthers(int line, int column) { const int defaultStyle = defStyleNum(line, column); @@ -121,6 +157,13 @@ return isOthers(cursor.line(), cursor.column()); } +bool KateScriptDocument::isOthers(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isOthers(cursor); +} + int KateScriptDocument::firstVirtualColumn(int line) { const int tabWidth = m_document->config()->tabWidth(); @@ -158,6 +201,13 @@ return toVirtualColumn(cursor.line(), cursor.column()); } +int KateScriptDocument::toVirtualColumn(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return toVirtualColumn(cursor); +} + KTextEditor::Cursor KateScriptDocument::toVirtualCursor(const KTextEditor::Cursor &cursor) { return KTextEditor::Cursor(cursor.line(), @@ -185,7 +235,7 @@ fromVirtualColumn(virtualCursor.line(), virtualCursor.column())); } -KTextEditor::Cursor KateScriptDocument::rfind(int line, int column, const QString &text, int attribute) +KTextEditor::Cursor KateScriptDocument::rfindInternal(int line, int column, const QString &text, int attribute) { KTextEditor::DocumentCursor cursor(document(), line, column); const int start = cursor.line(); @@ -223,10 +273,22 @@ KTextEditor::Cursor KateScriptDocument::rfind(const KTextEditor::Cursor &cursor, const QString &text, int attribute) { - return rfind(cursor.line(), cursor.column(), text, attribute); + return rfindInternal(cursor.line(), cursor.column(), text, attribute); +} + +QJSValue KateScriptDocument::rfind(int line, int column, const QString &text, int attribute) +{ + return cursorToScriptValue(m_engine, rfindInternal(line, column, text, attribute)); } -KTextEditor::Cursor KateScriptDocument::anchor(int line, int column, QChar character) +QJSValue KateScriptDocument::rfind(const QJSValue &jscursor, const QString &text, int attribute) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return cursorToScriptValue(m_engine, rfind(cursor, text, attribute)); +} + +KTextEditor::Cursor KateScriptDocument::anchorInternal(int line, int column, QChar character) { QChar lc; QChar rc; @@ -284,6 +346,18 @@ KTextEditor::Cursor KateScriptDocument::anchor(const KTextEditor::Cursor &cursor, QChar character) { + return anchorInternal(cursor.line(), cursor.column(), character); +} + +QJSValue KateScriptDocument::anchor(int line, int column, QChar character) +{ + return cursorToScriptValue(m_engine, anchorInternal(line, column, character)); +} + +QJSValue KateScriptDocument::anchor(const QJSValue &jscursor, QChar character) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); return anchor(cursor.line(), cursor.column(), character); } @@ -349,8 +423,10 @@ return m_document->embeddedHighlightingModes(); } -QString KateScriptDocument::highlightingModeAt(const KTextEditor::Cursor &pos) +QString KateScriptDocument::highlightingModeAt(const QJSValue &jspos) { + KTextEditor::Cursor pos; + cursorFromScriptValue(jspos, pos); return m_document->highlightingModeAt(pos); } @@ -379,6 +455,13 @@ return m_document->text(range); } +QString KateScriptDocument::text(const QJSValue &jsrange) +{ + KTextEditor::Range range; + rangeFromScriptValue(jsrange, range); + return text(range); +} + QString KateScriptDocument::line(int line) { return m_document->line(line); @@ -386,7 +469,7 @@ QString KateScriptDocument::wordAt(int line, int column) { - return m_document->wordAt(KTextEditor::Cursor(line, column)); + return wordAt(KTextEditor::Cursor(line, column)); } QString KateScriptDocument::wordAt(const KTextEditor::Cursor &cursor) @@ -394,14 +477,14 @@ return m_document->wordAt(cursor); } -KTextEditor::Range KateScriptDocument::wordRangeAt(int line, int column) +QJSValue KateScriptDocument::wordRangeAt(int line, int column) { return wordRangeAt(KTextEditor::Cursor(line, column)); } -KTextEditor::Range KateScriptDocument::wordRangeAt(const KTextEditor::Cursor &cursor) +QJSValue KateScriptDocument::wordRangeAt(const KTextEditor::Cursor &cursor) { - return m_document->wordRangeAt(cursor); + return rangeToScriptValue(m_engine, m_document->wordRangeAt(cursor)); } QString KateScriptDocument::charAt(int line, int column) @@ -415,6 +498,13 @@ return c.isNull() ? QString() : QString(c); } +QString KateScriptDocument::charAt(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return charAt(cursor); +} + QString KateScriptDocument::firstChar(int line) { Kate::TextLine textLine = m_document->plainKateTextLine(line); @@ -447,6 +537,13 @@ return m_document->characterAt(cursor).isSpace(); } +bool KateScriptDocument::isSpace(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isSpace(cursor); +} + bool KateScriptDocument::matchesAt(int line, int column, const QString &s) { Kate::TextLine textLine = m_document->plainKateTextLine(line); @@ -455,9 +552,18 @@ bool KateScriptDocument::matchesAt(const KTextEditor::Cursor &cursor, const QString &s) { + return matchesAt(cursor.line(), cursor.column(), s); } +bool KateScriptDocument::matchesAt(const QJSValue &jscursor, const QString &s) +{ + + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return matchesAt(cursor, s); +} + bool KateScriptDocument::setText(const QString &s) { return m_document->setText(s); @@ -494,6 +600,13 @@ return m_document->insertText(cursor, s); } +bool KateScriptDocument::insertText(const QJSValue &jscursor, const QString &s) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return insertText(cursor, s); +} + bool KateScriptDocument::removeText(int fromLine, int fromColumn, int toLine, int toColumn) { return removeText(KTextEditor::Range(fromLine, fromColumn, toLine, toColumn)); @@ -509,6 +622,13 @@ return m_document->removeText(range); } +bool KateScriptDocument::removeText(const QJSValue &jsrange) +{ + KTextEditor::Range range; + rangeFromScriptValue(jsrange, range); + return removeText(range); +} + bool KateScriptDocument::insertLine(int line, const QString &s) { return m_document->insertLine(line, s); @@ -529,6 +649,13 @@ return wrapLine(cursor.line(), cursor.column()); } +bool KateScriptDocument::wrapLine(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return wrapLine(cursor); +} + void KateScriptDocument::joinLines(int startLine, int endLine) { m_document->joinLines(startLine, endLine); @@ -689,14 +816,14 @@ return m_document->highlight()->getCommentEnd(attribute); } -KTextEditor::Range KateScriptDocument::documentRange() +QJSValue KateScriptDocument::documentRange() { - return m_document->documentRange(); + return rangeToScriptValue(m_engine, m_document->documentRange()); } -KTextEditor::Cursor KateScriptDocument::documentEnd() +QJSValue KateScriptDocument::documentEnd() { - return m_document->documentEnd(); + return cursorToScriptValue(m_engine, m_document->documentEnd()); } int KateScriptDocument::attribute(int line, int column) @@ -736,6 +863,13 @@ return attributeName(cursor.line(), cursor.column()); } +QString KateScriptDocument::attributeName(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return attributeName(cursor); +} + bool KateScriptDocument::isAttributeName(int line, int column, const QString &name) { return name == attributeName(line, column); @@ -746,6 +880,13 @@ return isAttributeName(cursor.line(), cursor.column(), name); } +bool KateScriptDocument::isAttributeName(const QJSValue &jscursor, const QString &name) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + return isAttributeName(cursor, name); +} + QString KateScriptDocument::variable(const QString &s) { return m_document->variable(s); @@ -771,3 +912,10 @@ { m_document->indent(range, change); } + +void KateScriptDocument::indent(const QJSValue &jsrange, int change) +{ + KTextEditor::Range range; + rangeFromScriptValue(jsrange, range); + indent(range, change); +} Index: src/script/katescripthelpers.h =================================================================== --- src/script/katescripthelpers.h +++ src/script/katescripthelpers.h @@ -21,11 +21,11 @@ #ifndef KATE_SCRIPTHELPERS_H #define KATE_SCRIPTHELPERS_H -#include +#include +#include #include -class QScriptEngine; -class QScriptContext; +class QJSEngine; namespace Kate { @@ -36,15 +36,24 @@ /** read complete file contents, helper */ KTEXTEDITOR_EXPORT bool readFile(const QString &sourceUrl, QString &sourceCode); -KTEXTEDITOR_EXPORT QScriptValue read(QScriptContext *context, QScriptEngine *engine); -KTEXTEDITOR_EXPORT QScriptValue require(QScriptContext *context, QScriptEngine *engine); -KTEXTEDITOR_EXPORT QScriptValue debug(QScriptContext *context, QScriptEngine *engine); -KTEXTEDITOR_EXPORT QScriptValue i18n(QScriptContext *context, QScriptEngine *engine); -KTEXTEDITOR_EXPORT QScriptValue i18nc(QScriptContext *context, QScriptEngine *engine); -KTEXTEDITOR_EXPORT QScriptValue i18np(QScriptContext *context, QScriptEngine *engine); -KTEXTEDITOR_EXPORT QScriptValue i18ncp(QScriptContext *context, QScriptEngine *engine); -} -} +} // namespace Script + +class KTEXTEDITOR_EXPORT ScriptHelper : public QObject { + Q_OBJECT + QJSEngine *m_engine; +public: + ScriptHelper(QJSEngine *engine) : m_engine(engine) {} + Q_INVOKABLE QString read(const QString &file); + Q_INVOKABLE void require(const QString &file); + Q_INVOKABLE void debug(const QString &msg); + Q_INVOKABLE QString _i18n(const QString &msg); + Q_INVOKABLE QString _i18nc(const QString &textContext, const QString &text); + Q_INVOKABLE QString _i18np(const QString &trSingular, const QString &trPlural, int number); + Q_INVOKABLE QString _i18ncp(const QString &trContext, const QString &trSingular, + const QString &trPlural, int number = 0); +}; + +} // namespace Kate #endif Index: src/script/katescripthelpers.cpp =================================================================== --- src/script/katescripthelpers.cpp +++ src/script/katescripthelpers.cpp @@ -33,12 +33,13 @@ #include -#include -#include -#include +#include +#include #include #include +#include + #include namespace Kate @@ -63,18 +64,22 @@ return true; } -QScriptValue read(QScriptContext *context, QScriptEngine *) +} // namespace Script + +QString ScriptHelper::read(const QString &file) { + QList files; + files << file; /** * just search for all given files and read them all */ QString fullContent; - for (int i = 0; i < context->argumentCount(); ++i) { + for (int i = 0; i < files.count(); ++i) { /** * get full name of file * skip on errors */ - const QString name = context->argument(i).toString(); + const QString name = files[i]; QString fullName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("katepart5/script/files/") + name); if (fullName.isEmpty()) { @@ -91,7 +96,7 @@ * skip non-existing files */ QString content; - if (!readFile(fullName, content)) { + if (!Script::readFile(fullName, content)) { continue; } @@ -104,20 +109,22 @@ /** * return full content */ - return QScriptValue(fullContent); + return fullContent; } -QScriptValue require(QScriptContext *context, QScriptEngine *engine) +void ScriptHelper::require(const QString &file) { + QStringList files; + files << file; /** * just search for all given scripts and eval them */ - for (int i = 0; i < context->argumentCount(); ++i) { + for (int i = 0; i < files.count(); ++i) { /** * get full name of file * skip on errors */ - const QString name = context->argument(i).toString(); + const QString name = files[i]; QString fullName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("katepart5/script/libraries/") + name); if (fullName.isEmpty()) { @@ -132,7 +139,7 @@ /** * check include guard */ - QScriptValue require_guard = engine->globalObject().property(QStringLiteral("require_guard")); + QJSValue require_guard = m_engine->globalObject().property(QStringLiteral("require_guard")); if (require_guard.property(fullName).toBool()) { continue; } @@ -142,198 +149,81 @@ * skip non-existing files */ QString code; - if (!readFile(fullName, code)) { + if (!Script::readFile(fullName, code)) { continue; } /** - * fixup QScriptContext - * else the nested evaluate will not work :/ - * see http://www.qtcentre.org/threads/31027-QtScript-nesting-with-include-imports-or-spawned-script-engines - * http://www.qtcentre.org/threads/20432-Can-I-include-a-script-from-script - */ - QScriptContext *context = engine->currentContext(); - QScriptContext *parent = context->parentContext(); - if (parent) { - context->setActivationObject(context->parentContext()->activationObject()); - context->setThisObject(context->parentContext()->thisObject()); - } - - /** * eval in current script engine */ - engine->evaluate(code, fullName); + QJSValue val = m_engine->evaluate(code, fullName); + if (val.isError()) + qWarning() << "error evaluating" << fullName << val.toString(); /** * set include guard */ - require_guard.setProperty(fullName, QScriptValue(true)); + require_guard.setProperty(fullName, QJSValue(true)); } - - /** - * no return value - */ - return engine->nullValue(); } -QScriptValue debug(QScriptContext *context, QScriptEngine *engine) +void ScriptHelper::debug(const QString &message) { - QStringList message; - for (int i = 0; i < context->argumentCount(); ++i) { - message << context->argument(i).toString(); - } // debug in blue to distance from other debug output if necessary - std::cerr << "\033[31m" << qPrintable(message.join(QLatin1Char(' '))) << "\033[0m\n"; - return engine->nullValue(); + std::cerr << "\033[31m" << qPrintable(message) << "\033[0m\n"; } //BEGIN code adapted from kdelibs/kross/modules/translation.cpp /// helper function to do the substitution from QtScript > QVariant > real values -KLocalizedString substituteArguments(const KLocalizedString &kls, const QVariantList &arguments, int max = 99) -{ - KLocalizedString ls = kls; - int cnt = qMin(arguments.count(), max); // QString supports max 99 - for (int i = 0; i < cnt; ++i) { - QVariant arg = arguments[i]; - switch (arg.type()) { - case QVariant::Int: ls = ls.subs(arg.toInt()); break; - case QVariant::UInt: ls = ls.subs(arg.toUInt()); break; - case QVariant::LongLong: ls = ls.subs(arg.toLongLong()); break; - case QVariant::ULongLong: ls = ls.subs(arg.toULongLong()); break; - case QVariant::Double: ls = ls.subs(arg.toDouble()); break; - default: ls = ls.subs(arg.toString()); break; - } - } - return ls; -} +//KLocalizedString substituteArguments(const KLocalizedString &kls, const QVariantList &arguments, int max = 99) +//{ +// KLocalizedString ls = kls; +// int cnt = qMin(arguments.count(), max); // QString supports max 99 +// for (int i = 0; i < cnt; ++i) { +// QVariant arg = arguments[i]; +// switch (arg.type()) { +// case QVariant::Int: ls = ls.subs(arg.toInt()); break; +// case QVariant::UInt: ls = ls.subs(arg.toUInt()); break; +// case QVariant::LongLong: ls = ls.subs(arg.toLongLong()); break; +// case QVariant::ULongLong: ls = ls.subs(arg.toULongLong()); break; +// case QVariant::Double: ls = ls.subs(arg.toDouble()); break; +// default: ls = ls.subs(arg.toString()); break; +// } +// } +// return ls; +//} /// i18n("text", arguments [optional]) -QScriptValue i18n(QScriptContext *context, QScriptEngine *engine) +QString ScriptHelper::_i18n(const QString &text) { - Q_UNUSED(engine) - QString text; - QVariantList args; - const int argCount = context->argumentCount(); - - if (argCount == 0) { - qCWarning(LOG_KTE) << "wrong usage of i18n:" << context->backtrace().join(QStringLiteral("\n\t")); - } - - if (argCount > 0) { - text = context->argument(0).toString(); - } - - for (int i = 1; i < argCount; ++i) { - args << context->argument(i).toVariant(); - } - - KLocalizedString ls = ki18n(text.toUtf8().data()); - return substituteArguments(ls, args).toString(); + KLocalizedString ls = ki18n(text.toUtf8().constData()); + return ls.toString(); //substituteArguments(ls, args).toString(); } /// i18nc("context", "text", arguments [optional]) -QScriptValue i18nc(QScriptContext *context, QScriptEngine *engine) +QString ScriptHelper::_i18nc(const QString &textContext, const QString &text) { - Q_UNUSED(engine) - QString text; - QString textContext; - QVariantList args; - const int argCount = context->argumentCount(); - - if (argCount < 2) { - qCWarning(LOG_KTE) << "wrong usage of i18nc:" << context->backtrace().join(QStringLiteral("\n\t")); - } - - if (argCount > 0) { - textContext = context->argument(0).toString(); - } - - if (argCount > 1) { - text = context->argument(1).toString(); - } - - for (int i = 2; i < argCount; ++i) { - args << context->argument(i).toVariant(); - } - - KLocalizedString ls = ki18nc(textContext.toUtf8().data(), text.toUtf8().data()); - return substituteArguments(ls, args).toString(); + KLocalizedString ls = ki18nc(textContext.toUtf8().constData(), text.toUtf8().constData()); + return ls.toString(); //substituteArguments(ls, args).toString(); } /// i18np("singular", "plural", number, arguments [optional]) -QScriptValue i18np(QScriptContext *context, QScriptEngine *engine) +QString ScriptHelper::_i18np(const QString &trSingular, const QString &trPlural, int number) { - Q_UNUSED(engine) - QString trSingular; - QString trPlural; - int number = 0; - QVariantList args; - const int argCount = context->argumentCount(); - - if (argCount < 3) { - qCWarning(LOG_KTE) << "wrong usage of i18np:" << context->backtrace().join(QStringLiteral("\n\t")); - } - - if (argCount > 0) { - trSingular = context->argument(0).toString(); - } - - if (argCount > 1) { - trPlural = context->argument(1).toString(); - } - - if (argCount > 2) { - number = context->argument(2).toInt32(); - } - - for (int i = 3; i < argCount; ++i) { - args << context->argument(i).toVariant(); - } - - KLocalizedString ls = ki18np(trSingular.toUtf8().data(), trPlural.toUtf8().data()).subs(number); - return substituteArguments(ls, args, 98).toString(); + KLocalizedString ls = ki18np(trSingular.toUtf8().constData(), trPlural.toUtf8().constData()).subs(number); + return ls.toString(); //substituteArguments(ls, args, 98).toString(); } /// i18ncp("context", "singular", "plural", number, arguments [optional]) -QScriptValue i18ncp(QScriptContext *context, QScriptEngine *engine) +QString ScriptHelper::_i18ncp( + const QString &trContext, const QString &trSingular, + const QString &trPlural, int number) { - Q_UNUSED(engine) - QString trContext; - QString trSingular; - QString trPlural; - int number = 0; - QVariantList args; - const int argCount = context->argumentCount(); - - if (argCount < 4) { - qCWarning(LOG_KTE) << "wrong usage of i18ncp:" << context->backtrace().join(QStringLiteral("\n\t")); - } - - if (argCount > 0) { - trContext = context->argument(0).toString(); - } - - if (argCount > 1) { - trSingular = context->argument(1).toString(); - } - - if (argCount > 2) { - trPlural = context->argument(2).toString(); - } - - if (argCount > 3) { - number = context->argument(3).toInt32(); - } - - for (int i = 4; i < argCount; ++i) { - args << context->argument(i).toVariant(); - } - KLocalizedString ls = ki18ncp(trContext.toUtf8().data(), trSingular.toUtf8().data(), trPlural.toUtf8().data()).subs(number); - return substituteArguments(ls, args, 98).toString(); + return ls.toString(); // substituteArguments(ls, args, 98).toString(); } + //END code adapted from kdelibs/kross/modules/translation.cpp -} -} +} // namespace kate Index: src/script/katescriptview.h =================================================================== --- src/script/katescriptview.h +++ src/script/katescriptview.h @@ -21,7 +21,7 @@ #define KATE_SCRIPT_VIEW_H #include -#include +#include #include @@ -29,51 +29,51 @@ #include namespace KTextEditor { class ViewPrivate; } - +class QJSEngine; /** * Thinish wrapping around KTextEditor::ViewPrivate, exposing the methods we want exposed * and adding some helper methods. * - * We inherit from QScriptable to have more thight access to the scripting - * engine. - * * setView _must_ be called before using any other method. This is not checked * for the sake of speed. */ -class KTEXTEDITOR_EXPORT KateScriptView : public QObject, protected QScriptable +class KTEXTEDITOR_EXPORT KateScriptView : public QObject { /// Properties are accessible with a nicer syntax from JavaScript Q_OBJECT public: - KateScriptView(QObject *parent = nullptr); + KateScriptView(QJSEngine *, QObject *parent = nullptr); void setView(KTextEditor::ViewPrivate *view); KTextEditor::ViewPrivate *view(); - Q_INVOKABLE KTextEditor::Cursor cursorPosition(); + Q_INVOKABLE QJSValue cursorPosition(); /** * Set the cursor position in the view. * @since 4.4 */ Q_INVOKABLE void setCursorPosition(int line, int column); Q_INVOKABLE void setCursorPosition(const KTextEditor::Cursor &cursor); + Q_INVOKABLE void setCursorPosition(const QJSValue &cursor); - Q_INVOKABLE KTextEditor::Cursor virtualCursorPosition(); + Q_INVOKABLE QJSValue virtualCursorPosition(); Q_INVOKABLE void setVirtualCursorPosition(int line, int column); Q_INVOKABLE void setVirtualCursorPosition(const KTextEditor::Cursor &cursor); + Q_INVOKABLE void setVirtualCursorPosition(const QJSValue &cursor); Q_INVOKABLE QString selectedText(); Q_INVOKABLE bool hasSelection(); - Q_INVOKABLE KTextEditor::Range selection(); - Q_INVOKABLE void setSelection(const KTextEditor::Range &range); + Q_INVOKABLE QJSValue selection(); + Q_INVOKABLE void setSelection(const QJSValue &range); Q_INVOKABLE void removeSelectedText(); Q_INVOKABLE void selectAll(); Q_INVOKABLE void clearSelection(); - Q_INVOKABLE void align(const KTextEditor::Range &range); + Q_INVOKABLE void align(const QJSValue &range); private: KTextEditor::ViewPrivate *m_view; + QJSEngine *m_engine; }; #endif Index: src/script/katescriptview.cpp =================================================================== --- src/script/katescriptview.cpp +++ src/script/katescriptview.cpp @@ -23,9 +23,13 @@ #include "kateview.h" #include "katerenderer.h" #include "katescript.h" +#include "scriptcursor.h" +#include "scriptrange.h" -KateScriptView::KateScriptView(QObject *parent) - : QObject(parent), m_view(nullptr) +#include + +KateScriptView::KateScriptView(QJSEngine *engine, QObject *parent) + : QObject(parent), m_view(nullptr), m_engine(engine) { } @@ -39,9 +43,9 @@ return m_view; } -KTextEditor::Cursor KateScriptView::cursorPosition() +QJSValue KateScriptView::cursorPosition() { - return m_view->cursorPosition(); + return cursorToScriptValue(m_engine, m_view->cursorPosition()); } void KateScriptView::setCursorPosition(int line, int column) @@ -55,9 +59,16 @@ m_view->setCursorPosition(cursor); } -KTextEditor::Cursor KateScriptView::virtualCursorPosition() +void KateScriptView::setCursorPosition(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + setCursorPosition(cursor); +} + +QJSValue KateScriptView::virtualCursorPosition() { - return m_view->cursorPositionVirtual(); + return cursorToScriptValue(m_engine, m_view->cursorPositionVirtual()); } void KateScriptView::setVirtualCursorPosition(int line, int column) @@ -70,6 +81,13 @@ m_view->setCursorPositionVisual(cursor); } +void KateScriptView::setVirtualCursorPosition(const QJSValue &jscursor) +{ + KTextEditor::Cursor cursor; + cursorFromScriptValue(jscursor, cursor); + setVirtualCursorPosition(cursor); +} + QString KateScriptView::selectedText() { return m_view->selectionText(); @@ -80,13 +98,15 @@ return m_view->selection(); } -KTextEditor::Range KateScriptView::selection() +QJSValue KateScriptView::selection() { - return m_view->selectionRange(); + return rangeToScriptValue(m_engine, m_view->selectionRange()); } -void KateScriptView::setSelection(const KTextEditor::Range &range) +void KateScriptView::setSelection(const QJSValue &jsrange) { + KTextEditor::Range range; + rangeFromScriptValue(jsrange, range); m_view->setSelection(range); } @@ -105,7 +125,9 @@ m_view->clearSelection(); } -void KateScriptView::align(const KTextEditor::Range &range) +void KateScriptView::align(const QJSValue &jsrange) { + KTextEditor::Range range; + rangeFromScriptValue(jsrange, range); m_view->doc()->align (m_view, range); } Index: src/script/scriptcursor.h =================================================================== --- /dev/null +++ src/script/scriptcursor.h @@ -0,0 +1,44 @@ +/* This file is part of the KDE project + Copyright (C) 2017 Allan Sandfeld Jensen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KTEXTEDITOR_SCRIPTCURSOR_H +#define KTEXTEDITOR_SCRIPTCURSOR_H + +#include +#include + +#include "ktexteditor/cursor.h" + +inline QJSValue cursorToScriptValue(QJSEngine *engine, const KTextEditor::Cursor &cursor) +{ + QString code = QStringLiteral("new Cursor(%1, %2);").arg(cursor.line()).arg(cursor.column()); + QJSValue result = engine->evaluate(code); + Q_ASSERT(!result.isError()); + return result; +} + +inline void cursorFromScriptValue(const QJSValue &obj, KTextEditor::Cursor &cursor) +{ + QJSValue line = obj.property(QStringLiteral("line")); + QJSValue column = obj.property(QStringLiteral("column")); + Q_ASSERT(!line.isError() && !column.isError()); + cursor.setPosition(line.toInt(), column.toInt()); +} + +#endif Index: src/script/scriptrange.h =================================================================== --- /dev/null +++ src/script/scriptrange.h @@ -0,0 +1,47 @@ +/* This file is part of the KDE project + Copyright (C) 2017 Allan Sandfeld Jensen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KTEXTEDITOR_SCRIPTRANGE_H +#define KTEXTEDITOR_SCRIPTRANGE_H + +#include +#include + +#include "ktexteditor/range.h" + +inline QJSValue rangeToScriptValue(QJSEngine *engine, const KTextEditor::Range &range) +{ + QString code = QStringLiteral("new Range(%1, %2, %3, %4);").arg(range.start().line()) + .arg(range.start().column()) + .arg(range.end().line()) + .arg(range.end().column()); + QJSValue result = engine->evaluate(code); + Q_ASSERT(!result.isError()); + return result; +} + +inline void rangeFromScriptValue(const QJSValue &obj, KTextEditor::Range &range) +{ + range.setRange(KTextEditor::Cursor(obj.property(QStringLiteral("start")).property(QStringLiteral("line")).toInt(), + obj.property(QStringLiteral("start")).property(QStringLiteral("column")).toInt()), + KTextEditor::Cursor(obj.property(QStringLiteral("end")).property(QStringLiteral("line")).toInt(), + obj.property(QStringLiteral("end")).property(QStringLiteral("column")).toInt())); +} + +#endif Index: src/utils/katetemplatehandler.cpp =================================================================== --- src/utils/katetemplatehandler.cpp +++ src/utils/katetemplatehandler.cpp @@ -549,7 +549,8 @@ // only editable fields are of interest to the scripts continue; } - map.insert(field.identifier, QScriptValue(doc()->text(field.range->toRange()))); + QString text = doc()->text(field.range->toRange()); + map.insert(field.identifier, QJSValue(text)); } return map; }