feat: 脚本引擎单例化;更合理的格式化参数;
This commit is contained in:
parent
7597663d76
commit
d6680e3f11
|
@ -15,7 +15,6 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
string(APPEND CMAKE_CXX_FLAGS " /utf-8")
|
string(APPEND CMAKE_CXX_FLAGS " /utf-8")
|
||||||
string(APPEND CMAKE_C_FLAGS " /utf-8")
|
string(APPEND CMAKE_C_FLAGS " /utf-8")
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit fac4d08fd0473a94d99c143c6ba6b1f9e0bd7636
|
Subproject commit ce639ebfcec47a7c74233b4bab50017cb34e615b
|
|
@ -42,7 +42,7 @@ option(WINGHEX_USE_FRAMELESS "Use borderless windows to ensure UI uniformity"
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
find_package(QT NAMES Qt6 Qt5 REQUIRED AxContainer)
|
find_package(QT NAMES Qt6 Qt5 REQUIRED AxContainer)
|
||||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED AxContainer)
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED AxContainer)
|
||||||
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-DNOMINMAX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${QT_VERSION_MAJOR} EQUAL 5)
|
if(${QT_VERSION_MAJOR} EQUAL 5)
|
||||||
|
@ -239,8 +239,6 @@ set(CLASS_SRC
|
||||||
src/class/settingmanager.cpp
|
src/class/settingmanager.cpp
|
||||||
src/class/asdebugger.h
|
src/class/asdebugger.h
|
||||||
src/class/asdebugger.cpp
|
src/class/asdebugger.cpp
|
||||||
src/class/scriptconsolemachine.h
|
|
||||||
src/class/scriptconsolemachine.cpp
|
|
||||||
src/class/angelobjstring.h
|
src/class/angelobjstring.h
|
||||||
src/class/angelobjstring.cpp
|
src/class/angelobjstring.cpp
|
||||||
src/class/scripteditortheme.h
|
src/class/scripteditortheme.h
|
||||||
|
@ -319,8 +317,6 @@ set(MODEL_SRC
|
||||||
src/model/checksummodel.cpp
|
src/model/checksummodel.cpp
|
||||||
src/model/qjsontablemodel.h
|
src/model/qjsontablemodel.h
|
||||||
src/model/qjsontablemodel.cpp
|
src/model/qjsontablemodel.cpp
|
||||||
src/model/scriptobjmodel.h
|
|
||||||
src/model/scriptobjmodel.cpp
|
|
||||||
src/model/dbgcallstackmodel.h
|
src/model/dbgcallstackmodel.h
|
||||||
src/model/dbgcallstackmodel.cpp
|
src/model/dbgcallstackmodel.cpp
|
||||||
src/model/dbgvarshowmodel.h
|
src/model/dbgvarshowmodel.h
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -24,33 +24,14 @@
|
||||||
|
|
||||||
asBuilder::asBuilder(asIScriptEngine *engine) : AsPreprocesser(engine) {}
|
asBuilder::asBuilder(asIScriptEngine *engine) : AsPreprocesser(engine) {}
|
||||||
|
|
||||||
asBuilder::~asBuilder() {
|
int asBuilder::build(asIScriptModule *module) {
|
||||||
if (module) {
|
|
||||||
module->Discard();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int asBuilder::StartNewModule(const char *moduleName) {
|
|
||||||
if (module) {
|
|
||||||
module->Discard();
|
|
||||||
}
|
|
||||||
|
|
||||||
module = engine->GetModule(moduleName, asGM_ALWAYS_CREATE);
|
|
||||||
if (module == nullptr)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
clearAll();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
asIScriptModule *asBuilder::GetModule() { return module; }
|
|
||||||
|
|
||||||
int asBuilder::Build() {
|
|
||||||
Q_ASSERT(module);
|
Q_ASSERT(module);
|
||||||
if (module == nullptr) {
|
if (module == nullptr) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module->ResetGlobalVars();
|
||||||
|
|
||||||
for (auto &mod : modifiedScripts) {
|
for (auto &mod : modifiedScripts) {
|
||||||
module->AddScriptSection(mod.section.toUtf8(), mod.script.data(),
|
module->AddScriptSection(mod.section.toUtf8(), mod.script.data(),
|
||||||
mod.script.size());
|
mod.script.size());
|
||||||
|
|
|
@ -27,19 +27,10 @@
|
||||||
class asBuilder : public AsPreprocesser {
|
class asBuilder : public AsPreprocesser {
|
||||||
public:
|
public:
|
||||||
explicit asBuilder(asIScriptEngine *engine);
|
explicit asBuilder(asIScriptEngine *engine);
|
||||||
virtual ~asBuilder();
|
|
||||||
|
|
||||||
// Start a new module
|
public:
|
||||||
virtual int StartNewModule(const char *moduleName);
|
// build the added script sections
|
||||||
|
int build(asIScriptModule *module);
|
||||||
// Build the added script sections
|
|
||||||
virtual int Build();
|
|
||||||
|
|
||||||
// Returns the current module
|
|
||||||
asIScriptModule *GetModule();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
asIScriptModule *module = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ASBUILDER_H
|
#endif // ASBUILDER_H
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "asdatabase.h"
|
#include "asdatabase.h"
|
||||||
#include "class/aspreprocesser.h"
|
#include "class/aspreprocesser.h"
|
||||||
#include "class/qascodeparser.h"
|
#include "class/qascodeparser.h"
|
||||||
|
#include "class/scriptmachine.h"
|
||||||
#include "model/codecompletionmodel.h"
|
#include "model/codecompletionmodel.h"
|
||||||
#include "wingcodeedit.h"
|
#include "wingcodeedit.h"
|
||||||
|
|
||||||
|
@ -39,10 +40,9 @@ Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, DBL_COLON_TRIGGER, ("::"))
|
||||||
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, LEFT_PARE_TRIGGER, ("("))
|
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, LEFT_PARE_TRIGGER, ("("))
|
||||||
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, SEMI_COLON_TRIGGER, (";"))
|
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, SEMI_COLON_TRIGGER, (";"))
|
||||||
|
|
||||||
AsCompletion::AsCompletion(asIScriptEngine *engine, WingCodeEdit *p)
|
AsCompletion::AsCompletion(WingCodeEdit *p)
|
||||||
: WingCompleter(p), parser(engine), _engine(engine), m_parseDocument(true) {
|
: WingCompleter(p), parser(ScriptMachine::instance().engine()),
|
||||||
Q_ASSERT(engine);
|
m_parseDocument(true) {
|
||||||
|
|
||||||
setTriggerList({*DOT_TRIGGER, *DBL_COLON_TRIGGER,
|
setTriggerList({*DOT_TRIGGER, *DBL_COLON_TRIGGER,
|
||||||
// unleash the power of call tips
|
// unleash the power of call tips
|
||||||
*LEFT_PARE_TRIGGER,
|
*LEFT_PARE_TRIGGER,
|
||||||
|
@ -157,7 +157,8 @@ void AsCompletion::processTrigger(const QString &trigger,
|
||||||
qsizetype pos = 0;
|
qsizetype pos = 0;
|
||||||
for (; p < end;) {
|
for (; p < end;) {
|
||||||
asUINT tokenLen = 0;
|
asUINT tokenLen = 0;
|
||||||
auto tt = _engine->ParseToken(p, len, &tokenLen);
|
auto tt =
|
||||||
|
ScriptMachine::instance().engine()->ParseToken(p, len, &tokenLen);
|
||||||
if (tt == asTC_WHITESPACE) {
|
if (tt == asTC_WHITESPACE) {
|
||||||
p += tokenLen;
|
p += tokenLen;
|
||||||
pos += tokenLen;
|
pos += tokenLen;
|
||||||
|
@ -292,7 +293,7 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
|
||||||
auto code = editor->toPlainText();
|
auto code = editor->toPlainText();
|
||||||
|
|
||||||
// first preprocess the code
|
// first preprocess the code
|
||||||
AsPreprocesser prepc(_engine);
|
AsPreprocesser prepc(ScriptMachine::instance().engine());
|
||||||
// TODO: set include callback
|
// TODO: set include callback
|
||||||
// prepc.setIncludeCallback();
|
// prepc.setIncludeCallback();
|
||||||
|
|
||||||
|
@ -306,7 +307,7 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
|
||||||
QList<CodeInfoTip> ret;
|
QList<CodeInfoTip> ret;
|
||||||
|
|
||||||
for (auto &d : data) {
|
for (auto &d : data) {
|
||||||
QAsCodeParser parser(_engine);
|
QAsCodeParser parser(ScriptMachine::instance().engine());
|
||||||
auto syms =
|
auto syms =
|
||||||
parser.parseAndIntell(editor->textCursor().position(), d.script);
|
parser.parseAndIntell(editor->textCursor().position(), d.script);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
class AsCompletion : public WingCompleter {
|
class AsCompletion : public WingCompleter {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit AsCompletion(asIScriptEngine *engine, WingCodeEdit *p);
|
explicit AsCompletion(WingCodeEdit *p);
|
||||||
|
|
||||||
virtual ~AsCompletion();
|
virtual ~AsCompletion();
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASDataBase parser;
|
ASDataBase parser;
|
||||||
asIScriptEngine *_engine;
|
|
||||||
bool m_parseDocument;
|
bool m_parseDocument;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
|
|
||||||
#include "control/scriptingconsole.h"
|
#include "control/scriptingconsole.h"
|
||||||
|
|
||||||
AsConsoleCompletion::AsConsoleCompletion(asIScriptEngine *engine,
|
AsConsoleCompletion::AsConsoleCompletion(ScriptingConsole *p)
|
||||||
ScriptingConsole *p)
|
: AsCompletion(p), _console(p) {
|
||||||
: AsCompletion(engine, p), _console(p) {
|
|
||||||
setParseDocument(false);
|
setParseDocument(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class ScriptingConsole;
|
||||||
class AsConsoleCompletion : public AsCompletion {
|
class AsConsoleCompletion : public AsCompletion {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit AsConsoleCompletion(asIScriptEngine *engine, ScriptingConsole *p);
|
explicit AsConsoleCompletion(ScriptingConsole *p);
|
||||||
virtual ~AsConsoleCompletion() = default;
|
virtual ~AsConsoleCompletion() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -17,6 +17,25 @@
|
||||||
|
|
||||||
#include "ascontextmgr.h"
|
#include "ascontextmgr.h"
|
||||||
|
|
||||||
|
// copy from base class
|
||||||
|
struct SContextInfo {
|
||||||
|
asUINT sleepUntil;
|
||||||
|
std::vector<asIScriptContext *> coRoutines;
|
||||||
|
asUINT currentCoRoutine;
|
||||||
|
asIScriptContext *keepCtxAfterExecution;
|
||||||
|
};
|
||||||
|
|
||||||
asContextMgr::asContextMgr() : CContextMgr() {}
|
asContextMgr::asContextMgr() : CContextMgr() {}
|
||||||
|
|
||||||
bool asContextMgr::isRunning() const { return !m_threads.empty(); }
|
bool asContextMgr::findThreadWithUserData(asPWORD index, void *data) const {
|
||||||
|
for (auto &th : m_threads) {
|
||||||
|
auto ctx = th->keepCtxAfterExecution;
|
||||||
|
if (ctx) {
|
||||||
|
auto user = ctx->GetUserData(index);
|
||||||
|
if (user == data) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ class asContextMgr : public CContextMgr {
|
||||||
public:
|
public:
|
||||||
asContextMgr();
|
asContextMgr();
|
||||||
|
|
||||||
bool isRunning() const;
|
bool findThreadWithUserData(asPWORD index, void *data) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ASCONTEXTMGR_H
|
#endif // ASCONTEXTMGR_H
|
||||||
|
|
|
@ -75,6 +75,12 @@ void asDebugger::lineCallback(asIScriptContext *ctx) {
|
||||||
if (ctx == nullptr)
|
if (ctx == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto isDbg = reinterpret_cast<asPWORD>(
|
||||||
|
ctx->GetUserData(AsUserDataType::UserData_isDbg));
|
||||||
|
if (!isDbg) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const char *file = 0;
|
const char *file = 0;
|
||||||
int col = 0;
|
int col = 0;
|
||||||
int lineNbr = ctx->GetLineNumber(0, &col, &file);
|
int lineNbr = ctx->GetLineNumber(0, &col, &file);
|
||||||
|
@ -500,6 +506,8 @@ asDebugger::GCStatistic asDebugger::gcStatistics() {
|
||||||
|
|
||||||
void asDebugger::runDebugAction(DebugAction action) { m_action = action; }
|
void asDebugger::runDebugAction(DebugAction action) { m_action = action; }
|
||||||
|
|
||||||
|
void asDebugger::resetState() { m_action = CONTINUE; }
|
||||||
|
|
||||||
void asDebugger::deleteDbgContextInfo(void *info) {
|
void asDebugger::deleteDbgContextInfo(void *info) {
|
||||||
if (info) {
|
if (info) {
|
||||||
delete reinterpret_cast<ContextDbgInfo *>(info);
|
delete reinterpret_cast<ContextDbgInfo *>(info);
|
||||||
|
|
|
@ -116,6 +116,7 @@ public:
|
||||||
void runDebugAction(DebugAction action);
|
void runDebugAction(DebugAction action);
|
||||||
|
|
||||||
DebugAction currentState() const;
|
DebugAction currentState() const;
|
||||||
|
void resetState();
|
||||||
|
|
||||||
static void deleteDbgContextInfo(void *info);
|
static void deleteDbgContextInfo(void *info);
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ QString ClangFormatManager::formatCode(const QString &codes, bool &ok) {
|
||||||
.arg(m_clangStyle)
|
.arg(m_clangStyle)
|
||||||
.arg(m_identWidth);
|
.arg(m_identWidth);
|
||||||
auto ret = runClangFormat(
|
auto ret = runClangFormat(
|
||||||
{style, QStringLiteral("--assume-filename=wing.cpp")}, codes, ok);
|
{style, QStringLiteral("--assume-filename=wing.cs")}, codes, ok);
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
return runClangFormat({}, codes, ok);
|
return runClangFormat({}, codes, ok);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "Qt-Advanced-Docking-System/src/DockAreaWidget.h"
|
#include "Qt-Advanced-Docking-System/src/DockAreaWidget.h"
|
||||||
#include "class/languagemanager.h"
|
#include "class/languagemanager.h"
|
||||||
#include "class/logger.h"
|
#include "class/logger.h"
|
||||||
|
#include "class/scriptmachine.h"
|
||||||
#include "class/settingmanager.h"
|
#include "class/settingmanager.h"
|
||||||
#include "class/skinmanager.h"
|
#include "class/skinmanager.h"
|
||||||
#include "class/wingcstruct.h"
|
#include "class/wingcstruct.h"
|
||||||
|
@ -3886,6 +3887,8 @@ void PluginSystem::loadAllPlugin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger::newLine();
|
||||||
|
|
||||||
// loading finished, delete the checking engine
|
// loading finished, delete the checking engine
|
||||||
finalizeCheckingEngine();
|
finalizeCheckingEngine();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
/*==============================================================================
|
|
||||||
** Copyright (C) 2024-2027 WingSummer
|
|
||||||
**
|
|
||||||
** This program is free software: you can redistribute it and/or modify it under
|
|
||||||
** the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
** Software Foundation, version 3.
|
|
||||||
**
|
|
||||||
** This program 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 Affero General Public License for more
|
|
||||||
** details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU Affero General Public License
|
|
||||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
** =============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scriptconsolemachine.h"
|
|
||||||
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QTextStream>
|
|
||||||
|
|
||||||
ScriptConsoleMachine::ScriptConsoleMachine(
|
|
||||||
std::function<QString(void)> &getInputFn, QObject *parent)
|
|
||||||
: ScriptMachine(getInputFn, parent) {
|
|
||||||
if (!ScriptConsoleMachine::configureEngine(engine())) {
|
|
||||||
destoryMachine();
|
|
||||||
}
|
|
||||||
if (engine()) {
|
|
||||||
_model = new ScriptObjModel(engine(), debugger(), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptConsoleMachine::~ScriptConsoleMachine() {}
|
|
||||||
|
|
||||||
bool ScriptConsoleMachine::executeCode(const QString &code) {
|
|
||||||
return execString(engine(), code);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptObjModel *ScriptConsoleMachine::model() const { return _model; }
|
|
||||||
|
|
||||||
bool ScriptConsoleMachine::configureEngine(asIScriptEngine *engine) {
|
|
||||||
_clsfn = std::bind(&ScriptConsoleMachine::onClearConsole, this);
|
|
||||||
auto r = engine->RegisterGlobalFunction(
|
|
||||||
"void clear()", asMETHOD(decltype(_clsfn), operator()),
|
|
||||||
asCALL_THISCALL_ASGLOBAL, &_clsfn);
|
|
||||||
Q_ASSERT(r >= 0);
|
|
||||||
return r >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScriptConsoleMachine::execString(asIScriptEngine *engine,
|
|
||||||
const QString &code) {
|
|
||||||
auto mod = engine->GetModule("Console", asGM_CREATE_IF_NOT_EXISTS);
|
|
||||||
if (code.startsWith(QStringLiteral("addvar "))) {
|
|
||||||
auto varcmd = code.mid(7) + QStringLiteral(";");
|
|
||||||
if (varcmd.length() == 1) {
|
|
||||||
MessageInfo info;
|
|
||||||
info.message = tr("EmptyDecl");
|
|
||||||
emit onOutput(MessageType::Error, info);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto ret = mod->CompileGlobalVar("addvar", varcmd.toUtf8(), 0) >= 0;
|
|
||||||
_model->updateData();
|
|
||||||
return ret;
|
|
||||||
} else if (code.startsWith(QStringLiteral("rmvar "))) {
|
|
||||||
if (mod == nullptr || mod->GetGlobalVarCount() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the tailing semi-colons
|
|
||||||
static QRegularExpression re(QStringLiteral(";+$"));
|
|
||||||
|
|
||||||
auto varcmd = code.mid(6).remove(re);
|
|
||||||
for (auto &var : varcmd.split(' ', Qt::SkipEmptyParts)) {
|
|
||||||
int index = mod->GetGlobalVarIndexByName(var.toUtf8());
|
|
||||||
if (index >= 0) {
|
|
||||||
mod->RemoveGlobalVar(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_model->updateData();
|
|
||||||
return true;
|
|
||||||
} else if (code.startsWith(QStringLiteral("lsfn"))) {
|
|
||||||
if (code.trimmed().length() != 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString str;
|
|
||||||
QTextStream s(&str);
|
|
||||||
asUINT n;
|
|
||||||
|
|
||||||
// List the application registered functions
|
|
||||||
s << tr("Application functions:") << Qt::endl;
|
|
||||||
for (n = 0; n < engine->GetGlobalFunctionCount(); n++) {
|
|
||||||
asIScriptFunction *func = engine->GetGlobalFunctionByIndex(n);
|
|
||||||
|
|
||||||
// Skip the functions that start with _ as these are not meant to be
|
|
||||||
// called explicitly by the user
|
|
||||||
if (func->GetName()[0] != '_')
|
|
||||||
s << QStringLiteral(" ") << func->GetDeclaration() << Qt::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// List the user functions in the module
|
|
||||||
if (mod) {
|
|
||||||
s << Qt::endl;
|
|
||||||
s << tr("User functions:") << Qt::endl;
|
|
||||||
for (n = 0; n < mod->GetFunctionCount(); n++) {
|
|
||||||
asIScriptFunction *func = mod->GetFunctionByIndex(n);
|
|
||||||
s << QStringLiteral(" ") << func->GetDeclaration() << Qt::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageInfo info;
|
|
||||||
info.message = str;
|
|
||||||
emit onOutput(MessageType::Info, info);
|
|
||||||
return true;
|
|
||||||
} else if (code.startsWith(QStringLiteral("lsvar"))) {
|
|
||||||
if (code.trimmed().length() != 5) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString str;
|
|
||||||
QTextStream s(&str);
|
|
||||||
asUINT n;
|
|
||||||
|
|
||||||
// List the application registered variables
|
|
||||||
s << tr("Application variables:") << Qt::endl;
|
|
||||||
for (n = 0; n < engine->GetGlobalPropertyCount(); n++) {
|
|
||||||
const char *name;
|
|
||||||
int typeId;
|
|
||||||
bool isConst;
|
|
||||||
engine->GetGlobalPropertyByIndex(n, &name, 0, &typeId, &isConst);
|
|
||||||
auto decl =
|
|
||||||
isConst ? QStringLiteral(" const ") : QStringLiteral(" ");
|
|
||||||
decl += engine->GetTypeDeclaration(typeId);
|
|
||||||
decl += QStringLiteral(" ");
|
|
||||||
decl += name;
|
|
||||||
s << decl << Qt::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// List the user variables in the module
|
|
||||||
if (mod) {
|
|
||||||
s << Qt::endl;
|
|
||||||
s << tr("User variables:") << Qt::endl;
|
|
||||||
for (n = 0; n < (asUINT)mod->GetGlobalVarCount(); n++) {
|
|
||||||
s << QStringLiteral(" ") << mod->GetGlobalVarDeclaration(n)
|
|
||||||
<< Qt::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageInfo info;
|
|
||||||
info.message = str;
|
|
||||||
emit onOutput(MessageType::Info, info);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return ScriptMachine::executeCode(code);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*==============================================================================
|
|
||||||
** Copyright (C) 2024-2027 WingSummer
|
|
||||||
**
|
|
||||||
** This program is free software: you can redistribute it and/or modify it under
|
|
||||||
** the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
** Software Foundation, version 3.
|
|
||||||
**
|
|
||||||
** This program 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 Affero General Public License for more
|
|
||||||
** details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU Affero General Public License
|
|
||||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
** =============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SCRIPTCONSOLEMACHINE_H
|
|
||||||
#define SCRIPTCONSOLEMACHINE_H
|
|
||||||
|
|
||||||
#include "model/scriptobjmodel.h"
|
|
||||||
#include "scriptmachine.h"
|
|
||||||
|
|
||||||
class ScriptConsoleMachine : public ScriptMachine {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ScriptConsoleMachine(std::function<QString()> &getInputFn,
|
|
||||||
QObject *parent = nullptr);
|
|
||||||
virtual ~ScriptConsoleMachine();
|
|
||||||
|
|
||||||
virtual bool executeCode(const QString &code) override;
|
|
||||||
|
|
||||||
ScriptObjModel *model() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void onClearConsole();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool configureEngine(asIScriptEngine *engine) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool execString(asIScriptEngine *engine, const QString &code);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ScriptObjModel *_model = nullptr;
|
|
||||||
|
|
||||||
std::function<void(void)> _clsfn;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SCRIPTCONSOLEMACHINE_H
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "scriptaddon/scriptregex.h"
|
#include "scriptaddon/scriptregex.h"
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QScopeGuard>
|
||||||
|
|
||||||
ScriptMachine::~ScriptMachine() {
|
ScriptMachine::~ScriptMachine() {
|
||||||
if (_ctxMgr) {
|
if (_ctxMgr) {
|
||||||
|
@ -49,94 +50,119 @@ ScriptMachine::~ScriptMachine() {
|
||||||
destoryMachine();
|
destoryMachine();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMachine::inited() { return _engine != nullptr; }
|
bool ScriptMachine::init() {
|
||||||
|
if (isInited()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ScriptMachine::isRunning() const {
|
qRegisterMetaType<MessageInfo>();
|
||||||
return _debugger->getEngine() || _ctxMgr->isRunning();
|
|
||||||
|
_engine = asCreateScriptEngine();
|
||||||
|
if (!ScriptMachine::configureEngine()) {
|
||||||
|
_engine->ShutDownAndRelease();
|
||||||
|
_engine = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the debugger hold an engine pointer that can be used by the
|
||||||
|
// callbacks
|
||||||
|
_debugger->setEngine(_engine);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
bool ScriptMachine::isInited() const { return _engine != nullptr; }
|
||||||
if (engine == nullptr) {
|
|
||||||
|
bool ScriptMachine::isRunning(ConsoleMode mode) const {
|
||||||
|
return _ctxMgr->findThreadWithUserData(
|
||||||
|
AsUserDataType::UserData_ContextMode,
|
||||||
|
reinterpret_cast<void *>(asPWORD(mode)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptMachine::configureEngine() {
|
||||||
|
if (_engine == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need utf8, the default is what we want
|
// we need utf8, the default is what we want
|
||||||
engine->SetEngineProperty(asEP_EXPAND_DEF_ARRAY_TO_TMPL, true);
|
_engine->SetEngineProperty(asEP_EXPAND_DEF_ARRAY_TO_TMPL, true);
|
||||||
engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
|
_engine->SetEngineProperty(asEP_DISALLOW_EMPTY_LIST_ELEMENTS, true);
|
||||||
engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, false);
|
_engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, false);
|
||||||
engine->SetEngineProperty(asEP_ALLOW_MULTILINE_STRINGS, false);
|
_engine->SetEngineProperty(asEP_ALLOW_MULTILINE_STRINGS, false);
|
||||||
engine->SetEngineProperty(asEP_USE_CHARACTER_LITERALS, false);
|
_engine->SetEngineProperty(asEP_USE_CHARACTER_LITERALS, false);
|
||||||
engine->SetEngineProperty(asEP_DISABLE_INTEGER_DIVISION, false);
|
_engine->SetEngineProperty(asEP_DISABLE_INTEGER_DIVISION, false);
|
||||||
engine->SetEngineProperty(asEP_PRIVATE_PROP_AS_PROTECTED, false);
|
_engine->SetEngineProperty(asEP_PRIVATE_PROP_AS_PROTECTED, false);
|
||||||
engine->SetEngineProperty(asEP_ALTER_SYNTAX_NAMED_ARGS, 0);
|
_engine->SetEngineProperty(asEP_ALTER_SYNTAX_NAMED_ARGS, 0);
|
||||||
engine->SetEngineProperty(asEP_ALLOW_UNICODE_IDENTIFIERS, true);
|
_engine->SetEngineProperty(asEP_ALLOW_UNICODE_IDENTIFIERS, true);
|
||||||
engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true); // enum class like
|
_engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE,
|
||||||
setDebugMode(false);
|
true); // enum class like
|
||||||
|
|
||||||
|
// We will only initialize the global variables once we're
|
||||||
|
// ready to execute, so disable the automatic initialization
|
||||||
|
_engine->SetEngineProperty(asEP_INIT_GLOBAL_VARS_AFTER_BUILD, false);
|
||||||
|
|
||||||
// The script compiler will send any compiler messages to the callback
|
// The script compiler will send any compiler messages to the callback
|
||||||
auto r = engine->SetMessageCallback(asFUNCTION(messageCallback), this,
|
auto r = _engine->SetMessageCallback(asFUNCTION(messageCallback), this,
|
||||||
asCALL_CDECL);
|
asCALL_CDECL);
|
||||||
Q_ASSERT(r >= 0);
|
Q_ASSERT(r >= 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine->SetContextUserDataCleanupCallback(
|
_engine->SetContextUserDataCleanupCallback(
|
||||||
&ScriptMachine::cleanUpDbgContext,
|
&ScriptMachine::cleanUpDbgContext,
|
||||||
AsUserDataType::UserData_ContextDbgInfo);
|
AsUserDataType::UserData_ContextDbgInfo);
|
||||||
|
|
||||||
engine->SetFunctionUserDataCleanupCallback(
|
_engine->SetFunctionUserDataCleanupCallback(
|
||||||
&ScriptMachine::cleanUpPluginSysIDFunction,
|
&ScriptMachine::cleanUpPluginSysIDFunction,
|
||||||
AsUserDataType::UserData_PluginFn);
|
AsUserDataType::UserData_PluginFn);
|
||||||
|
|
||||||
registerEngineAddon(engine);
|
registerEngineAddon(_engine);
|
||||||
|
|
||||||
_rtypes.resize(RegisteredType::tMAXCOUNT);
|
_rtypes.resize(RegisteredType::tMAXCOUNT);
|
||||||
_rtypes[RegisteredType::tString] =
|
_rtypes[RegisteredType::tString] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("string"));
|
q_check_ptr(_engine->GetTypeInfoByName("string"));
|
||||||
_rtypes[RegisteredType::tChar] =
|
_rtypes[RegisteredType::tChar] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("char"));
|
q_check_ptr(_engine->GetTypeInfoByName("char"));
|
||||||
_rtypes[RegisteredType::tArray] =
|
_rtypes[RegisteredType::tArray] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("array"));
|
q_check_ptr(_engine->GetTypeInfoByName("array"));
|
||||||
_rtypes[RegisteredType::tComplex] =
|
_rtypes[RegisteredType::tComplex] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("complex"));
|
q_check_ptr(_engine->GetTypeInfoByName("complex"));
|
||||||
_rtypes[RegisteredType::tWeakref] =
|
_rtypes[RegisteredType::tWeakref] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("weakref"));
|
q_check_ptr(_engine->GetTypeInfoByName("weakref"));
|
||||||
_rtypes[RegisteredType::tConstWeakref] =
|
_rtypes[RegisteredType::tConstWeakref] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("const_weakref"));
|
q_check_ptr(_engine->GetTypeInfoByName("const_weakref"));
|
||||||
_rtypes[RegisteredType::tAny] =
|
_rtypes[RegisteredType::tAny] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("any"));
|
q_check_ptr(_engine->GetTypeInfoByName("any"));
|
||||||
_rtypes[RegisteredType::tDictionary] =
|
_rtypes[RegisteredType::tDictionary] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("dictionary"));
|
q_check_ptr(_engine->GetTypeInfoByName("dictionary"));
|
||||||
_rtypes[RegisteredType::tDictionaryValue] =
|
_rtypes[RegisteredType::tDictionaryValue] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("dictionaryValue"));
|
q_check_ptr(_engine->GetTypeInfoByName("dictionaryValue"));
|
||||||
_rtypes[RegisteredType::tGrid] =
|
_rtypes[RegisteredType::tGrid] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("grid"));
|
q_check_ptr(_engine->GetTypeInfoByName("grid"));
|
||||||
_rtypes[RegisteredType::tRef] =
|
_rtypes[RegisteredType::tRef] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("ref"));
|
q_check_ptr(_engine->GetTypeInfoByName("ref"));
|
||||||
_rtypes[RegisteredType::tColor] =
|
_rtypes[RegisteredType::tColor] =
|
||||||
q_check_ptr(engine->GetTypeInfoByName("color"));
|
q_check_ptr(_engine->GetTypeInfoByName("color"));
|
||||||
|
|
||||||
// Register a couple of extra functions for the scripts
|
// Register a couple of extra functions for the scripts
|
||||||
_printFn = std::bind(&ScriptMachine::print, this, std::placeholders::_1,
|
r = _engine->RegisterGlobalFunction("void print(? &in obj)",
|
||||||
std::placeholders::_2);
|
asMETHOD(ScriptMachine, print),
|
||||||
r = engine->RegisterGlobalFunction("void print(? &in obj)",
|
asCALL_THISCALL_ASGLOBAL, this);
|
||||||
asMETHOD(decltype(_printFn), operator()),
|
|
||||||
asCALL_THISCALL_ASGLOBAL, &_printFn);
|
|
||||||
Q_ASSERT(r >= 0);
|
Q_ASSERT(r >= 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = engine->RegisterGlobalFunction(
|
r = _engine->RegisterGlobalFunction("string getInput()",
|
||||||
"string getInput()", asMETHOD(decltype(_getInputFn), operator()),
|
asMETHOD(ScriptMachine, getInput),
|
||||||
asCALL_THISCALL_ASGLOBAL, &_getInputFn);
|
asCALL_THISCALL_ASGLOBAL, this);
|
||||||
assert(r >= 0);
|
Q_ASSERT(r >= 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = engine->RegisterGlobalFunction(
|
r = _engine->RegisterGlobalFunction(
|
||||||
"int exec(string &out output, const string &in exe, "
|
"int exec(string &out output, const string &in exe, "
|
||||||
"const string &in params = \"\", int timeout = 3000)",
|
"const string &in params = \"\", int timeout = 3000)",
|
||||||
asFUNCTION(execSystemCmd), asCALL_CDECL);
|
asFUNCTION(execSystemCmd), asCALL_CDECL);
|
||||||
|
@ -147,12 +173,12 @@ bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
||||||
|
|
||||||
// Setup the context manager and register the support for co-routines
|
// Setup the context manager and register the support for co-routines
|
||||||
_ctxMgr = new asContextMgr();
|
_ctxMgr = new asContextMgr();
|
||||||
_ctxMgr->RegisterCoRoutineSupport(engine);
|
_ctxMgr->RegisterCoRoutineSupport(_engine);
|
||||||
|
|
||||||
// Tell the engine to use our context pool. This will also
|
// Tell the engine to use our context pool. This will also
|
||||||
// allow us to debug internal script calls made by the engine
|
// allow us to debug internal script calls made by the engine
|
||||||
r = engine->SetContextCallbacks(requestContextCallback,
|
r = _engine->SetContextCallbacks(requestContextCallback,
|
||||||
returnContextCallback, this);
|
returnContextCallback, this);
|
||||||
Q_ASSERT(r >= 0);
|
Q_ASSERT(r >= 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -160,8 +186,8 @@ bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
||||||
|
|
||||||
_debugger = new asDebugger(this);
|
_debugger = new asDebugger(this);
|
||||||
|
|
||||||
// Register the to-string callbacks so the user can see the contents of
|
// Register the to-string callbacks so the user can see
|
||||||
// strings
|
// the contents of strings
|
||||||
_debugger->registerToStringCallback(_rtypes[RegisteredType::tString],
|
_debugger->registerToStringCallback(_rtypes[RegisteredType::tString],
|
||||||
&AngelObjString::stringToString);
|
&AngelObjString::stringToString);
|
||||||
_debugger->registerToStringCallback(_rtypes[RegisteredType::tChar],
|
_debugger->registerToStringCallback(_rtypes[RegisteredType::tChar],
|
||||||
|
@ -175,6 +201,9 @@ bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
||||||
|
|
||||||
PluginSystem::instance().angelApi()->installAPI(this);
|
PluginSystem::instance().angelApi()->installAPI(this);
|
||||||
|
|
||||||
|
// create module for Console
|
||||||
|
_engine->GetModule("WINGCONSOLE", asGM_ALWAYS_CREATE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,34 +227,64 @@ QString ScriptMachine::getCallStack(asIScriptContext *context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::destoryMachine() {
|
void ScriptMachine::destoryMachine() {
|
||||||
|
_debugger->setEngine(nullptr);
|
||||||
_engine->ShutDownAndRelease();
|
_engine->ShutDownAndRelease();
|
||||||
_engine = nullptr;
|
_engine = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::exceptionCallback(asIScriptContext *context) {
|
void ScriptMachine::exceptionCallback(asIScriptContext *context) {
|
||||||
QString message =
|
if (context) {
|
||||||
tr("- Exception '%1' in '%2'\n")
|
ConsoleMode mode = ConsoleMode(reinterpret_cast<asPWORD>(
|
||||||
.arg(context->GetExceptionString(),
|
context->GetUserData(AsUserDataType::UserData_ContextMode)));
|
||||||
context->GetExceptionFunction()->GetDeclaration()) +
|
QString message =
|
||||||
QStringLiteral("\n") + getCallStack(context);
|
tr("- Exception '%1' in '%2'\n")
|
||||||
|
.arg(context->GetExceptionString(),
|
||||||
|
context->GetExceptionFunction()->GetDeclaration()) +
|
||||||
|
QStringLiteral("\n") + getCallStack(context);
|
||||||
|
|
||||||
const char *section;
|
const char *section;
|
||||||
MessageInfo msg;
|
MessageInfo msg;
|
||||||
msg.row = context->GetExceptionLineNumber(&msg.col, §ion);
|
msg.row = context->GetExceptionLineNumber(&msg.col, §ion);
|
||||||
msg.type = asMSGTYPE_ERROR;
|
msg.type = MessageType::Error;
|
||||||
msg.message = message;
|
msg.message = message;
|
||||||
emit onOutput(MessageType::Error, msg);
|
|
||||||
|
outputMessage(mode, msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::print(void *ref, int typeId) {
|
void ScriptMachine::print(void *ref, int typeId) {
|
||||||
MessageInfo info;
|
auto context = asGetActiveContext();
|
||||||
info.message = _debugger->toString(ref, typeId, _engine);
|
if (context) {
|
||||||
emit onOutput(MessageType::Print, info);
|
ConsoleMode mode = ConsoleMode(reinterpret_cast<asPWORD>(
|
||||||
|
context->GetUserData(AsUserDataType::UserData_ContextMode)));
|
||||||
|
|
||||||
|
MessageInfo info;
|
||||||
|
info.type = MessageType::Print;
|
||||||
|
info.message = _debugger->toString(ref, typeId, _engine);
|
||||||
|
|
||||||
|
outputMessage(mode, info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScriptMachine::getInput() {
|
QString ScriptMachine::getInput() {
|
||||||
Q_ASSERT(_getInputFn);
|
auto context = asGetActiveContext();
|
||||||
return _getInputFn();
|
if (context) {
|
||||||
|
ConsoleMode mode = ConsoleMode(reinterpret_cast<asPWORD>(
|
||||||
|
context->GetUserData(AsUserDataType::UserData_ContextMode)));
|
||||||
|
|
||||||
|
auto cbs = _regcalls.value(mode);
|
||||||
|
if (cbs.getInputFn) {
|
||||||
|
return cbs.getInputFn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMachine::outputMessage(ConsoleMode mode, const MessageInfo &info) {
|
||||||
|
auto cbs = _regcalls.value(mode);
|
||||||
|
if (cbs.printMsgFn) {
|
||||||
|
cbs.printMsgFn(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMachine::isType(asITypeInfo *tinfo, RegisteredType type) {
|
bool ScriptMachine::isType(asITypeInfo *tinfo, RegisteredType type) {
|
||||||
|
@ -257,11 +316,32 @@ int ScriptMachine::execSystemCmd(QString &out, const QString &exe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
// We will only initialize the global variables once we're
|
bool isInDebug) {
|
||||||
// ready to execute, so disable the automatic initialization
|
// Compile the script
|
||||||
_engine->SetEngineProperty(asEP_INIT_GLOBAL_VARS_AFTER_BUILD, false);
|
auto mod = createModule(mode);
|
||||||
setDebugMode(isInDebug);
|
// script-running is not allowed in interactive mode
|
||||||
|
if (mod == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScopeGuard guard([mod, mode]() {
|
||||||
|
if (mode != ConsoleMode::Interactive) {
|
||||||
|
// Before leaving, allow the engine to clean up remaining objects by
|
||||||
|
// discarding the module and doing a full garbage collection so that
|
||||||
|
// this can also be debugged if desired
|
||||||
|
mod->Discard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
asPWORD isDbg = 0;
|
||||||
|
if (mode == Scripting) {
|
||||||
|
if (isInDebug) {
|
||||||
|
isDbg = 1;
|
||||||
|
_debugger->resetState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, isDbg == 0);
|
||||||
|
|
||||||
asBuilder builder(_engine);
|
asBuilder builder(_engine);
|
||||||
for (auto &m : PluginSystem::instance().scriptMarcos()) {
|
for (auto &m : PluginSystem::instance().scriptMarcos()) {
|
||||||
|
@ -272,27 +352,17 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
builder.setPragmaCallback(&ScriptMachine::pragmaCallback, this);
|
builder.setPragmaCallback(&ScriptMachine::pragmaCallback, this);
|
||||||
builder.setIncludeCallback(&ScriptMachine::includeCallback, this);
|
builder.setIncludeCallback(&ScriptMachine::includeCallback, this);
|
||||||
|
|
||||||
// Compile the script
|
auto r = builder.loadSectionFromFile(script.toUtf8());
|
||||||
auto r = builder.StartNewModule("script");
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = builder.loadSectionFromFile(script.toUtf8());
|
r = builder.build(mod);
|
||||||
if (r < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = builder.Build();
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
info.message = tr("Script failed to build");
|
info.message = tr("Script failed to build");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
return false;
|
outputMessage(mode, info);
|
||||||
}
|
|
||||||
|
|
||||||
asIScriptModule *mod = builder.GetModule();
|
|
||||||
if (!mod) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,19 +376,17 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
if (func == nullptr) {
|
if (func == nullptr) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
info.message = tr("Cannot find 'int main()' or 'void main()'");
|
info.message = tr("Cannot find 'int main()' or 'void main()'");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the debugger hold an engine pointer that can be used by the
|
|
||||||
// callbacks
|
|
||||||
_debugger->setEngine(_engine);
|
|
||||||
|
|
||||||
if (isInDebug) {
|
if (isInDebug) {
|
||||||
// Allow the user to initialize the debugging before moving on
|
// Allow the user to initialize the debugging before moving on
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
info.message = tr("Debugging, waiting for commands.");
|
info.message = tr("Debugging, waiting for commands.");
|
||||||
emit onOutput(MessageType::Info, info);
|
info.type = MessageType::Info;
|
||||||
|
outputMessage(mode, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once we have the main function, we first need to initialize the global
|
// Once we have the main function, we first need to initialize the global
|
||||||
|
@ -328,7 +396,8 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
info.message = tr("Failed while initializing global variables");
|
info.message = tr("Failed while initializing global variables");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +405,16 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
// The context manager will request the context from the
|
// The context manager will request the context from the
|
||||||
// pool, which will automatically attach the debugger
|
// pool, which will automatically attach the debugger
|
||||||
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||||
|
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
|
AsUserDataType::UserData_isDbg);
|
||||||
|
mod->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
|
AsUserDataType::UserData_isDbg);
|
||||||
|
|
||||||
|
asPWORD umode = asPWORD(mode);
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(umode),
|
||||||
|
AsUserDataType::UserData_ContextMode);
|
||||||
|
|
||||||
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback), this,
|
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback), this,
|
||||||
asCALL_THISCALL);
|
asCALL_THISCALL);
|
||||||
|
|
||||||
|
@ -353,12 +432,14 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
info.message = tr("The script failed with an exception") +
|
info.message = tr("The script failed with an exception") +
|
||||||
QStringLiteral("\n") +
|
QStringLiteral("\n") +
|
||||||
QString::fromStdString(GetExceptionInfo(ctx, true));
|
QString::fromStdString(GetExceptionInfo(ctx, true));
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
r = -1;
|
r = -1;
|
||||||
} else if (r == asEXECUTION_ABORTED) {
|
} else if (r == asEXECUTION_ABORTED) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
info.message = tr("The script was aborted");
|
info.message = tr("The script was aborted");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
r = -1;
|
r = -1;
|
||||||
} else {
|
} else {
|
||||||
auto e = QMetaEnum::fromType<asEContextState>();
|
auto e = QMetaEnum::fromType<asEContextState>();
|
||||||
|
@ -366,7 +447,8 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
info.message = tr("The script terminated unexpectedly") +
|
info.message = tr("The script terminated unexpectedly") +
|
||||||
QStringLiteral(" (") + e.valueToKey(r) +
|
QStringLiteral(" (") + e.valueToKey(r) +
|
||||||
QStringLiteral(")");
|
QStringLiteral(")");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -379,7 +461,8 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
|
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
info.message = tr("The script exited with ") + QString::number(r);
|
info.message = tr("The script exited with ") + QString::number(r);
|
||||||
emit onOutput(MessageType::Info, info);
|
info.type = MessageType::Info;
|
||||||
|
outputMessage(mode, info);
|
||||||
|
|
||||||
// Return the context after retrieving the return value
|
// Return the context after retrieving the return value
|
||||||
_ctxMgr->DoneWithContext(ctx);
|
_ctxMgr->DoneWithContext(ctx);
|
||||||
|
@ -389,31 +472,21 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
||||||
// this can also be debugged if desired
|
// this can also be debugged if desired
|
||||||
_engine->GarbageCollect();
|
_engine->GarbageCollect();
|
||||||
|
|
||||||
// Release all contexts that have been allocated
|
if (isDbg) {
|
||||||
for (auto &ctx : _ctxPool) {
|
|
||||||
ctx->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ctxPool.clear();
|
|
||||||
|
|
||||||
// Detach debugger
|
|
||||||
Q_ASSERT(_debugger);
|
|
||||||
_debugger->setEngine(nullptr);
|
|
||||||
|
|
||||||
if (isInDebug) {
|
|
||||||
_debugger->clearBreakPoint();
|
_debugger->clearBreakPoint();
|
||||||
setDebugMode(false);
|
|
||||||
emit onDebugFinished();
|
emit onDebugFinished();
|
||||||
}
|
}
|
||||||
return r >= 0;
|
return r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::abortScript() {
|
void ScriptMachine::abortDbgScript(ConsoleMode mode) {
|
||||||
if (_debugger->getEngine()) {
|
if (_debugger->getEngine()) {
|
||||||
_debugger->runDebugAction(asDebugger::ABORT);
|
_debugger->runDebugAction(asDebugger::ABORT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptMachine::abortScript() { _ctxMgr->AbortAll(); }
|
||||||
|
|
||||||
void ScriptMachine::messageCallback(const asSMessageInfo *msg, void *param) {
|
void ScriptMachine::messageCallback(const asSMessageInfo *msg, void *param) {
|
||||||
MessageType t = MessageType::Print;
|
MessageType t = MessageType::Print;
|
||||||
switch (msg->type) {
|
switch (msg->type) {
|
||||||
|
@ -438,7 +511,8 @@ void ScriptMachine::messageCallback(const asSMessageInfo *msg, void *param) {
|
||||||
info.col = msg->col;
|
info.col = msg->col;
|
||||||
info.section = msg->section;
|
info.section = msg->section;
|
||||||
info.message = m;
|
info.message = m;
|
||||||
emit ins->onOutput(t, info);
|
info.type = t;
|
||||||
|
ins->outputMessage(ins->_curMode, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::cleanUpDbgContext(asIScriptContext *context) {
|
void ScriptMachine::cleanUpDbgContext(asIScriptContext *context) {
|
||||||
|
@ -460,17 +534,56 @@ asITypeInfo *ScriptMachine::typeInfo(RegisteredType type) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptMachine::ScriptMachine(const std::function<QString()> &getInputFn,
|
ScriptMachine &ScriptMachine::instance() {
|
||||||
QObject *parent)
|
static ScriptMachine ins;
|
||||||
: QObject(parent), _getInputFn(getInputFn) {
|
return ins;
|
||||||
Q_ASSERT(getInputFn);
|
}
|
||||||
qRegisterMetaType<MessageInfo>();
|
|
||||||
|
|
||||||
_engine = asCreateScriptEngine();
|
ScriptMachine::ScriptMachine() : QObject() {}
|
||||||
if (!ScriptMachine::configureEngine(_engine)) {
|
|
||||||
_engine->ShutDownAndRelease();
|
asIScriptModule *ScriptMachine::createModule(ConsoleMode mode) {
|
||||||
_engine = nullptr;
|
if (isModuleExists(mode)) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
switch (mode) {
|
||||||
|
case Interactive:
|
||||||
|
return nullptr;
|
||||||
|
case Scripting:
|
||||||
|
return _engine->GetModule("WINGSCRIPT", asGM_ALWAYS_CREATE);
|
||||||
|
case Background:
|
||||||
|
return _engine->GetModule("WINGSRV", asGM_ALWAYS_CREATE);
|
||||||
|
}
|
||||||
|
// should not go there
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
asIScriptModule *ScriptMachine::createModuleIfNotExist(ConsoleMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case Interactive:
|
||||||
|
return _engine->GetModule("WINGCONSOLE", asGM_ONLY_IF_EXISTS);
|
||||||
|
case Scripting:
|
||||||
|
return _engine->GetModule("WINGSCRIPT", asGM_CREATE_IF_NOT_EXISTS);
|
||||||
|
case Background:
|
||||||
|
return _engine->GetModule("WINGSRV", asGM_CREATE_IF_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// should not go there
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
asIScriptModule *ScriptMachine::module(ConsoleMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case Interactive:
|
||||||
|
return _engine->GetModule("WINGCONSOLE", asGM_ONLY_IF_EXISTS);
|
||||||
|
case Scripting:
|
||||||
|
return _engine->GetModule("WINGSCRIPT", asGM_ONLY_IF_EXISTS);
|
||||||
|
case Background:
|
||||||
|
return _engine->GetModule("WINGSRV", asGM_ONLY_IF_EXISTS);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptMachine::isModuleExists(ConsoleMode mode) {
|
||||||
|
return module(mode) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
asIScriptContext *ScriptMachine::requestContextCallback(asIScriptEngine *engine,
|
asIScriptContext *ScriptMachine::requestContextCallback(asIScriptEngine *engine,
|
||||||
|
@ -808,8 +921,6 @@ QString ScriptMachine::processTranslation(const char *content,
|
||||||
}},
|
}},
|
||||||
{QRegularExpression(QStringLiteral("^Instead found '(.*?)'")),
|
{QRegularExpression(QStringLiteral("^Instead found '(.*?)'")),
|
||||||
[machine](const QStringList &contents) -> QString {
|
[machine](const QStringList &contents) -> QString {
|
||||||
if (machine->m_insteadFoundDisabled)
|
|
||||||
return {};
|
|
||||||
return tr("Instead found '%1'").arg(contents.at(1));
|
return tr("Instead found '%1'").arg(contents.at(1));
|
||||||
}},
|
}},
|
||||||
{QRegularExpression(
|
{QRegularExpression(
|
||||||
|
@ -1588,14 +1699,6 @@ void ScriptMachine::translation() {
|
||||||
tr("Too many nested calls");
|
tr("Too many nested calls");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMachine::insteadFoundDisabled() const {
|
|
||||||
return m_insteadFoundDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptMachine::setInsteadFoundDisabled(bool newInsteadFoundDisabled) {
|
|
||||||
m_insteadFoundDisabled = newInsteadFoundDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptMachine::registerEngineAddon(asIScriptEngine *engine) {
|
void ScriptMachine::registerEngineAddon(asIScriptEngine *engine) {
|
||||||
RegisterScriptArray(engine, true);
|
RegisterScriptArray(engine, true);
|
||||||
RegisterQString(engine);
|
RegisterQString(engine);
|
||||||
|
@ -1649,6 +1752,11 @@ void ScriptMachine::registerEngineAssert(asIScriptEngine *engine) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptMachine::registerCallBack(ConsoleMode mode,
|
||||||
|
const RegCallBacks &callbacks) {
|
||||||
|
_regcalls.insert(mode, callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptMachine::scriptAssert(bool b) {
|
void ScriptMachine::scriptAssert(bool b) {
|
||||||
auto ctx = asGetActiveContext();
|
auto ctx = asGetActiveContext();
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
@ -1679,28 +1787,35 @@ void ScriptMachine::scriptThrow(const QString &msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMachine::isDebugMode() const {
|
bool ScriptMachine::isDebugMode(ConsoleMode mode) {
|
||||||
return !_engine->GetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES);
|
if (mode == Scripting) {
|
||||||
}
|
auto mod = module(mode);
|
||||||
|
if (mod) {
|
||||||
|
return reinterpret_cast<asPWORD>(
|
||||||
|
mod->GetUserData(AsUserDataType::UserData_isDbg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptMachine::setDebugMode(bool isDbg) {
|
return false;
|
||||||
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, !isDbg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asIScriptEngine *ScriptMachine::engine() const { return _engine; }
|
asIScriptEngine *ScriptMachine::engine() const { return _engine; }
|
||||||
|
|
||||||
asDebugger *ScriptMachine::debugger() const { return _debugger; }
|
asDebugger *ScriptMachine::debugger() const { return _debugger; }
|
||||||
|
|
||||||
bool ScriptMachine::executeCode(const QString &code) {
|
bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
||||||
// We will only initialize the global variables once we're
|
asIScriptModule *mod = createModuleIfNotExist(mode);
|
||||||
// ready to execute, so disable the automatic initialization
|
|
||||||
_engine->SetEngineProperty(asEP_INIT_GLOBAL_VARS_AFTER_BUILD, false);
|
|
||||||
setDebugMode(false);
|
|
||||||
|
|
||||||
asIScriptModule *mod = _engine->GetModule("Console", asGM_ONLY_IF_EXISTS);
|
QScopeGuard guard([mod, mode]() {
|
||||||
if (!mod) {
|
if (mode != ConsoleMode::Interactive) {
|
||||||
return false;
|
// Before leaving, allow the engine to clean up remaining objects by
|
||||||
}
|
// discarding the module and doing a full garbage collection so that
|
||||||
|
// this can also be debugged if desired
|
||||||
|
mod->Discard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, false);
|
||||||
|
|
||||||
// first, preparse the code
|
// first, preparse the code
|
||||||
QAsCodeParser parser(_engine);
|
QAsCodeParser parser(_engine);
|
||||||
|
@ -1717,9 +1832,10 @@ bool ScriptMachine::executeCode(const QString &code) {
|
||||||
auto r = mod->CompileFunction(nullptr, ccode, -1, 0, &func);
|
auto r = mod->CompileFunction(nullptr, ccode, -1, 0, &func);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
|
info.mode = mode;
|
||||||
info.message = tr("Script failed to build");
|
info.message = tr("Script failed to build");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
mod->Discard();
|
outputMessage(mode, info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1728,9 +1844,10 @@ bool ScriptMachine::executeCode(const QString &code) {
|
||||||
auto r = mod->Build();
|
auto r = mod->Build();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
|
info.mode = mode;
|
||||||
info.message = tr("Script failed to build");
|
info.message = tr("Script failed to build");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
mod->Discard();
|
outputMessage(mode, info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1743,21 +1860,29 @@ bool ScriptMachine::executeCode(const QString &code) {
|
||||||
|
|
||||||
if (func == nullptr) {
|
if (func == nullptr) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
|
info.mode = mode;
|
||||||
info.message = tr("Cannot find 'int main()' or 'void main()'");
|
info.message = tr("Cannot find 'int main()' or 'void main()'");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
mod->Discard();
|
outputMessage(mode, info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the debugger hold an engine pointer that can be used by the
|
|
||||||
// callbacks
|
|
||||||
_debugger->setEngine(_engine);
|
|
||||||
|
|
||||||
// Set up a context to execute the script
|
// Set up a context to execute the script
|
||||||
// The context manager will request the context from the
|
// The context manager will request the context from the
|
||||||
// pool, which will automatically attach the debugger
|
// pool, which will automatically attach the debugger
|
||||||
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||||
|
|
||||||
|
asPWORD isDbg = 0;
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
|
AsUserDataType::UserData_isDbg);
|
||||||
|
mod->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
|
AsUserDataType::UserData_isDbg);
|
||||||
|
|
||||||
|
asPWORD umode = asPWORD(mode);
|
||||||
|
ctx->SetUserData(reinterpret_cast<void *>(umode),
|
||||||
|
AsUserDataType::UserData_ContextMode);
|
||||||
|
|
||||||
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback), this,
|
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback), this,
|
||||||
asCALL_THISCALL);
|
asCALL_THISCALL);
|
||||||
|
|
||||||
|
@ -1772,15 +1897,19 @@ bool ScriptMachine::executeCode(const QString &code) {
|
||||||
if (r != asEXECUTION_FINISHED) {
|
if (r != asEXECUTION_FINISHED) {
|
||||||
if (r == asEXECUTION_EXCEPTION) {
|
if (r == asEXECUTION_EXCEPTION) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
|
info.mode = mode;
|
||||||
info.message = tr("The script failed with an exception") +
|
info.message = tr("The script failed with an exception") +
|
||||||
QStringLiteral("\n") +
|
QStringLiteral("\n") +
|
||||||
QString::fromStdString(GetExceptionInfo(ctx, true));
|
QString::fromStdString(GetExceptionInfo(ctx, true));
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
r = -1;
|
r = -1;
|
||||||
} else if (r == asEXECUTION_ABORTED) {
|
} else if (r == asEXECUTION_ABORTED) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
|
info.mode = mode;
|
||||||
info.message = tr("The script was aborted");
|
info.message = tr("The script was aborted");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
r = -1;
|
r = -1;
|
||||||
} else {
|
} else {
|
||||||
auto e = QMetaEnum::fromType<asEContextState>();
|
auto e = QMetaEnum::fromType<asEContextState>();
|
||||||
|
@ -1788,7 +1917,8 @@ bool ScriptMachine::executeCode(const QString &code) {
|
||||||
info.message = tr("The script terminated unexpectedly") +
|
info.message = tr("The script terminated unexpectedly") +
|
||||||
QStringLiteral(" (") + e.valueToKey(r) +
|
QStringLiteral(" (") + e.valueToKey(r) +
|
||||||
QStringLiteral(")");
|
QStringLiteral(")");
|
||||||
emit onOutput(MessageType::Error, info);
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
r = -1;
|
r = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1797,24 +1927,8 @@ bool ScriptMachine::executeCode(const QString &code) {
|
||||||
|
|
||||||
// Return the context after retrieving the return value
|
// Return the context after retrieving the return value
|
||||||
_ctxMgr->DoneWithContext(ctx);
|
_ctxMgr->DoneWithContext(ctx);
|
||||||
|
|
||||||
// Before leaving, allow the engine to clean up remaining objects by
|
|
||||||
// discarding the module and doing a full garbage collection so that
|
|
||||||
// this can also be debugged if desired
|
|
||||||
mod->Discard();
|
|
||||||
_engine->GarbageCollect();
|
_engine->GarbageCollect();
|
||||||
|
|
||||||
// Release all contexts that have been allocated
|
|
||||||
for (auto ctx : std::as_const(_ctxPool)) {
|
|
||||||
ctx->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ctxPool.clear();
|
|
||||||
|
|
||||||
// Detach debugger
|
|
||||||
Q_ASSERT(_debugger);
|
|
||||||
_debugger->setEngine(nullptr);
|
|
||||||
|
|
||||||
return r >= 0;
|
return r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,14 +31,23 @@ class ScriptMachine : public QObject {
|
||||||
private:
|
private:
|
||||||
using TranslateFunc = std::function<QString(const QStringList &)>;
|
using TranslateFunc = std::function<QString(const QStringList &)>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// we have three console modes
|
||||||
|
enum ConsoleMode {
|
||||||
|
Interactive, // in a shell
|
||||||
|
Scripting, // in scripting dialog
|
||||||
|
Background // run codes from other way
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class MessageType { Info, Warn, Error, Print };
|
enum class MessageType { Info, Warn, Error, Print };
|
||||||
|
|
||||||
struct MessageInfo {
|
struct MessageInfo {
|
||||||
|
ConsoleMode mode = ConsoleMode::Background;
|
||||||
QString section;
|
QString section;
|
||||||
int row = -1;
|
int row = -1;
|
||||||
int col = -1;
|
int col = -1;
|
||||||
asEMsgType type = asEMsgType::asMSGTYPE_INFORMATION;
|
MessageType type = MessageType::Info;
|
||||||
QString message;
|
QString message;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,25 +87,42 @@ public:
|
||||||
Q_ENUM(asEContextState)
|
Q_ENUM(asEContextState)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ScriptMachine(const std::function<QString()> &getInputFn,
|
struct RegCallBacks {
|
||||||
QObject *parent = nullptr);
|
std::function<QString()> getInputFn;
|
||||||
|
std::function<void()> clearFn;
|
||||||
|
std::function<void(const ScriptMachine::MessageInfo &)> printMsgFn;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ScriptMachine();
|
||||||
|
Q_DISABLE_COPY_MOVE(ScriptMachine)
|
||||||
|
|
||||||
|
public:
|
||||||
|
asIScriptModule *createModule(ConsoleMode mode);
|
||||||
|
asIScriptModule *createModuleIfNotExist(ConsoleMode mode);
|
||||||
|
asIScriptModule *module(ConsoleMode mode);
|
||||||
|
bool isModuleExists(ConsoleMode mode);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ScriptMachine &instance();
|
||||||
|
|
||||||
virtual ~ScriptMachine();
|
virtual ~ScriptMachine();
|
||||||
|
|
||||||
bool inited();
|
public:
|
||||||
|
bool init();
|
||||||
bool isRunning() const;
|
bool isInited() const;
|
||||||
|
bool isRunning(ConsoleMode mode = Scripting) const;
|
||||||
asDebugger *debugger() const;
|
|
||||||
|
|
||||||
asIScriptEngine *engine() const;
|
|
||||||
|
|
||||||
bool insteadFoundDisabled() const;
|
|
||||||
void setInsteadFoundDisabled(bool newInsteadFoundDisabled);
|
|
||||||
|
|
||||||
static void registerEngineAddon(asIScriptEngine *engine);
|
static void registerEngineAddon(asIScriptEngine *engine);
|
||||||
static void registerEngineAssert(asIScriptEngine *engine);
|
static void registerEngineAssert(asIScriptEngine *engine);
|
||||||
|
|
||||||
|
void registerCallBack(ConsoleMode mode, const RegCallBacks &callbacks);
|
||||||
|
|
||||||
|
public:
|
||||||
|
asDebugger *debugger() const;
|
||||||
|
|
||||||
|
asIScriptEngine *engine() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void scriptAssert(bool b);
|
static void scriptAssert(bool b);
|
||||||
static void scriptAssert_X(bool b, const QString &msg);
|
static void scriptAssert_X(bool b, const QString &msg);
|
||||||
|
@ -109,20 +135,19 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// debug or release?
|
// debug or release?
|
||||||
bool isDebugMode() const;
|
bool isDebugMode(ConsoleMode mode = Scripting);
|
||||||
void setDebugMode(bool isDbg);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual bool executeCode(const QString &code);
|
bool executeCode(ConsoleMode mode, const QString &code);
|
||||||
virtual bool executeScript(const QString &script, bool isInDebug = false);
|
// only scripting mode can be debugged
|
||||||
|
bool executeScript(ConsoleMode mode, const QString &script,
|
||||||
|
bool isInDebug = false);
|
||||||
|
|
||||||
|
void abortDbgScript(ConsoleMode mode);
|
||||||
void abortScript();
|
void abortScript();
|
||||||
|
|
||||||
private:
|
|
||||||
bool execute(const QString &code, bool isInDebug = false);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool configureEngine(asIScriptEngine *engine);
|
bool configureEngine();
|
||||||
|
|
||||||
QString getCallStack(asIScriptContext *context);
|
QString getCallStack(asIScriptContext *context);
|
||||||
|
|
||||||
|
@ -130,8 +155,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void print(void *ref, int typeId);
|
void print(void *ref, int typeId);
|
||||||
|
|
||||||
QString getInput();
|
QString getInput();
|
||||||
|
void outputMessage(ConsoleMode mode, const MessageInfo &info);
|
||||||
|
|
||||||
bool isType(asITypeInfo *tinfo, RegisteredType type);
|
bool isType(asITypeInfo *tinfo, RegisteredType type);
|
||||||
|
|
||||||
|
@ -166,8 +191,6 @@ private:
|
||||||
Q_DECL_UNUSED void translation();
|
Q_DECL_UNUSED void translation();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onOutput(MessageType type, const MessageInfo &message);
|
|
||||||
|
|
||||||
void onDebugFinished();
|
void onDebugFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -175,12 +198,10 @@ private:
|
||||||
asDebugger *_debugger = nullptr;
|
asDebugger *_debugger = nullptr;
|
||||||
asContextMgr *_ctxMgr = nullptr;
|
asContextMgr *_ctxMgr = nullptr;
|
||||||
QVector<asIScriptContext *> _ctxPool;
|
QVector<asIScriptContext *> _ctxPool;
|
||||||
std::function<void(void *ref, int typeId)> _printFn;
|
|
||||||
|
|
||||||
QVector<asITypeInfo *> _rtypes;
|
QVector<asITypeInfo *> _rtypes;
|
||||||
std::function<QString(void)> _getInputFn;
|
QMap<ConsoleMode, RegCallBacks> _regcalls;
|
||||||
|
ConsoleMode _curMode = ConsoleMode::Background;
|
||||||
bool m_insteadFoundDisabled = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ScriptMachine::MessageInfo)
|
Q_DECLARE_METATYPE(ScriptMachine::MessageInfo)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
|
#include "scriptmachine.h"
|
||||||
#include "settingmanager.h"
|
#include "settingmanager.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "wingmessagebox.h"
|
#include "wingmessagebox.h"
|
||||||
|
@ -50,7 +51,7 @@ ScriptManager::ScriptManager() : QObject() {
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptManager::~ScriptManager() { detach(); }
|
ScriptManager::~ScriptManager() {}
|
||||||
|
|
||||||
QStringList ScriptManager::getScriptFileNames(const QDir &dir) const {
|
QStringList ScriptManager::getScriptFileNames(const QDir &dir) const {
|
||||||
if (!dir.exists()) {
|
if (!dir.exists()) {
|
||||||
|
@ -206,14 +207,6 @@ ScriptManager::ensureDirMeta(const QFileInfo &info) {
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptManager::attach(ScriptingConsole *console) {
|
|
||||||
if (console) {
|
|
||||||
_console = console;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptManager::detach() { _console = nullptr; }
|
|
||||||
|
|
||||||
ScriptManager::ScriptDirMeta
|
ScriptManager::ScriptDirMeta
|
||||||
ScriptManager::usrDirMeta(const QString &cat) const {
|
ScriptManager::usrDirMeta(const QString &cat) const {
|
||||||
return _usrDirMetas.value(cat);
|
return _usrDirMetas.value(cat);
|
||||||
|
@ -257,13 +250,16 @@ ScriptManager::buildUpRibbonScriptRunner(RibbonButtonGroup *group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptManager::runScript(const QString &filename) {
|
void ScriptManager::runScript(const QString &filename) {
|
||||||
Q_ASSERT(_console);
|
// ScriptMachine::instance().executeScript(filename);
|
||||||
_console->setMode(ScriptingConsole::Output);
|
|
||||||
_console->stdWarn(tr("Excuting:") + filename);
|
// Q_ASSERT(_console);
|
||||||
_console->newLine();
|
// _console->setMode(ScriptingConsole::Output);
|
||||||
_console->machine()->executeScript(filename);
|
// _console->stdWarn(tr("Excuting:") + filename);
|
||||||
_console->appendCommandPrompt();
|
// _console->newLine();
|
||||||
_console->setMode(ScriptingConsole::Input);
|
// // TODO
|
||||||
|
// // _console->machine()->executeScript(filename);
|
||||||
|
// _console->appendCommandPrompt();
|
||||||
|
// _console->setMode(ScriptingConsole::Input);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ScriptManager::usrScriptsDbCats() const {
|
QStringList ScriptManager::usrScriptsDbCats() const {
|
||||||
|
|
|
@ -65,9 +65,6 @@ public:
|
||||||
void refreshUsrScriptsDbCats();
|
void refreshUsrScriptsDbCats();
|
||||||
void refreshSysScriptsDbCats();
|
void refreshSysScriptsDbCats();
|
||||||
|
|
||||||
void attach(ScriptingConsole *console);
|
|
||||||
void detach();
|
|
||||||
|
|
||||||
ScriptDirMeta usrDirMeta(const QString &cat) const;
|
ScriptDirMeta usrDirMeta(const QString &cat) const;
|
||||||
ScriptDirMeta sysDirMeta(const QString &cat) const;
|
ScriptDirMeta sysDirMeta(const QString &cat) const;
|
||||||
|
|
||||||
|
@ -133,8 +130,6 @@ private:
|
||||||
|
|
||||||
QHash<QString, ScriptDirMeta> _usrDirMetas;
|
QHash<QString, ScriptDirMeta> _usrDirMetas;
|
||||||
QHash<QString, ScriptDirMeta> _sysDirMetas;
|
QHash<QString, ScriptDirMeta> _sysDirMetas;
|
||||||
|
|
||||||
ScriptingConsole *_console = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ScriptManager::ScriptDirMeta)
|
Q_DECLARE_METATYPE(ScriptManager::ScriptDirMeta)
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "class/scriptmachine.h"
|
#include "class/scriptmachine.h"
|
||||||
#include "class/wingfiledialog.h"
|
#include "class/wingfiledialog.h"
|
||||||
#include "class/winginputdialog.h"
|
#include "class/winginputdialog.h"
|
||||||
#include "control/scriptingconsole.h"
|
|
||||||
#include "define.h"
|
#include "define.h"
|
||||||
#include "scriptaddon/scriptqdictionary.h"
|
#include "scriptaddon/scriptqdictionary.h"
|
||||||
|
|
||||||
|
@ -2084,44 +2083,35 @@ bool WingAngelAPI::execScriptCode(const WingHex::SenderInfo &sender,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_console) {
|
QTemporaryFile f;
|
||||||
QTemporaryFile f;
|
if (f.open()) {
|
||||||
if (f.open()) {
|
f.write(code.toUtf8());
|
||||||
f.write(code.toUtf8());
|
f.close();
|
||||||
f.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
_console->setMode(ScriptingConsole::Output);
|
|
||||||
_console->stdOut(getSenderHeader(sender));
|
|
||||||
auto handles = _handles;
|
|
||||||
_console->machine()->executeScript(f.fileName());
|
|
||||||
cleanUpHandles(handles);
|
|
||||||
_console->appendCommandPrompt();
|
|
||||||
_console->setMode(ScriptingConsole::Input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto handles = _handles;
|
||||||
|
ScriptMachine::instance().executeScript(ScriptMachine::Background,
|
||||||
|
f.fileName());
|
||||||
|
cleanUpHandles(handles);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingAngelAPI::execScript(const WingHex::SenderInfo &sender,
|
bool WingAngelAPI::execScript(const WingHex::SenderInfo &sender,
|
||||||
const QString &fileName) {
|
const QString &fileName) {
|
||||||
_console->setMode(ScriptingConsole::Output);
|
|
||||||
_console->stdOut(getSenderHeader(sender));
|
|
||||||
auto handles = _handles;
|
auto handles = _handles;
|
||||||
auto ret = _console->machine()->executeScript(fileName);
|
auto ret = ScriptMachine::instance().executeScript(
|
||||||
|
ScriptMachine::Background, fileName);
|
||||||
cleanUpHandles(handles);
|
cleanUpHandles(handles);
|
||||||
_console->appendCommandPrompt();
|
|
||||||
_console->setMode(ScriptingConsole::Input);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingAngelAPI::execCode(const WingHex::SenderInfo &sender,
|
bool WingAngelAPI::execCode(const WingHex::SenderInfo &sender,
|
||||||
const QString &code) {
|
const QString &code) {
|
||||||
_console->setMode(ScriptingConsole::Output);
|
auto handles = _handles;
|
||||||
_console->stdOut(getSenderHeader(sender));
|
auto ret =
|
||||||
auto ret = _console->machine()->executeCode(code);
|
ScriptMachine::instance().executeCode(ScriptMachine::Background, code);
|
||||||
_console->appendCommandPrompt();
|
cleanUpHandles(handles);
|
||||||
_console->setMode(ScriptingConsole::Input);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2175,7 +2165,7 @@ void *WingAngelAPI::vector2AsArray(const WingHex::SenderInfo &sender,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto engine = _console->machine()->engine();
|
auto engine = ScriptMachine::instance().engine();
|
||||||
auto info = engine->GetTypeInfoByDecl(typeStr.toUtf8());
|
auto info = engine->GetTypeInfoByDecl(typeStr.toUtf8());
|
||||||
if (info) {
|
if (info) {
|
||||||
auto len = content.length();
|
auto len = content.length();
|
||||||
|
@ -2197,7 +2187,7 @@ void *WingAngelAPI::list2AsArray(const WingHex::SenderInfo &sender,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto engine = _console->machine()->engine();
|
auto engine = ScriptMachine::instance().engine();
|
||||||
auto info = engine->GetTypeInfoByDecl(typeStr.toUtf8());
|
auto info = engine->GetTypeInfoByDecl(typeStr.toUtf8());
|
||||||
if (info) {
|
if (info) {
|
||||||
auto len = content.length();
|
auto len = content.length();
|
||||||
|
@ -2222,7 +2212,7 @@ void *WingAngelAPI::newAsDictionary(
|
||||||
const WingHex::SenderInfo &sender,
|
const WingHex::SenderInfo &sender,
|
||||||
const QHash<QString, QPair<MetaType, void *>> &content) {
|
const QHash<QString, QPair<MetaType, void *>> &content) {
|
||||||
Q_UNUSED(sender);
|
Q_UNUSED(sender);
|
||||||
auto engine = _console->machine()->engine();
|
auto engine = ScriptMachine::instance().engine();
|
||||||
auto dic = CScriptDictionary::Create(engine);
|
auto dic = CScriptDictionary::Create(engine);
|
||||||
|
|
||||||
for (auto p = content.constKeyValueBegin(); p != content.constKeyValueEnd();
|
for (auto p = content.constKeyValueBegin(); p != content.constKeyValueEnd();
|
||||||
|
@ -2248,11 +2238,6 @@ void WingAngelAPI::deleteAsDictionary(const WingHex::SenderInfo &sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString WingAngelAPI::getSenderHeader(const WingHex::SenderInfo &sender) {
|
|
||||||
return QStringLiteral("(") + sender.puid + QStringLiteral("::") +
|
|
||||||
sender.plgcls + QStringLiteral(") ");
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingAngelAPI::cleanUpHandles(const QVector<int> &handles) {
|
void WingAngelAPI::cleanUpHandles(const QVector<int> &handles) {
|
||||||
for (auto &h : _handles) {
|
for (auto &h : _handles) {
|
||||||
if (!handles.contains(h)) {
|
if (!handles.contains(h)) {
|
||||||
|
@ -2510,7 +2495,3 @@ bool WingAngelAPI::_DataVisual_updateTextTable(const QString &json,
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingAngelAPI::setBindingConsole(ScriptingConsole *console) {
|
|
||||||
_console = console;
|
|
||||||
}
|
|
||||||
|
|
|
@ -73,9 +73,6 @@ public:
|
||||||
void installAPI(ScriptMachine *machine);
|
void installAPI(ScriptMachine *machine);
|
||||||
void installBasicTypes(asIScriptEngine *engine);
|
void installBasicTypes(asIScriptEngine *engine);
|
||||||
|
|
||||||
void setBindingConsole(ScriptingConsole *console);
|
|
||||||
void unBindConsole();
|
|
||||||
|
|
||||||
static QString qvariantCastASString(const QMetaType::Type &id);
|
static QString qvariantCastASString(const QMetaType::Type &id);
|
||||||
|
|
||||||
static int qvariantCastASID(asIScriptEngine *engine,
|
static int qvariantCastASID(asIScriptEngine *engine,
|
||||||
|
@ -203,8 +200,6 @@ private:
|
||||||
|
|
||||||
// =========================================================
|
// =========================================================
|
||||||
|
|
||||||
QString getSenderHeader(const WingHex::SenderInfo &sender);
|
|
||||||
|
|
||||||
void cleanUpHandles(const QVector<int> &handles);
|
void cleanUpHandles(const QVector<int> &handles);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -261,8 +256,6 @@ private:
|
||||||
QVector<IWingPlugin::UNSAFE_SCFNPTR> _usfns;
|
QVector<IWingPlugin::UNSAFE_SCFNPTR> _usfns;
|
||||||
QHash<QString, QHash<QString, qsizetype>> _urfns;
|
QHash<QString, QHash<QString, qsizetype>> _urfns;
|
||||||
|
|
||||||
ScriptingConsole *_console = nullptr;
|
|
||||||
|
|
||||||
QHash<QString, QHash<QString, QList<QPair<QString, int>>>> _objs;
|
QHash<QString, QHash<QString, QList<QPair<QString, int>>>> _objs;
|
||||||
|
|
||||||
QVector<int> _handles;
|
QVector<int> _handles;
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "class/ascompletion.h"
|
#include "class/ascompletion.h"
|
||||||
#include "class/clangformatmanager.h"
|
#include "class/clangformatmanager.h"
|
||||||
|
|
||||||
ScriptEditor::ScriptEditor(asIScriptEngine *engine, QWidget *parent)
|
ScriptEditor::ScriptEditor(QWidget *parent)
|
||||||
: ads::CDockWidget(nullptr, QString(), parent) {
|
: ads::CDockWidget(nullptr, QString(), parent) {
|
||||||
this->setFeatures(
|
this->setFeatures(
|
||||||
CDockWidget::DockWidgetFocusable | CDockWidget::DockWidgetMovable |
|
CDockWidget::DockWidgetFocusable | CDockWidget::DockWidgetMovable |
|
||||||
|
@ -48,7 +48,7 @@ ScriptEditor::ScriptEditor(asIScriptEngine *engine, QWidget *parent)
|
||||||
m_editor->setSyntax(
|
m_editor->setSyntax(
|
||||||
m_editor->syntaxRepo().definitionForName("AngelScript"));
|
m_editor->syntaxRepo().definitionForName("AngelScript"));
|
||||||
|
|
||||||
auto cm = new AsCompletion(engine, m_editor);
|
auto cm = new AsCompletion(m_editor);
|
||||||
connect(cm, &AsCompletion::onFunctionTip, this,
|
connect(cm, &AsCompletion::onFunctionTip, this,
|
||||||
&ScriptEditor::onFunctionTip);
|
&ScriptEditor::onFunctionTip);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ScriptEditor : public ads::CDockWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ScriptEditor(asIScriptEngine *engine, QWidget *parent = nullptr);
|
explicit ScriptEditor(QWidget *parent = nullptr);
|
||||||
virtual ~ScriptEditor();
|
virtual ~ScriptEditor();
|
||||||
|
|
||||||
QString fileName() const;
|
QString fileName() const;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "scriptingconsole.h"
|
#include "scriptingconsole.h"
|
||||||
#include "QConsoleWidget/QConsoleIODevice.h"
|
#include "QConsoleWidget/QConsoleIODevice.h"
|
||||||
#include "class/logger.h"
|
#include "class/logger.h"
|
||||||
#include "class/scriptconsolemachine.h"
|
#include "class/scriptmachine.h"
|
||||||
#include "class/scriptsettings.h"
|
#include "class/scriptsettings.h"
|
||||||
#include "class/skinmanager.h"
|
#include "class/skinmanager.h"
|
||||||
#include "model/codecompletionmodel.h"
|
#include "model/codecompletionmodel.h"
|
||||||
|
@ -91,103 +91,16 @@ void ScriptingConsole::handleReturnKey() {
|
||||||
void ScriptingConsole::init() {
|
void ScriptingConsole::init() {
|
||||||
_getInputFn = std::bind(&ScriptingConsole::getInput, this);
|
_getInputFn = std::bind(&ScriptingConsole::getInput, this);
|
||||||
|
|
||||||
_sp = new ScriptConsoleMachine(_getInputFn, this);
|
// _sp = new ScriptConsoleMachine(_getInputFn, this);
|
||||||
connect(_sp, &ScriptConsoleMachine::onClearConsole, this,
|
// connect(_sp, &ScriptConsoleMachine::onClearConsole, this,
|
||||||
&ScriptingConsole::clear);
|
// &ScriptingConsole::clear);
|
||||||
connect(this, &ScriptingConsole::abortEvaluation, _sp,
|
// connect(this, &ScriptingConsole::abortEvaluation, _sp,
|
||||||
&ScriptConsoleMachine::abortScript);
|
// &ScriptConsoleMachine::abortScript);
|
||||||
|
|
||||||
connect(
|
|
||||||
_sp, &ScriptConsoleMachine::onOutput, this,
|
|
||||||
[=](ScriptConsoleMachine::MessageType type,
|
|
||||||
const ScriptConsoleMachine::MessageInfo &message) {
|
|
||||||
// <type, <row, col>>
|
|
||||||
static QPair<ScriptConsoleMachine::MessageType, QPair<int, int>>
|
|
||||||
lastInfo{ScriptConsoleMachine::MessageType::Print, {-1, -1}};
|
|
||||||
|
|
||||||
auto doc = this->document();
|
|
||||||
auto lastLine = doc->lastBlock();
|
|
||||||
auto isNotBlockStart = !lastLine.text().isEmpty();
|
|
||||||
|
|
||||||
auto fmtMsg = [](const ScriptConsoleMachine::MessageInfo &message)
|
|
||||||
-> QString {
|
|
||||||
if (message.row <= 0 || message.col <= 0) {
|
|
||||||
return message.message;
|
|
||||||
} else {
|
|
||||||
return QStringLiteral("(") + QString::number(message.row) +
|
|
||||||
QStringLiteral(", ") + QString::number(message.col) +
|
|
||||||
QStringLiteral(") ") + message.message;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto isMatchLast =
|
|
||||||
[](ScriptConsoleMachine::MessageType type,
|
|
||||||
const ScriptConsoleMachine::MessageInfo &message) -> bool {
|
|
||||||
if (message.row < 0 || message.col < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return lastInfo.first == type &&
|
|
||||||
lastInfo.second.first == message.row &&
|
|
||||||
lastInfo.second.second == message.col;
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case ScriptMachine::MessageType::Info:
|
|
||||||
if (isMatchLast(type, message)) {
|
|
||||||
stdOut(message.message);
|
|
||||||
} else {
|
|
||||||
if (isNotBlockStart) {
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
stdOut(tr("[Info]") + fmtMsg(message));
|
|
||||||
}
|
|
||||||
flush();
|
|
||||||
break;
|
|
||||||
case ScriptMachine::MessageType::Warn:
|
|
||||||
if (isMatchLast(type, message)) {
|
|
||||||
stdWarn(message.message);
|
|
||||||
} else {
|
|
||||||
if (isNotBlockStart) {
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
stdWarn(tr("[Warn]") + fmtMsg(message));
|
|
||||||
}
|
|
||||||
flush();
|
|
||||||
break;
|
|
||||||
case ScriptMachine::MessageType::Error:
|
|
||||||
if (isMatchLast(type, message)) {
|
|
||||||
stdErr(message.message);
|
|
||||||
} else {
|
|
||||||
if (isNotBlockStart) {
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
stdErr(tr("[Error]") + fmtMsg(message));
|
|
||||||
}
|
|
||||||
flush();
|
|
||||||
break;
|
|
||||||
case ScriptMachine::MessageType::Print:
|
|
||||||
if (lastInfo.first != type) {
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
// If running ouput in the console,
|
|
||||||
// otherwise logging.
|
|
||||||
if (_sp->isRunning()) {
|
|
||||||
stdOut(message.message);
|
|
||||||
} else {
|
|
||||||
Logger::logPrint(Logger::packDebugStr(
|
|
||||||
packUpLoggingStr(message.message)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastInfo.first = type;
|
|
||||||
lastInfo.second = qMakePair(message.row, message.col);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(this, &QConsoleWidget::consoleCommand, this,
|
connect(this, &QConsoleWidget::consoleCommand, this,
|
||||||
&ScriptingConsole::runConsoleCommand);
|
&ScriptingConsole::runConsoleCommand);
|
||||||
|
|
||||||
auto cm = new AsConsoleCompletion(_sp->engine(), this);
|
auto cm = new AsConsoleCompletion(this);
|
||||||
connect(cm, &AsCompletion::onFunctionTip, this,
|
connect(cm, &AsCompletion::onFunctionTip, this,
|
||||||
&ScriptingConsole::onFunctionTip);
|
&ScriptingConsole::onFunctionTip);
|
||||||
}
|
}
|
||||||
|
@ -201,6 +114,80 @@ void ScriptingConsole::clearConsole() {
|
||||||
|
|
||||||
void ScriptingConsole::processKeyEvent(QKeyEvent *e) { keyPressEvent(e); }
|
void ScriptingConsole::processKeyEvent(QKeyEvent *e) { keyPressEvent(e); }
|
||||||
|
|
||||||
|
void ScriptingConsole::onOutput(const ScriptMachine::MessageInfo &message) {
|
||||||
|
// <type, <row, col>>
|
||||||
|
static QPair<ScriptMachine::MessageType, QPair<int, int>> lastInfo{
|
||||||
|
ScriptMachine::MessageType::Print, {-1, -1}};
|
||||||
|
|
||||||
|
auto doc = this->document();
|
||||||
|
auto lastLine = doc->lastBlock();
|
||||||
|
auto isNotBlockStart = !lastLine.text().isEmpty();
|
||||||
|
|
||||||
|
auto fmtMsg = [](const ScriptMachine::MessageInfo &message) -> QString {
|
||||||
|
if (message.row <= 0 || message.col <= 0) {
|
||||||
|
return message.message;
|
||||||
|
} else {
|
||||||
|
return QStringLiteral("(") + QString::number(message.row) +
|
||||||
|
QStringLiteral(", ") + QString::number(message.col) +
|
||||||
|
QStringLiteral(")") + message.message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto isMatchLast = [](const ScriptMachine::MessageInfo &message) -> bool {
|
||||||
|
if (message.row < 0 || message.col < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return lastInfo.first == message.type &&
|
||||||
|
lastInfo.second.first == message.row &&
|
||||||
|
lastInfo.second.second == message.col;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (message.type) {
|
||||||
|
case ScriptMachine::MessageType::Info:
|
||||||
|
if (isMatchLast(message)) {
|
||||||
|
stdOut(message.message);
|
||||||
|
} else {
|
||||||
|
if (isNotBlockStart) {
|
||||||
|
newLine();
|
||||||
|
}
|
||||||
|
stdOut(tr("[Info]") + fmtMsg(message));
|
||||||
|
}
|
||||||
|
flush();
|
||||||
|
break;
|
||||||
|
case ScriptMachine::MessageType::Warn:
|
||||||
|
if (isMatchLast(message)) {
|
||||||
|
stdWarn(message.message);
|
||||||
|
} else {
|
||||||
|
if (isNotBlockStart) {
|
||||||
|
newLine();
|
||||||
|
}
|
||||||
|
stdWarn(tr("[Warn]") + fmtMsg(message));
|
||||||
|
}
|
||||||
|
flush();
|
||||||
|
break;
|
||||||
|
case ScriptMachine::MessageType::Error:
|
||||||
|
if (isMatchLast(message)) {
|
||||||
|
stdErr(message.message);
|
||||||
|
} else {
|
||||||
|
if (isNotBlockStart) {
|
||||||
|
newLine();
|
||||||
|
}
|
||||||
|
stdErr(tr("[Error]") + fmtMsg(message));
|
||||||
|
}
|
||||||
|
flush();
|
||||||
|
break;
|
||||||
|
case ScriptMachine::MessageType::Print:
|
||||||
|
if (lastInfo.first != message.type) {
|
||||||
|
newLine();
|
||||||
|
}
|
||||||
|
stdOut(message.message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastInfo.first = message.type;
|
||||||
|
lastInfo.second = qMakePair(message.row, message.col);
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptingConsole::applyScriptSettings() {
|
void ScriptingConsole::applyScriptSettings() {
|
||||||
auto &set = ScriptSettings::instance();
|
auto &set = ScriptSettings::instance();
|
||||||
auto dfont = QFont(set.consoleFontFamily());
|
auto dfont = QFont(set.consoleFontFamily());
|
||||||
|
@ -241,7 +228,9 @@ void ScriptingConsole::runConsoleCommand(const QString &code) {
|
||||||
} else {
|
} else {
|
||||||
setMode(Output);
|
setMode(Output);
|
||||||
_codes += exec;
|
_codes += exec;
|
||||||
if (!_sp->executeCode(_codes)) {
|
if (!ScriptMachine::instance().executeCode(ScriptMachine::Interactive,
|
||||||
|
_codes)) {
|
||||||
|
// WingMessageBox::
|
||||||
}
|
}
|
||||||
_codes.clear();
|
_codes.clear();
|
||||||
appendCommandPrompt();
|
appendCommandPrompt();
|
||||||
|
@ -290,10 +279,6 @@ QString ScriptingConsole::currentCodes() const {
|
||||||
return _codes + currentCommandLine();
|
return _codes + currentCommandLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptMachine *ScriptingConsole::machine() const { return _sp; }
|
|
||||||
|
|
||||||
ScriptConsoleMachine *ScriptingConsole::consoleMachine() const { return _sp; }
|
|
||||||
|
|
||||||
void ScriptingConsole::contextMenuEvent(QContextMenuEvent *event) {
|
void ScriptingConsole::contextMenuEvent(QContextMenuEvent *event) {
|
||||||
QMenu menu(this);
|
QMenu menu(this);
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,9 @@
|
||||||
#ifndef ScriptingConsole_H
|
#ifndef ScriptingConsole_H
|
||||||
#define ScriptingConsole_H
|
#define ScriptingConsole_H
|
||||||
|
|
||||||
#include "scriptingconsolebase.h"
|
|
||||||
|
|
||||||
#include "class/asconsolecompletion.h"
|
#include "class/asconsolecompletion.h"
|
||||||
#include "class/scriptconsolemachine.h"
|
#include "class/scriptmachine.h"
|
||||||
|
#include "scriptingconsolebase.h"
|
||||||
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
|
||||||
|
@ -33,14 +32,14 @@ public:
|
||||||
|
|
||||||
virtual ~ScriptingConsole();
|
virtual ~ScriptingConsole();
|
||||||
|
|
||||||
ScriptMachine *machine() const;
|
|
||||||
ScriptConsoleMachine *consoleMachine() const;
|
|
||||||
|
|
||||||
QString currentCodes() const;
|
QString currentCodes() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onFunctionTip(const QString &tip);
|
void onFunctionTip(const QString &tip);
|
||||||
|
|
||||||
|
public:
|
||||||
|
QString getInput();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
@ -48,14 +47,14 @@ public slots:
|
||||||
|
|
||||||
void processKeyEvent(QKeyEvent *e);
|
void processKeyEvent(QKeyEvent *e);
|
||||||
|
|
||||||
|
void onOutput(const ScriptMachine::MessageInfo &message);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void applyScriptSettings();
|
void applyScriptSettings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void runConsoleCommand(const QString &code);
|
void runConsoleCommand(const QString &code);
|
||||||
|
|
||||||
QString getInput();
|
|
||||||
|
|
||||||
QString packUpLoggingStr(const QString &message);
|
QString packUpLoggingStr(const QString &message);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -67,8 +66,6 @@ protected slots:
|
||||||
virtual void onCompletion(const QModelIndex &index) override;
|
virtual void onCompletion(const QModelIndex &index) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScriptConsoleMachine *_sp = nullptr;
|
|
||||||
|
|
||||||
QString _codes;
|
QString _codes;
|
||||||
|
|
||||||
std::function<QString(void)> _getInputFn;
|
std::function<QString(void)> _getInputFn;
|
||||||
|
|
|
@ -13,6 +13,8 @@ enum AsUserDataType {
|
||||||
UserData_ContextDbgInfo,
|
UserData_ContextDbgInfo,
|
||||||
UserData_API,
|
UserData_API,
|
||||||
UserData_PluginFn,
|
UserData_PluginFn,
|
||||||
|
UserData_isDbg,
|
||||||
|
UserData_ContextMode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include "class/pluginsystem.h"
|
#include "class/pluginsystem.h"
|
||||||
#include "class/qkeysequences.h"
|
#include "class/qkeysequences.h"
|
||||||
#include "class/richtextitemdelegate.h"
|
#include "class/richtextitemdelegate.h"
|
||||||
#include "class/scriptconsolemachine.h"
|
#include "class/scriptmachine.h"
|
||||||
#include "class/settingmanager.h"
|
#include "class/settingmanager.h"
|
||||||
#include "class/wingfiledialog.h"
|
#include "class/wingfiledialog.h"
|
||||||
#include "class/winginputdialog.h"
|
#include "class/winginputdialog.h"
|
||||||
|
@ -230,6 +230,32 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
|
||||||
// Don't setup it too early, because the plugin can register script
|
// Don't setup it too early, because the plugin can register script
|
||||||
// functions. Code completions of them will be not worked out.
|
// functions. Code completions of them will be not worked out.
|
||||||
if (set.scriptEnabled()) {
|
if (set.scriptEnabled()) {
|
||||||
|
auto &sm = ScriptMachine::instance();
|
||||||
|
auto smr = sm.init();
|
||||||
|
if (smr) {
|
||||||
|
ScriptMachine::RegCallBacks callbacks;
|
||||||
|
callbacks.getInputFn = [this]() -> QString {
|
||||||
|
return m_scriptConsole->getInput();
|
||||||
|
};
|
||||||
|
callbacks.clearFn = [this]() { m_scriptConsole->clearConsole(); };
|
||||||
|
callbacks.printMsgFn =
|
||||||
|
[this](const ScriptMachine::MessageInfo &message) {
|
||||||
|
m_scriptConsole->onOutput(message);
|
||||||
|
};
|
||||||
|
sm.registerCallBack(ScriptMachine::Interactive, callbacks);
|
||||||
|
|
||||||
|
callbacks.getInputFn = [this]() -> QString {
|
||||||
|
return WingInputDialog::getText(this, tr(""), tr(""));
|
||||||
|
};
|
||||||
|
callbacks.clearFn = [this]() { m_bgScriptOutput->clear(); };
|
||||||
|
callbacks.printMsgFn =
|
||||||
|
std::bind(&MainWindow::onOutputBgScriptOutput, this,
|
||||||
|
std::placeholders::_1);
|
||||||
|
sm.registerCallBack(ScriptMachine::Background, callbacks);
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
// At this time, AngelScript service plugin has started
|
// At this time, AngelScript service plugin has started
|
||||||
if (splash)
|
if (splash)
|
||||||
splash->setInfoText(tr("SetupConsole"));
|
splash->setInfoText(tr("SetupConsole"));
|
||||||
|
@ -237,25 +263,17 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
|
||||||
m_scriptConsole->init();
|
m_scriptConsole->init();
|
||||||
if (splash)
|
if (splash)
|
||||||
splash->setInfoText(tr("SetupScriptManager"));
|
splash->setInfoText(tr("SetupScriptManager"));
|
||||||
ScriptManager::instance().attach(m_scriptConsole);
|
|
||||||
|
|
||||||
plg.angelApi()->setBindingConsole(m_scriptConsole);
|
|
||||||
|
|
||||||
if (splash)
|
if (splash)
|
||||||
splash->setInfoText(tr("SetupScriptService"));
|
splash->setInfoText(tr("SetupScriptService"));
|
||||||
|
|
||||||
m_scriptConsole->initOutput();
|
m_scriptConsole->initOutput();
|
||||||
m_scriptConsole->setMode(QConsoleWidget::Input);
|
m_scriptConsole->setMode(QConsoleWidget::Input);
|
||||||
m_scriptConsole->machine()->setInsteadFoundDisabled(true);
|
|
||||||
|
|
||||||
if (splash)
|
if (splash)
|
||||||
splash->setInfoText(tr("SetupScriptEditor"));
|
splash->setInfoText(tr("SetupScriptEditor"));
|
||||||
m_scriptDialog = new ScriptingDialog(this);
|
m_scriptDialog = new ScriptingDialog(this);
|
||||||
m_scriptDialog->initConsole();
|
m_scriptDialog->initConsole();
|
||||||
|
|
||||||
// load the model
|
|
||||||
Q_ASSERT(m_scriptConsole && m_scriptConsole->machine());
|
|
||||||
m_varshowtable->setModel(m_scriptConsole->consoleMachine()->model());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect settings signals
|
// connect settings signals
|
||||||
|
@ -535,8 +553,8 @@ void MainWindow::buildUpDockSystem(QWidget *container) {
|
||||||
bottomRightArea = buildUpScriptConsoleDock(
|
bottomRightArea = buildUpScriptConsoleDock(
|
||||||
m_dock, ads::RightDockWidgetArea, bottomLeftArea);
|
m_dock, ads::RightDockWidgetArea, bottomLeftArea);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
buildUpScriptObjShowDock(m_dock, ads::CenterDockWidgetArea,
|
buildUpScriptBgOutputDock(m_dock, ads::CenterDockWidgetArea,
|
||||||
bottomRightArea);
|
bottomRightArea);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
buildUpHashResultDock(m_dock, ads::CenterDockWidgetArea,
|
buildUpHashResultDock(m_dock, ads::CenterDockWidgetArea,
|
||||||
bottomRightArea);
|
bottomRightArea);
|
||||||
|
@ -1000,17 +1018,14 @@ MainWindow::buildUpScriptConsoleDock(ads::CDockManager *dock,
|
||||||
}
|
}
|
||||||
|
|
||||||
ads::CDockAreaWidget *
|
ads::CDockAreaWidget *
|
||||||
MainWindow::buildUpScriptObjShowDock(ads::CDockManager *dock,
|
MainWindow::buildUpScriptBgOutputDock(ads::CDockManager *dock,
|
||||||
ads::DockWidgetArea area,
|
ads::DockWidgetArea area,
|
||||||
ads::CDockAreaWidget *areaw) {
|
ads::CDockAreaWidget *areaw) {
|
||||||
m_varshowtable = new QTableViewExt(this);
|
m_bgScriptOutput = new QPlainTextEdit(this);
|
||||||
m_varshowtable->setEditTriggers(QTableView::EditTrigger::DoubleClicked);
|
m_bgScriptOutput->setReadOnly(true);
|
||||||
m_varshowtable->setSelectionBehavior(
|
|
||||||
QAbstractItemView::SelectionBehavior::SelectRows);
|
|
||||||
m_varshowtable->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
|
|
||||||
auto dw = buildDockWidget(dock, QStringLiteral("ScriptObjShow"),
|
auto dw = buildDockWidget(dock, QStringLiteral("BgScriptOutput"),
|
||||||
tr("ScriptObjShow"), m_varshowtable);
|
tr("BgScriptOutput"), m_bgScriptOutput);
|
||||||
return dock->addDockWidget(area, dw, areaw);
|
return dock->addDockWidget(area, dw, areaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1720,7 +1735,7 @@ RibbonTabContent *MainWindow::buildPluginPage(RibbonTabContent *tab) {
|
||||||
auto pannel = tab->addGroup(tr("General"));
|
auto pannel = tab->addGroup(tr("General"));
|
||||||
addPannelAction(
|
addPannelAction(
|
||||||
pannel, QStringLiteral("settingplugin"), tr("Plugin"),
|
pannel, QStringLiteral("settingplugin"), tr("Plugin"),
|
||||||
&MainWindow::on_setting_plugin,
|
&MainWindow::on_settingPlugin,
|
||||||
shortcuts.keySequence(QKeySequences::Key::SETTING_PLUGIN));
|
shortcuts.keySequence(QKeySequences::Key::SETTING_PLUGIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1743,13 +1758,12 @@ RibbonTabContent *MainWindow::buildSettingPage(RibbonTabContent *tab) {
|
||||||
auto pannel = tab->addGroup(tr("General"));
|
auto pannel = tab->addGroup(tr("General"));
|
||||||
addPannelAction(
|
addPannelAction(
|
||||||
pannel, QStringLiteral("general"), tr("General"),
|
pannel, QStringLiteral("general"), tr("General"),
|
||||||
&MainWindow::on_setting_general,
|
&MainWindow::on_settingGeneral,
|
||||||
shortcuts.keySequence(QKeySequences::Key::SETTING_GENERAL));
|
shortcuts.keySequence(QKeySequences::Key::SETTING_GENERAL));
|
||||||
|
|
||||||
if (set.scriptEnabled()) {
|
if (set.scriptEnabled()) {
|
||||||
addPannelAction(pannel, QStringLiteral("scriptset"),
|
addPannelAction(pannel, QStringLiteral("scriptset"),
|
||||||
tr("ScriptSetting"),
|
tr("ScriptSetting"), &MainWindow::on_settingScript);
|
||||||
&MainWindow::on_setting_script);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3097,13 +3111,13 @@ void MainWindow::on_scriptwindow() {
|
||||||
m_scriptDialog->raise();
|
m_scriptDialog->raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_setting_general() { m_setdialog->showConfig(0); }
|
void MainWindow::on_settingGeneral() { m_setdialog->showConfig(0); }
|
||||||
|
|
||||||
void MainWindow::on_setting_script() {
|
void MainWindow::on_settingScript() {
|
||||||
m_scriptDialog->settingDialog()->showConfig();
|
m_scriptDialog->settingDialog()->showConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_setting_plugin() { m_setdialog->showConfig(2); }
|
void MainWindow::on_settingPlugin() { m_setdialog->showConfig(2); }
|
||||||
|
|
||||||
void MainWindow::on_about() { AboutSoftwareDialog().exec(); }
|
void MainWindow::on_about() { AboutSoftwareDialog().exec(); }
|
||||||
|
|
||||||
|
@ -3939,6 +3953,88 @@ ads::CDockAreaWidget *MainWindow::editorViewArea() const {
|
||||||
return m_dock->centralWidget()->dockAreaWidget();
|
return m_dock->centralWidget()->dockAreaWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onOutputBgScriptOutput(
|
||||||
|
const ScriptMachine::MessageInfo &message) {
|
||||||
|
static QPair<ScriptMachine::MessageType, QPair<int, int>> lastInfo{
|
||||||
|
ScriptMachine::MessageType::Print, {-1, -1}};
|
||||||
|
|
||||||
|
auto doc = m_bgScriptOutput->document();
|
||||||
|
auto lastLine = doc->lastBlock();
|
||||||
|
auto isNotBlockStart = !lastLine.text().isEmpty();
|
||||||
|
|
||||||
|
auto cursor = m_bgScriptOutput->textCursor();
|
||||||
|
cursor.movePosition(QTextCursor::End);
|
||||||
|
|
||||||
|
auto fmtMsg = [](const ScriptMachine::MessageInfo &message) -> QString {
|
||||||
|
if (message.row <= 0 || message.col <= 0) {
|
||||||
|
return message.message;
|
||||||
|
} else {
|
||||||
|
return QStringLiteral("(") + QString::number(message.row) +
|
||||||
|
QStringLiteral(", ") + QString::number(message.col) +
|
||||||
|
QStringLiteral(")") + message.message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto isMatchLast = [](const ScriptMachine::MessageInfo &message) -> bool {
|
||||||
|
if (message.row < 0 || message.col < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return lastInfo.first == message.type &&
|
||||||
|
lastInfo.second.first == message.row &&
|
||||||
|
lastInfo.second.second == message.col;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (message.type) {
|
||||||
|
case ScriptMachine::MessageType::Info:
|
||||||
|
if (isMatchLast(message)) {
|
||||||
|
cursor.insertText(message.message);
|
||||||
|
} else {
|
||||||
|
if (isNotBlockStart) {
|
||||||
|
cursor.insertBlock();
|
||||||
|
}
|
||||||
|
cursor.insertText(tr("[Info]") + fmtMsg(message));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ScriptMachine::MessageType::Warn:
|
||||||
|
if (isMatchLast(message)) {
|
||||||
|
auto fmt = cursor.charFormat();
|
||||||
|
fmt.setForeground(QColorConstants::Svg::gold);
|
||||||
|
cursor.insertText(message.message, fmt);
|
||||||
|
} else {
|
||||||
|
if (isNotBlockStart) {
|
||||||
|
m_bgScriptOutput->appendPlainText({});
|
||||||
|
}
|
||||||
|
auto fmt = cursor.charFormat();
|
||||||
|
fmt.setForeground(QColorConstants::Svg::gold);
|
||||||
|
cursor.insertText(tr("[Warn]") + fmtMsg(message), fmt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ScriptMachine::MessageType::Error:
|
||||||
|
if (isMatchLast(message)) {
|
||||||
|
auto fmt = cursor.charFormat();
|
||||||
|
fmt.setForeground(Qt::red);
|
||||||
|
cursor.insertText(message.message, fmt);
|
||||||
|
} else {
|
||||||
|
if (isNotBlockStart) {
|
||||||
|
cursor.insertBlock();
|
||||||
|
}
|
||||||
|
auto fmt = cursor.charFormat();
|
||||||
|
fmt.setForeground(Qt::red);
|
||||||
|
cursor.insertText(tr("[Error]") + fmtMsg(message), fmt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ScriptMachine::MessageType::Print:
|
||||||
|
if (lastInfo.first != message.type) {
|
||||||
|
cursor.insertBlock();
|
||||||
|
}
|
||||||
|
cursor.insertText(message.message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastInfo.first = message.type;
|
||||||
|
lastInfo.second = qMakePair(message.row, message.col);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject MainWindow::extractModelData(const QAbstractItemModel *model,
|
QJsonObject MainWindow::extractModelData(const QAbstractItemModel *model,
|
||||||
const QModelIndex &parent) {
|
const QModelIndex &parent) {
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
|
@ -3981,11 +4077,8 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// then checking the scripting console
|
// then abort all script running
|
||||||
auto sm = m_scriptConsole->consoleMachine();
|
ScriptMachine::instance().abortScript();
|
||||||
if (sm->isRunning()) {
|
|
||||||
sm->abortScript();
|
|
||||||
}
|
|
||||||
|
|
||||||
// then checking itself
|
// then checking itself
|
||||||
if (!m_views.isEmpty()) {
|
if (!m_views.isEmpty()) {
|
||||||
|
|
|
@ -123,8 +123,8 @@ private:
|
||||||
buildUpScriptConsoleDock(ads::CDockManager *dock, ads::DockWidgetArea area,
|
buildUpScriptConsoleDock(ads::CDockManager *dock, ads::DockWidgetArea area,
|
||||||
ads::CDockAreaWidget *areaw = nullptr);
|
ads::CDockAreaWidget *areaw = nullptr);
|
||||||
ads::CDockAreaWidget *
|
ads::CDockAreaWidget *
|
||||||
buildUpScriptObjShowDock(ads::CDockManager *dock, ads::DockWidgetArea area,
|
buildUpScriptBgOutputDock(ads::CDockManager *dock, ads::DockWidgetArea area,
|
||||||
ads::CDockAreaWidget *areaw = nullptr);
|
ads::CDockAreaWidget *areaw = nullptr);
|
||||||
ads::CDockAreaWidget *
|
ads::CDockAreaWidget *
|
||||||
buildUpVisualDataDock(ads::CDockManager *dock, ads::DockWidgetArea area,
|
buildUpVisualDataDock(ads::CDockManager *dock, ads::DockWidgetArea area,
|
||||||
ads::CDockAreaWidget *areaw = nullptr);
|
ads::CDockAreaWidget *areaw = nullptr);
|
||||||
|
@ -205,9 +205,9 @@ private slots:
|
||||||
void on_inspectQt();
|
void on_inspectQt();
|
||||||
|
|
||||||
void on_scriptwindow();
|
void on_scriptwindow();
|
||||||
void on_setting_general();
|
void on_settingGeneral();
|
||||||
void on_setting_script();
|
void on_settingScript();
|
||||||
void on_setting_plugin();
|
void on_settingPlugin();
|
||||||
|
|
||||||
void on_about();
|
void on_about();
|
||||||
void on_sponsor();
|
void on_sponsor();
|
||||||
|
@ -266,6 +266,8 @@ private:
|
||||||
|
|
||||||
inline ads::CDockAreaWidget *editorViewArea() const;
|
inline ads::CDockAreaWidget *editorViewArea() const;
|
||||||
|
|
||||||
|
void onOutputBgScriptOutput(const ScriptMachine::MessageInfo &message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QJsonObject extractModelData(const QAbstractItemModel *model,
|
QJsonObject extractModelData(const QAbstractItemModel *model,
|
||||||
const QModelIndex &parent = QModelIndex());
|
const QModelIndex &parent = QModelIndex());
|
||||||
|
@ -481,7 +483,7 @@ private:
|
||||||
|
|
||||||
ScriptingDialog *m_scriptDialog = nullptr;
|
ScriptingDialog *m_scriptDialog = nullptr;
|
||||||
ScriptingConsole *m_scriptConsole = nullptr;
|
ScriptingConsole *m_scriptConsole = nullptr;
|
||||||
QTableViewExt *m_varshowtable = nullptr;
|
QPlainTextEdit *m_bgScriptOutput = nullptr;
|
||||||
|
|
||||||
bool m_isfinding = false;
|
bool m_isfinding = false;
|
||||||
ads::CDockWidget *m_find = nullptr;
|
ads::CDockWidget *m_find = nullptr;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "class/languagemanager.h"
|
#include "class/languagemanager.h"
|
||||||
#include "class/pluginsystem.h"
|
#include "class/pluginsystem.h"
|
||||||
#include "class/qkeysequences.h"
|
#include "class/qkeysequences.h"
|
||||||
|
#include "class/scriptmachine.h"
|
||||||
#include "class/settingmanager.h"
|
#include "class/settingmanager.h"
|
||||||
#include "class/wingfiledialog.h"
|
#include "class/wingfiledialog.h"
|
||||||
#include "class/wingmessagebox.h"
|
#include "class/wingmessagebox.h"
|
||||||
|
@ -93,6 +94,17 @@ ScriptingDialog::ScriptingDialog(QWidget *parent)
|
||||||
m_dock->restoreState(set.scriptDockLayout());
|
m_dock->restoreState(set.scriptDockLayout());
|
||||||
_savedLayout = set.scriptDockLayout();
|
_savedLayout = set.scriptDockLayout();
|
||||||
|
|
||||||
|
ScriptMachine::RegCallBacks callbacks;
|
||||||
|
callbacks.getInputFn = [this]() -> QString {
|
||||||
|
return m_consoleout->getInput();
|
||||||
|
};
|
||||||
|
callbacks.clearFn = [this]() { m_consoleout->clearConsole(); };
|
||||||
|
callbacks.printMsgFn = [this](const ScriptMachine::MessageInfo &message) {
|
||||||
|
m_consoleout->onOutput(message);
|
||||||
|
};
|
||||||
|
ScriptMachine::instance().registerCallBack(ScriptMachine::Scripting,
|
||||||
|
callbacks);
|
||||||
|
|
||||||
this->setUpdatesEnabled(true);
|
this->setUpdatesEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +114,8 @@ void ScriptingDialog::initConsole() {
|
||||||
Q_ASSERT(m_consoleout);
|
Q_ASSERT(m_consoleout);
|
||||||
|
|
||||||
m_consoleout->init();
|
m_consoleout->init();
|
||||||
auto machine = m_consoleout->machine();
|
auto &machine = ScriptMachine::instance();
|
||||||
connect(machine, &ScriptMachine::onDebugFinished, this, [=] {
|
connect(&machine, &ScriptMachine::onDebugFinished, this, [=] {
|
||||||
this->updateRunDebugMode();
|
this->updateRunDebugMode();
|
||||||
m_callstack->updateData({});
|
m_callstack->updateData({});
|
||||||
m_varshow->updateData({});
|
m_varshow->updateData({});
|
||||||
|
@ -138,7 +150,7 @@ void ScriptingDialog::initConsole() {
|
||||||
_DebugingEditor = nullptr;
|
_DebugingEditor = nullptr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
auto dbg = machine->debugger();
|
auto dbg = machine.debugger();
|
||||||
Q_ASSERT(dbg);
|
Q_ASSERT(dbg);
|
||||||
connect(dbg, &asDebugger::onAdjustBreakPointLine, this,
|
connect(dbg, &asDebugger::onAdjustBreakPointLine, this,
|
||||||
[=](const asDebugger::BreakPoint &old, int newLineNr) {
|
[=](const asDebugger::BreakPoint &old, int newLineNr) {
|
||||||
|
@ -210,7 +222,7 @@ void ScriptingDialog::initConsole() {
|
||||||
});
|
});
|
||||||
connect(dbg, &asDebugger::onDebugActionExec, this,
|
connect(dbg, &asDebugger::onDebugActionExec, this,
|
||||||
[this]() { updateRunDebugMode(); });
|
[this]() { updateRunDebugMode(); });
|
||||||
m_sym->setEngine(machine->engine());
|
m_sym->setEngine(machine.engine());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptingDialog::about2Close() {
|
bool ScriptingDialog::about2Close() {
|
||||||
|
@ -489,16 +501,15 @@ RibbonTabContent *ScriptingDialog::buildDebugPage(RibbonTabContent *tab) {
|
||||||
|
|
||||||
auto dbgShortCut = new QShortcut(dbgkey, this);
|
auto dbgShortCut = new QShortcut(dbgkey, this);
|
||||||
connect(dbgShortCut, &QShortcut::activated, this, [this]() {
|
connect(dbgShortCut, &QShortcut::activated, this, [this]() {
|
||||||
auto runner = m_consoleout->machine();
|
auto &runner = ScriptMachine::instance();
|
||||||
bool isRun = false;
|
bool isRun = false;
|
||||||
bool isDbg = false;
|
bool isDbg = false;
|
||||||
bool isPaused = false;
|
bool isPaused = false;
|
||||||
if (runner) {
|
|
||||||
isRun = runner->isRunning();
|
isRun = runner.isRunning();
|
||||||
isDbg = runner->isDebugMode();
|
isDbg = runner.isDebugMode();
|
||||||
auto dbg = runner->debugger();
|
auto dbg = runner.debugger();
|
||||||
isPaused = dbg->currentState() == asDebugger::PAUSE;
|
isPaused = dbg->currentState() == asDebugger::PAUSE;
|
||||||
}
|
|
||||||
|
|
||||||
if (isRun && isDbg && isPaused) {
|
if (isRun && isDbg && isPaused) {
|
||||||
m_Tbtneditors[ToolButtonIndex::DBG_CONTINUE_ACTION]->animateClick();
|
m_Tbtneditors[ToolButtonIndex::DBG_CONTINUE_ACTION]->animateClick();
|
||||||
|
@ -728,8 +739,8 @@ void ScriptingDialog::registerEditorView(ScriptEditor *editor) {
|
||||||
Q_ASSERT(editor);
|
Q_ASSERT(editor);
|
||||||
Q_ASSERT(m_views.contains(editor));
|
Q_ASSERT(m_views.contains(editor));
|
||||||
|
|
||||||
auto m = m_consoleout->machine();
|
auto &m = ScriptMachine::instance();
|
||||||
if (m->isRunning() && _DebugingEditor == editor) {
|
if (m.isRunning() && _DebugingEditor == editor) {
|
||||||
if (WingMessageBox::warning(
|
if (WingMessageBox::warning(
|
||||||
this, this->windowTitle(), tr("ScriptStillRunning"),
|
this, this->windowTitle(), tr("ScriptStillRunning"),
|
||||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
||||||
|
@ -864,17 +875,17 @@ void ScriptingDialog::swapEditor(ScriptEditor *old, ScriptEditor *cur) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingDialog::updateRunDebugMode(bool disable) {
|
void ScriptingDialog::updateRunDebugMode(bool disable) {
|
||||||
auto runner = m_consoleout->machine();
|
auto &runner = ScriptMachine::instance();
|
||||||
auto enable = !disable;
|
auto enable = !disable;
|
||||||
bool isRun = false;
|
bool isRun = false;
|
||||||
bool isDbg = false;
|
bool isDbg = false;
|
||||||
bool isPaused = false;
|
bool isPaused = false;
|
||||||
if (runner) {
|
|
||||||
isRun = runner->isRunning();
|
isRun = runner.isRunning();
|
||||||
isDbg = runner->isDebugMode();
|
isDbg = runner.isDebugMode();
|
||||||
auto dbg = runner->debugger();
|
auto dbg = runner.debugger();
|
||||||
isPaused = dbg->currentState() == asDebugger::PAUSE;
|
isPaused = dbg->currentState() == asDebugger::PAUSE;
|
||||||
}
|
|
||||||
m_Tbtneditors.value(ToolButtonIndex::DBG_RUN_ACTION)->setEnabled(!isRun);
|
m_Tbtneditors.value(ToolButtonIndex::DBG_RUN_ACTION)->setEnabled(!isRun);
|
||||||
m_Tbtneditors.value(ToolButtonIndex::DBG_RUN_DBG_ACTION)
|
m_Tbtneditors.value(ToolButtonIndex::DBG_RUN_DBG_ACTION)
|
||||||
->setEnabled(!isRun);
|
->setEnabled(!isRun);
|
||||||
|
@ -920,8 +931,8 @@ ScriptEditor *ScriptingDialog::findEditorView(const QString &filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptingDialog::isCurrentDebugging() const {
|
bool ScriptingDialog::isCurrentDebugging() const {
|
||||||
auto m = m_consoleout->machine();
|
auto &m = ScriptMachine::instance();
|
||||||
return m && m->isDebugMode();
|
return m.isDebugMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEditor *ScriptingDialog::openFile(const QString &filename) {
|
ScriptEditor *ScriptingDialog::openFile(const QString &filename) {
|
||||||
|
@ -932,8 +943,7 @@ ScriptEditor *ScriptingDialog::openFile(const QString &filename) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto editor =
|
auto editor = new ScriptEditor(this);
|
||||||
new ScriptEditor(m_consoleout->consoleMachine()->engine(), this);
|
|
||||||
|
|
||||||
auto res = editor->openFile(filename);
|
auto res = editor->openFile(filename);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
|
@ -949,9 +959,9 @@ ScriptEditor *ScriptingDialog::openFile(const QString &filename) {
|
||||||
|
|
||||||
void ScriptingDialog::runDbgCommand(asDebugger::DebugAction action) {
|
void ScriptingDialog::runDbgCommand(asDebugger::DebugAction action) {
|
||||||
updateRunDebugMode(true);
|
updateRunDebugMode(true);
|
||||||
auto machine = m_consoleout->machine();
|
auto &machine = ScriptMachine::instance();
|
||||||
if (machine->isDebugMode()) {
|
if (machine.isDebugMode()) {
|
||||||
auto dbg = machine->debugger();
|
auto dbg = machine.debugger();
|
||||||
dbg->runDebugAction(action);
|
dbg->runDebugAction(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -978,7 +988,7 @@ void ScriptingDialog::startDebugScript(ScriptEditor *editor) {
|
||||||
m_consoleout->clear();
|
m_consoleout->clear();
|
||||||
|
|
||||||
// add breakpoints
|
// add breakpoints
|
||||||
auto dbg = m_consoleout->machine()->debugger();
|
auto dbg = ScriptMachine::instance().debugger();
|
||||||
auto fileName = editor->fileName();
|
auto fileName = editor->fileName();
|
||||||
auto e = editor->editor();
|
auto e = editor->editor();
|
||||||
auto totalblk = e->blockCount();
|
auto totalblk = e->blockCount();
|
||||||
|
@ -992,7 +1002,8 @@ void ScriptingDialog::startDebugScript(ScriptEditor *editor) {
|
||||||
PluginSystem::instance().scriptPragmaBegin();
|
PluginSystem::instance().scriptPragmaBegin();
|
||||||
|
|
||||||
editor->setReadOnly(true);
|
editor->setReadOnly(true);
|
||||||
m_consoleout->machine()->executeScript(fileName, true);
|
ScriptMachine::instance().executeScript(ScriptMachine::Scripting, fileName,
|
||||||
|
true);
|
||||||
editor->setReadOnly(false);
|
editor->setReadOnly(false);
|
||||||
|
|
||||||
updateRunDebugMode();
|
updateRunDebugMode();
|
||||||
|
@ -1006,8 +1017,9 @@ void ScriptingDialog::addBreakPoint(ScriptEditor *editor, int line) {
|
||||||
const auto curSym = QStringLiteral("cur");
|
const auto curSym = QStringLiteral("cur");
|
||||||
const auto hitCur = QStringLiteral("curbp");
|
const auto hitCur = QStringLiteral("curbp");
|
||||||
|
|
||||||
if (m_consoleout->machine()->isDebugMode()) {
|
auto &m = ScriptMachine::instance();
|
||||||
auto dbg = m_consoleout->machine()->debugger();
|
if (m.isDebugMode()) {
|
||||||
|
auto dbg = m.debugger();
|
||||||
auto symID = e->symbolMark(line);
|
auto symID = e->symbolMark(line);
|
||||||
if (curSym == symID) {
|
if (curSym == symID) {
|
||||||
e->addSymbolMark(line, hitCur);
|
e->addSymbolMark(line, hitCur);
|
||||||
|
@ -1027,8 +1039,9 @@ void ScriptingDialog::removeBreakPoint(ScriptEditor *editor, int line) {
|
||||||
Q_ASSERT(editor);
|
Q_ASSERT(editor);
|
||||||
auto e = editor->editor();
|
auto e = editor->editor();
|
||||||
|
|
||||||
if (m_consoleout->machine()->isDebugMode()) {
|
auto &m = ScriptMachine::instance();
|
||||||
auto dbg = m_consoleout->machine()->debugger();
|
if (m.isDebugMode()) {
|
||||||
|
auto dbg = m.debugger();
|
||||||
auto symID = e->symbolMark(line);
|
auto symID = e->symbolMark(line);
|
||||||
|
|
||||||
const auto bpMark = QStringLiteral("bp");
|
const auto bpMark = QStringLiteral("bp");
|
||||||
|
@ -1053,8 +1066,9 @@ void ScriptingDialog::toggleBreakPoint(ScriptEditor *editor, int line) {
|
||||||
Q_ASSERT(editor);
|
Q_ASSERT(editor);
|
||||||
auto e = editor->editor();
|
auto e = editor->editor();
|
||||||
|
|
||||||
if (m_consoleout->machine()->isDebugMode()) {
|
auto &m = ScriptMachine::instance();
|
||||||
auto dbg = m_consoleout->machine()->debugger();
|
if (m.isDebugMode()) {
|
||||||
|
auto dbg = m.debugger();
|
||||||
auto symID = e->symbolMark(line);
|
auto symID = e->symbolMark(line);
|
||||||
|
|
||||||
const auto bpMark = QStringLiteral("bp");
|
const auto bpMark = QStringLiteral("bp");
|
||||||
|
@ -1134,8 +1148,7 @@ void ScriptingDialog::on_newfile() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto editor =
|
auto editor = new ScriptEditor(this);
|
||||||
new ScriptEditor(m_consoleout->consoleMachine()->engine(), this);
|
|
||||||
auto res = editor->openFile(filename);
|
auto res = editor->openFile(filename);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
WingMessageBox::critical(this, tr("Error"), tr("FilePermission"));
|
WingMessageBox::critical(this, tr("Error"), tr("FilePermission"));
|
||||||
|
@ -1355,7 +1368,7 @@ void ScriptingDialog::on_runscript() {
|
||||||
PluginSystem::instance().scriptPragmaBegin();
|
PluginSystem::instance().scriptPragmaBegin();
|
||||||
|
|
||||||
editor->setReadOnly(true);
|
editor->setReadOnly(true);
|
||||||
m_consoleout->machine()->executeScript(editor->fileName());
|
// ScriptMachine::instance().executeScript(editor->fileName());
|
||||||
editor->setReadOnly(false);
|
editor->setReadOnly(false);
|
||||||
updateRunDebugMode();
|
updateRunDebugMode();
|
||||||
}
|
}
|
||||||
|
@ -1423,8 +1436,8 @@ void ScriptingDialog::on_removebreakpoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingDialog::closeEvent(QCloseEvent *event) {
|
void ScriptingDialog::closeEvent(QCloseEvent *event) {
|
||||||
auto runner = m_consoleout->machine();
|
auto &runner = ScriptMachine::instance();
|
||||||
if (runner->isRunning()) {
|
if (runner.isRunning()) {
|
||||||
if (WingMessageBox::warning(
|
if (WingMessageBox::warning(
|
||||||
this, this->windowTitle(), tr("ScriptStillRunning"),
|
this, this->windowTitle(), tr("ScriptStillRunning"),
|
||||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
/*==============================================================================
|
|
||||||
** Copyright (C) 2024-2027 WingSummer
|
|
||||||
**
|
|
||||||
** This program is free software: you can redistribute it and/or modify it under
|
|
||||||
** the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
** Software Foundation, version 3.
|
|
||||||
**
|
|
||||||
** This program 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 Affero General Public License for more
|
|
||||||
** details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU Affero General Public License
|
|
||||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
** =============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scriptobjmodel.h"
|
|
||||||
|
|
||||||
ScriptObjModel::ScriptObjModel(asIScriptEngine *engine, asDebugger *debugger,
|
|
||||||
QObject *parent)
|
|
||||||
: QAbstractTableModel(parent), _engine(engine), _debugger(debugger) {
|
|
||||||
Q_ASSERT(engine && debugger);
|
|
||||||
_mod = engine->GetModule("Console", asGM_CREATE_IF_NOT_EXISTS);
|
|
||||||
Q_ASSERT(_mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptObjModel::updateData() {
|
|
||||||
this->beginResetModel();
|
|
||||||
_datas.reserve(_engine->GetGlobalPropertyCount() +
|
|
||||||
_mod->GetGlobalVarCount());
|
|
||||||
_datas.clear();
|
|
||||||
|
|
||||||
for (asUINT n = 0; n < _engine->GetGlobalPropertyCount(); n++) {
|
|
||||||
const char *name;
|
|
||||||
int typeId;
|
|
||||||
bool isConst;
|
|
||||||
void *v;
|
|
||||||
|
|
||||||
_engine->GetGlobalPropertyByIndex(n, &name, nullptr, &typeId, &isConst,
|
|
||||||
nullptr, &v);
|
|
||||||
|
|
||||||
Data d;
|
|
||||||
d.name = name;
|
|
||||||
d.type = (isConst ? QStringLiteral(" const ") : QStringLiteral(" ")) +
|
|
||||||
_engine->GetTypeDeclaration(typeId);
|
|
||||||
d.value = _debugger->toString(v, typeId, _engine);
|
|
||||||
|
|
||||||
_datas.append(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (asUINT n = 0; n < _mod->GetGlobalVarCount(); n++) {
|
|
||||||
const char *name;
|
|
||||||
int typeId;
|
|
||||||
bool isConst;
|
|
||||||
void *v;
|
|
||||||
|
|
||||||
_mod->GetGlobalVar(n, &name, nullptr, &typeId, &isConst);
|
|
||||||
v = _mod->GetAddressOfGlobalVar(n);
|
|
||||||
|
|
||||||
Data d;
|
|
||||||
d.name = name;
|
|
||||||
d.type = (isConst ? QStringLiteral(" const ") : QStringLiteral(" ")) +
|
|
||||||
_engine->GetTypeDeclaration(typeId);
|
|
||||||
d.value = _debugger->toString(v, typeId, _engine);
|
|
||||||
_datas.append(d);
|
|
||||||
}
|
|
||||||
this->endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ScriptObjModel::rowCount(const QModelIndex &parent) const {
|
|
||||||
Q_UNUSED(parent);
|
|
||||||
return _datas.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ScriptObjModel::columnCount(const QModelIndex &parent) const {
|
|
||||||
Q_UNUSED(parent);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ScriptObjModel::data(const QModelIndex &index, int role) const {
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole: {
|
|
||||||
auto d = _datas.at(index.row());
|
|
||||||
switch (index.column()) {
|
|
||||||
case 0:
|
|
||||||
return d.name;
|
|
||||||
case 1:
|
|
||||||
return d.type;
|
|
||||||
case 2:
|
|
||||||
return d.value;
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case Qt::TextAlignmentRole:
|
|
||||||
return int(Qt::AlignCenter);
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ScriptObjModel::headerData(int section, Qt::Orientation orientation,
|
|
||||||
int role) const {
|
|
||||||
if (role == Qt::DisplayRole) {
|
|
||||||
if (orientation == Qt::Horizontal) {
|
|
||||||
switch (section) {
|
|
||||||
case 0:
|
|
||||||
return tr("Name");
|
|
||||||
case 1:
|
|
||||||
return tr("Type");
|
|
||||||
case 2:
|
|
||||||
return tr("Value");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return section + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*==============================================================================
|
|
||||||
** Copyright (C) 2024-2027 WingSummer
|
|
||||||
**
|
|
||||||
** This program is free software: you can redistribute it and/or modify it under
|
|
||||||
** the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
** Software Foundation, version 3.
|
|
||||||
**
|
|
||||||
** This program 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 Affero General Public License for more
|
|
||||||
** details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU Affero General Public License
|
|
||||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
** =============================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SCRIPTOBJMODEL_H
|
|
||||||
#define SCRIPTOBJMODEL_H
|
|
||||||
|
|
||||||
#include "angelscript.h"
|
|
||||||
#include "class/asdebugger.h"
|
|
||||||
#include <QAbstractTableModel>
|
|
||||||
|
|
||||||
class ScriptObjModel : public QAbstractTableModel {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ScriptObjModel(asIScriptEngine *engine, asDebugger *debugger,
|
|
||||||
QObject *parent = nullptr);
|
|
||||||
|
|
||||||
void updateData();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Data {
|
|
||||||
QString name;
|
|
||||||
QString type;
|
|
||||||
QString value;
|
|
||||||
};
|
|
||||||
|
|
||||||
QList<Data> _datas;
|
|
||||||
|
|
||||||
// QAbstractItemModel interface
|
|
||||||
public:
|
|
||||||
virtual int rowCount(const QModelIndex &parent) const override;
|
|
||||||
virtual int columnCount(const QModelIndex &parent) const override;
|
|
||||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
|
||||||
virtual QVariant headerData(int section, Qt::Orientation orientation,
|
|
||||||
int role) const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
asIScriptEngine *_engine = nullptr;
|
|
||||||
asDebugger *_debugger = nullptr;
|
|
||||||
asIScriptModule *_mod = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SCRIPTOBJMODEL_H
|
|
Loading…
Reference in New Issue