File indexing completed on 2024-07-21 12:13:48

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2001, 2003 Peter Kelly <pmk@post.com>
0004     SPDX-FileCopyrightText: 2003, 2004 Stephan Kulow <coolo@kde.org>
0005     SPDX-FileCopyrightText: 2004 Dirk Mueller <mueller@kde.org>
0006     SPDX-FileCopyrightText: 2006, 2007 Leo Savernik <l.savernik@aon.at>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 // BEGIN Includes
0012 #include "testutils.h"
0013 
0014 #include "kateconfig.h"
0015 #include "katedocument.h"
0016 #include "katescripthelpers.h"
0017 #include "kateview.h"
0018 #include "ktexteditor/cursor.h"
0019 #include "ktexteditor/range.h"
0020 
0021 #include <QObject>
0022 #include <QQmlEngine>
0023 #include <QTest>
0024 
0025 // END Includes
0026 
0027 // BEGIN TestScriptEnv
0028 
0029 TestScriptEnv::TestScriptEnv(KTextEditor::DocumentPrivate *part, bool &cflag)
0030     : m_engine(nullptr)
0031     , m_viewObj(nullptr)
0032     , m_docObj(nullptr)
0033     , m_output(nullptr)
0034 {
0035     m_engine = new QJSEngine(this);
0036 
0037     // export read & require function and add the require guard object
0038     QJSValue functions = m_engine->newQObject(new Kate::ScriptHelper(m_engine));
0039     m_engine->globalObject().setProperty(QStringLiteral("functions"), functions);
0040     m_engine->globalObject().setProperty(QStringLiteral("read"), functions.property(QStringLiteral("read")));
0041     m_engine->globalObject().setProperty(QStringLiteral("require"), functions.property(QStringLiteral("require")));
0042     m_engine->globalObject().setProperty(QStringLiteral("require_guard"), m_engine->newObject());
0043 
0044     // export debug function
0045     m_engine->globalObject().setProperty(QStringLiteral("debug"), functions.property(QStringLiteral("debug")));
0046 
0047     // export translation functions
0048     m_engine->globalObject().setProperty(QStringLiteral("i18n"), functions.property(QStringLiteral("_i18n")));
0049     m_engine->globalObject().setProperty(QStringLiteral("i18nc"), functions.property(QStringLiteral("_i18nc")));
0050     m_engine->globalObject().setProperty(QStringLiteral("i18np"), functions.property(QStringLiteral("_i18np")));
0051     m_engine->globalObject().setProperty(QStringLiteral("i18ncp"), functions.property(QStringLiteral("_i18ncp")));
0052 
0053     KTextEditor::ViewPrivate *view = qobject_cast<KTextEditor::ViewPrivate *>(part->widget());
0054 
0055     m_viewObj = new KateViewObject(m_engine, view);
0056     QJSValue sv = m_engine->newQObject(m_viewObj);
0057 
0058     m_engine->globalObject().setProperty(QStringLiteral("view"), sv);
0059     m_engine->globalObject().setProperty(QStringLiteral("v"), sv);
0060 
0061     m_docObj = new KateDocumentObject(m_engine, view->doc());
0062     QJSValue sd = m_engine->newQObject(m_docObj);
0063 
0064     m_engine->globalObject().setProperty(QStringLiteral("document"), sd);
0065     m_engine->globalObject().setProperty(QStringLiteral("d"), sd);
0066 
0067     m_output = new OutputObject(view, cflag);
0068     QJSValue so = m_engine->newQObject(m_output);
0069 
0070     m_engine->globalObject().setProperty(QStringLiteral("output"), so);
0071     m_engine->globalObject().setProperty(QStringLiteral("out"), so);
0072     m_engine->globalObject().setProperty(QStringLiteral("o"), so);
0073 }
0074 
0075 TestScriptEnv::~TestScriptEnv()
0076 {
0077     // delete explicitly, as the parent is the KTE::Document kpart, which is
0078     // reused for all tests. Hence, we explicitly have to delete the bindings.
0079     delete m_output;
0080     m_output = nullptr;
0081     delete m_docObj;
0082     m_docObj = nullptr;
0083     delete m_viewObj;
0084     m_viewObj = nullptr;
0085 
0086     // delete this too, although this should also be automagically be freed
0087     delete m_engine;
0088     m_engine = nullptr;
0089 
0090     //   kDebug() << "deleted";
0091 }
0092 // END TestScriptEnv
0093 
0094 // BEGIN KateViewObject
0095 
0096 KateViewObject::KateViewObject(QJSEngine *engine, KTextEditor::ViewPrivate *view)
0097     : KateScriptView(engine)
0098 {
0099     setView(view);
0100 }
0101 
0102 KateViewObject::~KateViewObject()
0103 {
0104     //   kDebug() << "deleted";
0105 }
0106 
0107 // Implements a function that calls an edit function repeatedly as specified by
0108 // its first parameter (once if not specified).
0109 #define REP_CALL(func)                                                                                                                                         \
0110     void KateViewObject::func(int cnt)                                                                                                                         \
0111     {                                                                                                                                                          \
0112         while (cnt--) {                                                                                                                                        \
0113             view()->func();                                                                                                                                    \
0114         }                                                                                                                                                      \
0115     }
0116 REP_CALL(keyReturn)
0117 REP_CALL(backspace)
0118 REP_CALL(deleteWordLeft)
0119 REP_CALL(keyDelete)
0120 REP_CALL(deleteWordRight)
0121 REP_CALL(transpose)
0122 REP_CALL(cursorLeft)
0123 REP_CALL(shiftCursorLeft)
0124 REP_CALL(cursorRight)
0125 REP_CALL(shiftCursorRight)
0126 REP_CALL(wordLeft)
0127 REP_CALL(shiftWordLeft)
0128 REP_CALL(wordRight)
0129 REP_CALL(shiftWordRight)
0130 REP_CALL(home)
0131 REP_CALL(shiftHome)
0132 REP_CALL(end)
0133 REP_CALL(shiftEnd)
0134 REP_CALL(up)
0135 REP_CALL(shiftUp)
0136 REP_CALL(down)
0137 REP_CALL(shiftDown)
0138 REP_CALL(scrollUp)
0139 REP_CALL(scrollDown)
0140 REP_CALL(topOfView)
0141 REP_CALL(shiftTopOfView)
0142 REP_CALL(bottomOfView)
0143 REP_CALL(shiftBottomOfView)
0144 REP_CALL(pageUp)
0145 REP_CALL(shiftPageUp)
0146 REP_CALL(pageDown)
0147 REP_CALL(shiftPageDown)
0148 REP_CALL(top)
0149 REP_CALL(shiftTop)
0150 REP_CALL(bottom)
0151 REP_CALL(shiftBottom)
0152 REP_CALL(toMatchingBracket)
0153 REP_CALL(shiftToMatchingBracket)
0154 #undef REP_CALL
0155 
0156 void KateViewObject::type(const QString &str)
0157 {
0158     view()->doc()->typeChars(view(), str);
0159 }
0160 
0161 void KateViewObject::paste(const QString &str)
0162 {
0163     view()->doc()->paste(view(), str);
0164 }
0165 
0166 void KateViewObject::setAutoBrackets(bool enable)
0167 {
0168     view()->config()->setValue(KateViewConfig::AutoBrackets, enable);
0169 }
0170 
0171 void KateViewObject::replaceTabs(bool enable)
0172 {
0173     view()->doc()->config()->setValue(KateDocumentConfig::ReplaceTabsWithSpaces, enable);
0174 }
0175 
0176 #define ALIAS(alias, func)                                                                                                                                     \
0177     void KateViewObject::alias(int cnt)                                                                                                                        \
0178     {                                                                                                                                                          \
0179         func(cnt);                                                                                                                                             \
0180     }
0181 ALIAS(enter, keyReturn)
0182 ALIAS(cursorPrev, cursorLeft)
0183 ALIAS(left, cursorLeft)
0184 ALIAS(prev, cursorLeft)
0185 ALIAS(shiftCursorPrev, shiftCursorLeft)
0186 ALIAS(shiftLeft, shiftCursorLeft)
0187 ALIAS(shiftPrev, shiftCursorLeft)
0188 ALIAS(cursorNext, cursorRight)
0189 ALIAS(right, cursorRight)
0190 ALIAS(next, cursorRight)
0191 ALIAS(shiftCursorNext, shiftCursorRight)
0192 ALIAS(shiftRight, shiftCursorRight)
0193 ALIAS(shiftNext, shiftCursorRight)
0194 ALIAS(wordPrev, wordLeft)
0195 ALIAS(shiftWordPrev, shiftWordLeft)
0196 ALIAS(wordNext, wordRight)
0197 ALIAS(shiftWordNext, shiftWordRight)
0198 #undef ALIAS
0199 
0200 // END KateViewObject
0201 
0202 // BEGIN KateDocumentObject
0203 
0204 KateDocumentObject::KateDocumentObject(QJSEngine *engine, KTextEditor::DocumentPrivate *doc)
0205     : KateScriptDocument(engine)
0206 {
0207     setDocument(doc);
0208 }
0209 
0210 KateDocumentObject::~KateDocumentObject()
0211 {
0212     //   kDebug() << "deleted";
0213 }
0214 // END KateDocumentObject
0215 
0216 // BEGIN OutputObject
0217 OutputObject::OutputObject(KTextEditor::ViewPrivate *v, bool &cflag)
0218     : view(v)
0219     , cflag(cflag)
0220 {
0221 }
0222 
0223 OutputObject::~OutputObject()
0224 {
0225     //   kDebug() << "deleted";
0226 }
0227 
0228 void OutputObject::output(bool cp, bool ln)
0229 {
0230     QString str;
0231     //   FIXME: This is not available with QtQml, but not sure if we need it
0232     //    for (int i = 0; i < context()->argumentCount(); ++i) {
0233     //        QJSValue arg = context()->argument(i);
0234     //        str += arg.toString();
0235     //    }
0236 
0237     if (cp) {
0238         KTextEditor::Cursor c = view->cursorPosition();
0239         str += QLatin1Char('(') + QString::number(c.line()) + QLatin1Char(',') + QString::number(c.column()) + QLatin1Char(')');
0240     }
0241 
0242     if (ln) {
0243         str += QLatin1Char('\n');
0244     }
0245 
0246     view->insertText(str);
0247 
0248     cflag = true;
0249 }
0250 
0251 void OutputObject::write()
0252 {
0253     output(false, false);
0254 }
0255 
0256 void OutputObject::writeln()
0257 {
0258     output(false, true);
0259 }
0260 
0261 void OutputObject::writeLn()
0262 {
0263     output(false, true);
0264 }
0265 
0266 void OutputObject::print()
0267 {
0268     output(false, false);
0269 }
0270 
0271 void OutputObject::println()
0272 {
0273     output(false, true);
0274 }
0275 
0276 void OutputObject::printLn()
0277 {
0278     output(false, true);
0279 }
0280 
0281 void OutputObject::writeCursorPosition()
0282 {
0283     output(true, false);
0284 }
0285 
0286 void OutputObject::writeCursorPositionln()
0287 {
0288     output(true, true);
0289 }
0290 
0291 void OutputObject::cursorPosition()
0292 {
0293     output(true, false);
0294 }
0295 
0296 void OutputObject::cursorPositionln()
0297 {
0298     output(true, true);
0299 }
0300 
0301 void OutputObject::cursorPositionLn()
0302 {
0303     output(true, true);
0304 }
0305 
0306 void OutputObject::pos()
0307 {
0308     output(true, false);
0309 }
0310 
0311 void OutputObject::posln()
0312 {
0313     output(true, true);
0314 }
0315 
0316 void OutputObject::posLn()
0317 {
0318     output(true, true);
0319 }
0320 // END OutputObject
0321 
0322 #include "moc_testutils.cpp"