fix: 修复完善和优化控制台;
This commit is contained in:
parent
6b020b7f70
commit
04551684d2
|
@ -1841,7 +1841,7 @@ void QEditor::paintEvent(QPaintEvent *e) {
|
|||
if (!m_doc)
|
||||
return;
|
||||
|
||||
auto p = new QPainter(viewport());
|
||||
QPainter p(viewport());
|
||||
const int yOffset = verticalOffset();
|
||||
const int xOffset = horizontalOffset();
|
||||
|
||||
|
@ -1855,7 +1855,7 @@ void QEditor::paintEvent(QPaintEvent *e) {
|
|||
// qDebug() << r;
|
||||
|
||||
// p.setClipping(false);
|
||||
p->translate(-xOffset, -yOffset);
|
||||
p.translate(-xOffset, -yOffset);
|
||||
|
||||
QDocument::PaintContext ctx;
|
||||
ctx.xoffset = xOffset;
|
||||
|
@ -1890,30 +1890,29 @@ void QEditor::paintEvent(QPaintEvent *e) {
|
|||
ctx.extra << m_dragAndDrop.handle();
|
||||
}
|
||||
|
||||
p->save();
|
||||
m_doc->draw(p, ctx);
|
||||
p->restore();
|
||||
p.save();
|
||||
m_doc->draw(&p, ctx);
|
||||
p.restore();
|
||||
|
||||
if (m_curPlaceHolder >= 0 && m_curPlaceHolder < m_placeHolders.count()) {
|
||||
const PlaceHolder &ph = m_placeHolders.at(m_curPlaceHolder);
|
||||
|
||||
p->setPen(Qt::red);
|
||||
p->drawConvexPolygon(ph.cursor.documentRegion());
|
||||
p.setPen(Qt::red);
|
||||
p.drawConvexPolygon(ph.cursor.documentRegion());
|
||||
|
||||
p->setPen(Qt::yellow);
|
||||
p.setPen(Qt::yellow);
|
||||
for (const QDocumentCursor &m : ph.mirrors) {
|
||||
if (m.isValid())
|
||||
p->drawConvexPolygon(m.documentRegion());
|
||||
p.drawConvexPolygon(m.documentRegion());
|
||||
}
|
||||
}
|
||||
|
||||
if (viewport()->height() > m_doc->height()) {
|
||||
p->fillRect(0, m_doc->height(), viewport()->width(),
|
||||
viewport()->height() - m_doc->height(), palette().base());
|
||||
p.fillRect(0, m_doc->height(), viewport()->width(),
|
||||
viewport()->height() - m_doc->height(), palette().base());
|
||||
}
|
||||
|
||||
p->end();
|
||||
delete p;
|
||||
p.end();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2252,7 +2251,7 @@ void QEditor::keyPressEvent(QKeyEvent *e) {
|
|||
// remanence of matches
|
||||
if (m_definition) {
|
||||
m_definition->clearMatches(m_doc);
|
||||
viewport()->repaint(); // force repaint in case of crash
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
bool hasPH = m_placeHolders.count() && m_curPlaceHolder != -1;
|
||||
|
@ -2610,7 +2609,7 @@ void QEditor::mouseDoubleClickEvent(QMouseEvent *e) {
|
|||
|
||||
repaintCursor();
|
||||
|
||||
viewport()->repaint();
|
||||
viewport()->update();
|
||||
} else {
|
||||
// qDebug("invalid cursor");
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -24,7 +24,17 @@
|
|||
|
||||
asBuilder::asBuilder(asIScriptEngine *engine) : AsPreprocesser(engine) {}
|
||||
|
||||
asBuilder::~asBuilder() {
|
||||
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;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
class asBuilder : public AsPreprocesser {
|
||||
public:
|
||||
explicit asBuilder(asIScriptEngine *engine);
|
||||
virtual ~asBuilder();
|
||||
|
||||
// Start a new module
|
||||
virtual int StartNewModule(const char *moduleName);
|
||||
|
|
|
@ -117,8 +117,11 @@ void asDebugger::lineCallback(asIScriptContext *ctx) {
|
|||
}
|
||||
};
|
||||
|
||||
qApp->processEvents();
|
||||
|
||||
switch (m_action) {
|
||||
case ABORT:
|
||||
ctx->Abort();
|
||||
return;
|
||||
case PAUSE:
|
||||
break;
|
||||
|
|
|
@ -21,22 +21,52 @@
|
|||
#include "AngelScript/sdk/angelscript/source/as_tokenizer.h"
|
||||
|
||||
QAsCodeParser::QAsCodeParser(asCScriptEngine *engine) : engine(engine) {
|
||||
Q_ASSERT(engine);
|
||||
checkValidTypes = false;
|
||||
isParsingAppInterface = false;
|
||||
}
|
||||
|
||||
QAsCodeParser::QAsCodeParser(asIScriptEngine *engine) {
|
||||
this->engine = dynamic_cast<asCScriptEngine *>(engine);
|
||||
Q_ASSERT(engine);
|
||||
checkValidTypes = false;
|
||||
isParsingAppInterface = false;
|
||||
}
|
||||
|
||||
QAsCodeParser::~QAsCodeParser() {}
|
||||
|
||||
QAsCodeParser::SymbolTable QAsCodeParser::preParse(const QByteArray &codes) {
|
||||
QAsCodeParser::SymbolTable QAsCodeParser::parse(const QByteArray &codes) {
|
||||
Reset();
|
||||
code = codes;
|
||||
ParseScript(false);
|
||||
return _symtable;
|
||||
|
||||
SymbolTable ret = _symtable;
|
||||
|
||||
if (!m_segs.isEmpty()) {
|
||||
// only add function signature as symbol
|
||||
// you can extend it with more features
|
||||
// PRS are welcomed.
|
||||
for (auto p = m_segs.constKeyValueBegin();
|
||||
p != m_segs.constKeyValueEnd(); ++p) {
|
||||
auto v = p->second;
|
||||
|
||||
Symbol fn;
|
||||
fn.type = SymbolType::Function;
|
||||
fn.name = v.name;
|
||||
fn.nameInSrc = v.nameInSrc;
|
||||
fn.content = v.args;
|
||||
fn.ns = v.ns;
|
||||
fn.typeStr = v.ret;
|
||||
ret.insert(p->first, fn);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QAsCodeParser::SymbolTable QAsCodeParser::parse(qsizetype offset,
|
||||
const QByteArray &codes) {
|
||||
preParse(codes);
|
||||
QAsCodeParser::SymbolTable QAsCodeParser::parseIntell(qsizetype offset,
|
||||
const QByteArray &codes) {
|
||||
parse(codes);
|
||||
// then we will parse the symbols we want
|
||||
|
||||
SymbolTable ret;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
class QAsCodeParser {
|
||||
public:
|
||||
QAsCodeParser(asCScriptEngine *engine);
|
||||
QAsCodeParser(asIScriptEngine *engine);
|
||||
~QAsCodeParser();
|
||||
|
||||
public:
|
||||
|
@ -100,9 +101,9 @@ private:
|
|||
QMap<qsizetype, CodeSegment> m_segs; // global functions
|
||||
|
||||
public:
|
||||
SymbolTable preParse(const QByteArray &codes);
|
||||
SymbolTable parse(const QByteArray &codes);
|
||||
|
||||
SymbolTable parse(qsizetype offset, const QByteArray &codes);
|
||||
SymbolTable parseIntell(qsizetype offset, const QByteArray &codes);
|
||||
|
||||
private:
|
||||
void ParseScript(bool inBlock);
|
||||
|
|
|
@ -37,6 +37,8 @@ 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(
|
||||
|
@ -51,34 +53,15 @@ bool ScriptConsoleMachine::execString(asIScriptEngine *engine,
|
|||
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("addfn "))) {
|
||||
auto fncmd = code.mid(6);
|
||||
asIScriptFunction *func = nullptr;
|
||||
int r = mod->CompileFunction("addfn", fncmd.toUtf8(), 0,
|
||||
asCOMP_ADD_TO_MODULE, &func);
|
||||
if (r < 0) {
|
||||
return false;
|
||||
} else {
|
||||
// The script engine supports function overloads, but to simplify
|
||||
// the console we'll disallow multiple functions with the same name.
|
||||
// We know the function was added, so if GetFunctionByName() fails
|
||||
// it is because there already was another function with the same
|
||||
// name.
|
||||
if (mod->GetFunctionByName(func->GetName()) == 0) {
|
||||
mod->RemoveFunction(func);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We must release the function object
|
||||
if (func) {
|
||||
func->Release();
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (code.startsWith(QStringLiteral("rmvar "))) {
|
||||
if (mod == nullptr || mod->GetGlobalVarCount() == 0) {
|
||||
return false;
|
||||
|
@ -95,24 +78,6 @@ bool ScriptConsoleMachine::execString(asIScriptEngine *engine,
|
|||
}
|
||||
}
|
||||
_model->updateData();
|
||||
return true;
|
||||
} else if (code.startsWith(QStringLiteral("rmfn "))) {
|
||||
if (mod == nullptr || mod->GetFunctionCount() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove the tailing semi-colons
|
||||
static QRegularExpression re(QStringLiteral(";+$"));
|
||||
|
||||
auto fncmd = code.mid(5).remove(re);
|
||||
for (auto &fn : fncmd.split(' ', Qt::SkipEmptyParts)) {
|
||||
asIScriptFunction *func = mod->GetFunctionByName(fn.toUtf8());
|
||||
if (func) {
|
||||
mod->RemoveFunction(func);
|
||||
}
|
||||
}
|
||||
engine->GarbageCollect();
|
||||
|
||||
return true;
|
||||
} else if (code.startsWith(QStringLiteral("lsfn"))) {
|
||||
if (code.trimmed().length() != 4) {
|
||||
|
@ -187,90 +152,6 @@ bool ScriptConsoleMachine::execString(asIScriptEngine *engine,
|
|||
emit onOutput(MessageType::Info, info);
|
||||
return true;
|
||||
} else {
|
||||
return ExecuteString(engine, code.toUtf8(), mod, immediateContext()) >=
|
||||
0;
|
||||
return ScriptMachine::executeCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
int ScriptConsoleMachine::ExecuteString(asIScriptEngine *engine,
|
||||
const char *code, asIScriptModule *mod,
|
||||
asIScriptContext *ctx) {
|
||||
return ExecuteString(engine, code, 0, asTYPEID_VOID, mod, ctx);
|
||||
}
|
||||
|
||||
ScriptObjModel *ScriptConsoleMachine::model() const { return _model; }
|
||||
|
||||
int ScriptConsoleMachine::ExecuteString(asIScriptEngine *engine,
|
||||
const char *code, void *ref,
|
||||
int refTypeId, asIScriptModule *mod,
|
||||
asIScriptContext *ctx) {
|
||||
// Wrap the code in a function so that it can be compiled and executed
|
||||
std::string funcCode = " ExecuteString() {\n";
|
||||
funcCode += code;
|
||||
funcCode += "\n}";
|
||||
|
||||
// Determine the return type based on the type of the ref arg
|
||||
funcCode = engine->GetTypeDeclaration(refTypeId, true) + funcCode;
|
||||
|
||||
// GetModule will free unused types, so to be on the safe side we'll
|
||||
// hold on to a reference to the type
|
||||
asITypeInfo *type = 0;
|
||||
if (refTypeId & asTYPEID_MASK_OBJECT) {
|
||||
type = engine->GetTypeInfoById(refTypeId);
|
||||
if (type)
|
||||
type->AddRef();
|
||||
}
|
||||
|
||||
// If no module was provided, get a dummy from the engine
|
||||
asIScriptModule *execMod =
|
||||
mod ? mod : engine->GetModule("ExecuteString", asGM_ALWAYS_CREATE);
|
||||
|
||||
// Now it's ok to release the type
|
||||
if (type)
|
||||
type->Release();
|
||||
|
||||
// Compile the function that can be executed
|
||||
asIScriptFunction *func = 0;
|
||||
int r = execMod->CompileFunction("ExecuteString", funcCode.c_str(), -1, 0,
|
||||
&func);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
// If no context was provided, request a new one from the engine
|
||||
asIScriptContext *execCtx = ctx ? ctx : engine->RequestContext();
|
||||
r = execCtx->Prepare(func);
|
||||
if (r >= 0) {
|
||||
// Execute the function
|
||||
r = execCtx->Execute();
|
||||
|
||||
// Unless the provided type was void retrieve it's value
|
||||
if (ref != 0 && refTypeId != asTYPEID_VOID) {
|
||||
if (refTypeId & asTYPEID_OBJHANDLE) {
|
||||
// Expect the pointer to be null to start with
|
||||
assert(*reinterpret_cast<void **>(ref) == 0);
|
||||
*reinterpret_cast<void **>(ref) = *reinterpret_cast<void **>(
|
||||
execCtx->GetAddressOfReturnValue());
|
||||
engine->AddRefScriptObject(*reinterpret_cast<void **>(ref),
|
||||
engine->GetTypeInfoById(refTypeId));
|
||||
} else if (refTypeId & asTYPEID_MASK_OBJECT) {
|
||||
// Use the registered assignment operator to do a value
|
||||
// assign. This assumes that the ref is pointing to a valid
|
||||
// object instance.
|
||||
engine->AssignScriptObject(ref,
|
||||
execCtx->GetAddressOfReturnValue(),
|
||||
engine->GetTypeInfoById(refTypeId));
|
||||
} else {
|
||||
// Copy the primitive value
|
||||
memcpy(ref, execCtx->GetAddressOfReturnValue(),
|
||||
engine->GetSizeOfPrimitiveType(refTypeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
func->Release();
|
||||
if (!ctx)
|
||||
engine->ReturnContext(execCtx);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -41,14 +41,6 @@ protected:
|
|||
private:
|
||||
bool execString(asIScriptEngine *engine, const QString &code);
|
||||
|
||||
// copy from helper
|
||||
int ExecuteString(asIScriptEngine *engine, const char *code,
|
||||
asIScriptModule *mod, asIScriptContext *ctx);
|
||||
|
||||
int ExecuteString(asIScriptEngine *engine, const char *code, void *ref,
|
||||
int refTypeId, asIScriptModule *mod,
|
||||
asIScriptContext *ctx);
|
||||
|
||||
private:
|
||||
ScriptObjModel *_model = nullptr;
|
||||
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
#include "AngelScript/sdk/add_on/scriptmath/scriptmath.h"
|
||||
#include "AngelScript/sdk/add_on/scriptmath/scriptmathcomplex.h"
|
||||
#include "AngelScript/sdk/add_on/weakref/weakref.h"
|
||||
|
||||
#include "angelobjstring.h"
|
||||
#include "class/asbuilder.h"
|
||||
#include "class/qascodeparser.h"
|
||||
#include "define.h"
|
||||
#include "plugin/pluginsystem.h"
|
||||
#include "scriptaddon/scriptcolor.h"
|
||||
|
@ -34,16 +37,9 @@
|
|||
#include "scriptaddon/scriptqstring.h"
|
||||
#include "scriptaddon/scriptregex.h"
|
||||
|
||||
#include "angelobjstring.h"
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
ScriptMachine::~ScriptMachine() {
|
||||
if (_immediateContext) {
|
||||
_immediateContext->Release();
|
||||
_immediateContext = nullptr;
|
||||
}
|
||||
|
||||
if (_ctxMgr) {
|
||||
delete _ctxMgr;
|
||||
}
|
||||
|
@ -55,10 +51,6 @@ bool ScriptMachine::inited() { return _engine != nullptr; }
|
|||
|
||||
bool ScriptMachine::isRunning() const { return _ctxMgr->isRunning(); }
|
||||
|
||||
bool ScriptMachine::isInDebugMode() const {
|
||||
return _debugger->getEngine() != nullptr;
|
||||
}
|
||||
|
||||
bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
||||
if (engine == nullptr) {
|
||||
return false;
|
||||
|
@ -75,6 +67,7 @@ bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
|||
engine->SetEngineProperty(asEP_ALTER_SYNTAX_NAMED_ARGS, 0);
|
||||
engine->SetEngineProperty(asEP_ALLOW_UNICODE_IDENTIFIERS, true);
|
||||
engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true); // enum class like
|
||||
setDebugMode(false);
|
||||
|
||||
// The script compiler will send any compiler messages to the callback
|
||||
auto r = engine->SetMessageCallback(asFUNCTION(messageCallback), this,
|
||||
|
@ -191,10 +184,6 @@ bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
|||
|
||||
PluginSystem::instance().angelApi()->installAPI(this);
|
||||
|
||||
_immediateContext = engine->CreateContext();
|
||||
_immediateContext->SetExceptionCallback(
|
||||
asMETHOD(ScriptMachine, exceptionCallback), this, asCALL_THISCALL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -277,6 +266,7 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
// 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);
|
||||
setDebugMode(isInDebug);
|
||||
|
||||
asBuilder builder(_engine);
|
||||
|
||||
|
@ -348,6 +338,8 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
// The context manager will request the context from the
|
||||
// pool, which will automatically attach the debugger
|
||||
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback), this,
|
||||
asCALL_THISCALL);
|
||||
|
||||
// Execute the script until completion
|
||||
// The script may create co-routines. These will automatically
|
||||
|
@ -404,16 +396,23 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
_ctxPool.clear();
|
||||
|
||||
// Detach debugger
|
||||
Q_ASSERT(_debugger);
|
||||
_debugger->setEngine(nullptr);
|
||||
|
||||
if (isInDebug) {
|
||||
Q_ASSERT(_debugger);
|
||||
_debugger->setEngine(nullptr);
|
||||
_debugger->clearBreakPoint();
|
||||
setDebugMode(false);
|
||||
emit onDebugFinished();
|
||||
}
|
||||
|
||||
return r >= 0;
|
||||
}
|
||||
|
||||
void ScriptMachine::abortScript() {
|
||||
if (_debugger->getEngine()) {
|
||||
_debugger->runDebugAction(asDebugger::ABORT);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptMachine::messageCallback(const asSMessageInfo *msg, void *param) {
|
||||
MessageType t = MessageType::Print;
|
||||
switch (msg->type) {
|
||||
|
@ -1614,17 +1613,141 @@ void ScriptMachine::registerEngineAddon(asIScriptEngine *engine) {
|
|||
RegisterExceptionRoutines(engine);
|
||||
}
|
||||
|
||||
asIScriptEngine *ScriptMachine::engine() const { return _engine; }
|
||||
|
||||
asIScriptContext *ScriptMachine::immediateContext() const {
|
||||
return _immediateContext;
|
||||
bool ScriptMachine::isDebugMode() const {
|
||||
return !_engine->GetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES);
|
||||
}
|
||||
|
||||
void ScriptMachine::setDebugMode(bool isDbg) {
|
||||
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, !isDbg);
|
||||
}
|
||||
|
||||
asIScriptEngine *ScriptMachine::engine() const { return _engine; }
|
||||
|
||||
asDebugger *ScriptMachine::debugger() const { return _debugger; }
|
||||
|
||||
bool ScriptMachine::executeCode(const QString &code) {
|
||||
return ExecuteString(
|
||||
_engine, code.toUtf8(),
|
||||
_engine->GetModule("Console", asGM_CREATE_IF_NOT_EXISTS),
|
||||
_immediateContext) >= 0;
|
||||
// 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);
|
||||
setDebugMode(false);
|
||||
|
||||
asIScriptModule *mod = _engine->GetModule("Console", asGM_ONLY_IF_EXISTS);
|
||||
if (!mod) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// first, preparse the code
|
||||
QAsCodeParser parser(_engine);
|
||||
auto ccode = code.toUtf8();
|
||||
|
||||
asIScriptFunction *func = nullptr;
|
||||
|
||||
auto ret = parser.parse(ccode);
|
||||
// check whether there is any enum/class
|
||||
if (ret.isEmpty()) {
|
||||
// ok, wrap the codes
|
||||
ccode.prepend("void main(){").append("}");
|
||||
// start to compile
|
||||
auto r = mod->CompileFunction(nullptr, ccode, -1, 0, &func);
|
||||
if (r < 0) {
|
||||
MessageInfo info;
|
||||
info.message = tr("Script failed to build");
|
||||
emit onOutput(MessageType::Error, info);
|
||||
mod->Discard();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
mod->AddScriptSection("Runner", ccode, ccode.size(), 0);
|
||||
|
||||
auto r = mod->Build();
|
||||
if (r < 0) {
|
||||
MessageInfo info;
|
||||
info.message = tr("Script failed to build");
|
||||
emit onOutput(MessageType::Error, info);
|
||||
mod->Discard();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the main function
|
||||
func = mod->GetFunctionByDecl("void main()");
|
||||
if (func == nullptr) {
|
||||
// Try again with "int main()"
|
||||
func = mod->GetFunctionByDecl("int main()");
|
||||
}
|
||||
|
||||
if (func == nullptr) {
|
||||
MessageInfo info;
|
||||
info.message = tr("Cannot find 'int main()' or 'void main()'");
|
||||
emit onOutput(MessageType::Error, info);
|
||||
mod->Discard();
|
||||
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
|
||||
// The context manager will request the context from the
|
||||
// pool, which will automatically attach the debugger
|
||||
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback), this,
|
||||
asCALL_THISCALL);
|
||||
|
||||
// Execute the script until completion
|
||||
// The script may create co-routines. These will automatically
|
||||
// be managed by the context manager
|
||||
while (_ctxMgr->ExecuteScripts())
|
||||
;
|
||||
|
||||
// Check if the main script finished normally
|
||||
int r = ctx->GetState();
|
||||
if (r != asEXECUTION_FINISHED) {
|
||||
if (r == asEXECUTION_EXCEPTION) {
|
||||
MessageInfo info;
|
||||
info.message = tr("The script failed with an exception") +
|
||||
QStringLiteral("\n") +
|
||||
QString::fromStdString(GetExceptionInfo(ctx, true));
|
||||
emit onOutput(MessageType::Error, info);
|
||||
r = -1;
|
||||
} else if (r == asEXECUTION_ABORTED) {
|
||||
MessageInfo info;
|
||||
info.message = tr("The script was aborted");
|
||||
emit onOutput(MessageType::Error, info);
|
||||
r = -1;
|
||||
} else {
|
||||
auto e = QMetaEnum::fromType<asEContextState>();
|
||||
MessageInfo info;
|
||||
info.message = tr("The script terminated unexpectedly") +
|
||||
QStringLiteral(" (") + e.valueToKey(r) +
|
||||
QStringLiteral(")");
|
||||
emit onOutput(MessageType::Error, info);
|
||||
r = -1;
|
||||
}
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
|
||||
// Return the context after retrieving the return value
|
||||
_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();
|
||||
|
||||
// Release all contexts that have been allocated
|
||||
for (auto ctx : _ctxPool) {
|
||||
ctx->Release();
|
||||
}
|
||||
|
||||
_ctxPool.clear();
|
||||
|
||||
// Detach debugger
|
||||
Q_ASSERT(_debugger);
|
||||
_debugger->setEngine(nullptr);
|
||||
|
||||
return r >= 0;
|
||||
}
|
||||
|
|
|
@ -87,12 +87,8 @@ public:
|
|||
|
||||
bool isRunning() const;
|
||||
|
||||
bool isInDebugMode() const;
|
||||
|
||||
asDebugger *debugger() const;
|
||||
|
||||
asIScriptContext *immediateContext() const;
|
||||
|
||||
asIScriptEngine *engine() const;
|
||||
|
||||
bool insteadFoundDisabled() const;
|
||||
|
@ -100,10 +96,19 @@ public:
|
|||
|
||||
static void registerEngineAddon(asIScriptEngine *engine);
|
||||
|
||||
// debug or release?
|
||||
bool isDebugMode() const;
|
||||
void setDebugMode(bool isDbg);
|
||||
|
||||
public slots:
|
||||
virtual bool executeCode(const QString &code);
|
||||
virtual bool executeScript(const QString &script, bool isInDebug = false);
|
||||
|
||||
void abortScript();
|
||||
|
||||
private:
|
||||
bool execute(const QString &code, bool isInDebug = false);
|
||||
|
||||
protected:
|
||||
virtual bool configureEngine(asIScriptEngine *engine);
|
||||
|
||||
|
@ -165,8 +170,6 @@ private:
|
|||
QVector<asITypeInfo *> _rtypes;
|
||||
std::function<QString(void)> _getInputFn;
|
||||
|
||||
asIScriptContext *_immediateContext = nullptr;
|
||||
|
||||
bool m_insteadFoundDisabled = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -246,6 +246,7 @@ WingCStruct::RegisteredEvents WingCStruct::registeredEvents() const {
|
|||
RegisteredEvents evs;
|
||||
evs.setFlag(RegisteredEvent::ScriptUnSafeFnRegistering);
|
||||
evs.setFlag(RegisteredEvent::ScriptPragma);
|
||||
evs.setFlag(RegisteredEvent::ScriptPragmaInit);
|
||||
return evs;
|
||||
}
|
||||
|
||||
|
@ -318,6 +319,8 @@ bool WingCStruct::eventOnScriptPragma(const QString &script,
|
|||
return false;
|
||||
}
|
||||
|
||||
void WingCStruct::eventOnScriptPragmaInit() { resetEnv(); }
|
||||
|
||||
QHash<QString, WingHex::IWingPlugin::UNSAFE_SCFNPTR>
|
||||
WingCStruct::registeredScriptUnsafeFns() const {
|
||||
return _scriptUnsafe;
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
virtual QHash<QString, ScriptFnInfo> registeredScriptFns() const override;
|
||||
virtual bool eventOnScriptPragma(const QString &script,
|
||||
const QStringList &comments) override;
|
||||
virtual void eventOnScriptPragmaInit() override;
|
||||
virtual QHash<QString, UNSAFE_SCFNPTR>
|
||||
registeredScriptUnsafeFns() const override;
|
||||
|
||||
|
|
|
@ -570,7 +570,7 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path,
|
|||
}
|
||||
}
|
||||
|
||||
if (doc->isUndoByteModified() || isNewFile()) {
|
||||
if (doc->isUndoByteModified() || m_fileName != fileName || isNewFile()) {
|
||||
if (m_docType == DocumentType::Extension) {
|
||||
if (_dev->isOpen()) {
|
||||
_dev->close();
|
||||
|
|
|
@ -21,13 +21,9 @@
|
|||
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
#include <QShortcut>
|
||||
#include <QKeyEvent>
|
||||
|
||||
ScriptingConsole::ScriptingConsole(QWidget *parent) : QConsoleWidget(parent) {
|
||||
auto shortCut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_L), this);
|
||||
connect(shortCut, &QShortcut::activated, this,
|
||||
&ScriptingConsole::clearConsole);
|
||||
}
|
||||
ScriptingConsole::ScriptingConsole(QWidget *parent) : QConsoleWidget(parent) {}
|
||||
|
||||
ScriptingConsole::~ScriptingConsole() {}
|
||||
|
||||
|
@ -49,6 +45,8 @@ void ScriptingConsole::init() {
|
|||
_sp = new ScriptConsoleMachine(_getInputFn, this);
|
||||
connect(_sp, &ScriptConsoleMachine::onClearConsole, this,
|
||||
&ScriptingConsole::clear);
|
||||
connect(this, &ScriptingConsole::abortEvaluation, _sp,
|
||||
&ScriptConsoleMachine::abortScript);
|
||||
|
||||
connect(_sp, &ScriptConsoleMachine::onOutput, this,
|
||||
[=](ScriptConsoleMachine::MessageType type,
|
||||
|
@ -157,6 +155,14 @@ QString ScriptingConsole::getInput() {
|
|||
return instr;
|
||||
}
|
||||
|
||||
void ScriptingConsole::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->modifiers() == Qt::ControlModifier && e->key() == Qt::Key_L) {
|
||||
clearConsole();
|
||||
} else {
|
||||
QConsoleWidget::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptingConsole::appendCommandPrompt(bool storeOnly) {
|
||||
QString commandPrompt;
|
||||
|
||||
|
@ -167,7 +173,7 @@ void ScriptingConsole::appendCommandPrompt(bool storeOnly) {
|
|||
if (!cursor.atBlockStart()) {
|
||||
commandPrompt = QStringLiteral("\n");
|
||||
}
|
||||
if (_sp && _sp->isInDebugMode()) {
|
||||
if (_sp && _sp->isDebugMode()) {
|
||||
commandPrompt += QStringLiteral("[dbg] > ");
|
||||
} else {
|
||||
commandPrompt += QStringLiteral("as > ");
|
||||
|
|
|
@ -58,6 +58,9 @@ private:
|
|||
|
||||
QString getInput();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
private:
|
||||
ScriptConsoleMachine *_sp = nullptr;
|
||||
QTextStream _s;
|
||||
|
|
|
@ -2146,13 +2146,22 @@ void MainWindow::on_saveas() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto filename = WingFileDialog::getSaveFileName(this, tr("ChooseSaveFile"),
|
||||
m_lastusedpath);
|
||||
QString lastpath;
|
||||
if (editor->isNewFile() || editor->isExtensionFile() ||
|
||||
editor->isDriver()) {
|
||||
lastpath = m_lastusedpath;
|
||||
} else {
|
||||
lastpath = editor->fileName();
|
||||
}
|
||||
|
||||
auto filename =
|
||||
WingFileDialog::getSaveFileName(this, tr("ChooseSaveFile"), lastpath);
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
m_lastusedpath = QFileInfo(filename).absoluteDir().absolutePath();
|
||||
|
||||
auto res = saveEditor(editor, filename, false);
|
||||
bool isWorkspace = editor->isOriginWorkSpace();
|
||||
auto res = saveEditor(editor, filename, false, false, isWorkspace);
|
||||
|
||||
restart:
|
||||
switch (res) {
|
||||
|
@ -2161,6 +2170,7 @@ restart:
|
|||
tr("SaveSuccessfully"));
|
||||
RecentFileManager::RecentInfo info;
|
||||
info.fileName = filename;
|
||||
info.isWorkSpace = isWorkspace;
|
||||
m_recentmanager->addRecentFile(info);
|
||||
break;
|
||||
}
|
||||
|
@ -3704,7 +3714,7 @@ ErrFile MainWindow::saveEditor(EditorView *editor, const QString &filename,
|
|||
auto oldName = editor->fileName();
|
||||
|
||||
QString workspace = m_views.value(editor);
|
||||
if (workspace.isEmpty()) {
|
||||
if (forceWorkspace || workspace.isEmpty()) {
|
||||
if (forceWorkspace || editor->change2WorkSpace()) {
|
||||
QString curFile;
|
||||
if (!editor->isDriver() && !editor->isExtensionFile()) {
|
||||
|
@ -4048,6 +4058,12 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
|||
return;
|
||||
}
|
||||
|
||||
// then checking the scripting console
|
||||
auto sm = m_scriptConsole->consoleMachine();
|
||||
if (sm->isRunning()) {
|
||||
sm->abortScript();
|
||||
}
|
||||
|
||||
// then checking itself
|
||||
if (!m_views.isEmpty()) {
|
||||
QStringList unSavedFiles;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "class/wingfiledialog.h"
|
||||
#include "class/wingmessagebox.h"
|
||||
#include "control/toast.h"
|
||||
#include "plugin/pluginsystem.h"
|
||||
#include "qcodeeditwidget/qeditconfig.h"
|
||||
#include "qcodeeditwidget/qformatconfig.h"
|
||||
#include "qdocumentline.h"
|
||||
|
@ -552,7 +553,7 @@ RibbonTabContent *ScriptingDialog::buildDebugPage(RibbonTabContent *tab) {
|
|||
bool isPaused = false;
|
||||
if (runner) {
|
||||
isRun = runner->isRunning();
|
||||
isDbg = runner->isInDebugMode();
|
||||
isDbg = runner->isDebugMode();
|
||||
auto dbg = runner->debugger();
|
||||
isPaused = dbg->currentState() == asDebugger::PAUSE;
|
||||
}
|
||||
|
@ -792,7 +793,7 @@ void ScriptingDialog::registerEditorView(ScriptEditor *editor) {
|
|||
Q_ASSERT(m_views.contains(editor));
|
||||
|
||||
auto m = m_consoleout->machine();
|
||||
if (m->isInDebugMode() && _DebugingScript == editor->fileName()) {
|
||||
if (m->isDebugMode() && _DebugingScript == editor->fileName()) {
|
||||
if (WingMessageBox::warning(
|
||||
this, this->windowTitle(), tr("ScriptStillRunning"),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
||||
|
@ -836,6 +837,7 @@ void ScriptingDialog::registerEditorView(ScriptEditor *editor) {
|
|||
}
|
||||
|
||||
editor->deleteDockWidget();
|
||||
updateEditModeEnabled();
|
||||
});
|
||||
|
||||
LangService::instance().applyLanguageSerivce(editor->editor());
|
||||
|
@ -929,7 +931,7 @@ void ScriptingDialog::updateRunDebugMode(bool disable) {
|
|||
bool isPaused = false;
|
||||
if (runner) {
|
||||
isRun = runner->isRunning();
|
||||
isDbg = runner->isInDebugMode();
|
||||
isDbg = runner->isDebugMode();
|
||||
auto dbg = runner->debugger();
|
||||
isPaused = dbg->currentState() == asDebugger::PAUSE;
|
||||
}
|
||||
|
@ -987,7 +989,7 @@ void ScriptingDialog::setCurrentEditorScale(qreal rate) {
|
|||
|
||||
bool ScriptingDialog::isCurrentDebugging() const {
|
||||
auto m = m_consoleout->machine();
|
||||
return m && m->isInDebugMode();
|
||||
return m && m->isDebugMode();
|
||||
}
|
||||
|
||||
ScriptEditor *ScriptingDialog::openFile(const QString &filename) {
|
||||
|
@ -1014,7 +1016,7 @@ ScriptEditor *ScriptingDialog::openFile(const QString &filename) {
|
|||
void ScriptingDialog::runDbgCommand(asDebugger::DebugAction action) {
|
||||
updateRunDebugMode(true);
|
||||
auto machine = m_consoleout->machine();
|
||||
if (machine->isInDebugMode()) {
|
||||
if (machine->isDebugMode()) {
|
||||
auto dbg = machine->debugger();
|
||||
dbg->runDebugAction(action);
|
||||
}
|
||||
|
@ -1043,6 +1045,8 @@ void ScriptingDialog::startDebugScript(const QString &fileName) {
|
|||
m_consoleout->clear();
|
||||
|
||||
_DebugingScript = fileName;
|
||||
PluginSystem::instance().dispatchEvent(
|
||||
IWingPlugin::RegisteredEvent::ScriptPragmaInit, {});
|
||||
m_consoleout->machine()->executeScript(fileName, true);
|
||||
|
||||
updateRunDebugMode();
|
||||
|
@ -1054,7 +1058,7 @@ void ScriptingDialog::addBreakPoint(QEditor *editor, int lineIndex) {
|
|||
auto curLine = lineIndex + 1;
|
||||
auto dbg = m_consoleout->machine()->debugger();
|
||||
|
||||
if (m_consoleout->machine()->isInDebugMode()) {
|
||||
if (m_consoleout->machine()->isDebugMode()) {
|
||||
auto line = editor->document()->line(lineIndex);
|
||||
auto hitCur = m_symID.value(Symbols::DbgRunHitBreakPoint);
|
||||
auto curSym = m_symID.value(Symbols::DbgRunCurrentLine);
|
||||
|
@ -1084,7 +1088,7 @@ void ScriptingDialog::removeBreakPoint(QEditor *editor, int lineIndex) {
|
|||
auto curLine = lineIndex + 1;
|
||||
|
||||
auto dbg = m_consoleout->machine()->debugger();
|
||||
if (m_consoleout->machine()->isInDebugMode()) {
|
||||
if (m_consoleout->machine()->isDebugMode()) {
|
||||
auto line = editor->document()->line(lineIndex);
|
||||
auto hitCur = m_symID.value(Symbols::DbgRunHitBreakPoint);
|
||||
auto curSym = m_symID.value(Symbols::DbgRunCurrentLine);
|
||||
|
@ -1113,7 +1117,7 @@ void ScriptingDialog::toggleBreakPoint(QEditor *editor, int lineIndex) {
|
|||
auto curLine = lineIndex + 1;
|
||||
|
||||
auto dbg = m_consoleout->machine()->debugger();
|
||||
if (m_consoleout->machine()->isInDebugMode()) {
|
||||
if (m_consoleout->machine()->isDebugMode()) {
|
||||
auto line = editor->document()->line(lineIndex);
|
||||
auto bpMark = m_symID.value(Symbols::BreakPoint);
|
||||
auto hitCur = m_symID.value(Symbols::DbgRunHitBreakPoint);
|
||||
|
@ -1225,6 +1229,11 @@ void ScriptingDialog::on_save() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (editor->fileName().isEmpty()) {
|
||||
on_saveas();
|
||||
return;
|
||||
}
|
||||
|
||||
auto res = editor->save();
|
||||
if (res) {
|
||||
Toast::toast(this, NAMEICONRES(QStringLiteral("save")),
|
||||
|
@ -1241,6 +1250,11 @@ void ScriptingDialog::on_saveas() {
|
|||
return;
|
||||
}
|
||||
|
||||
QString lastPath = editor->fileName();
|
||||
if (lastPath.isEmpty()) {
|
||||
lastPath = m_lastusedpath;
|
||||
}
|
||||
|
||||
auto filename = WingFileDialog::getSaveFileName(
|
||||
this, tr("ChooseSaveFile"), m_lastusedpath,
|
||||
QStringLiteral("AngelScript (*.as *.angelscript)"));
|
||||
|
@ -1383,6 +1397,8 @@ void ScriptingDialog::on_runscript() {
|
|||
return;
|
||||
}
|
||||
m_consoleout->clear();
|
||||
PluginSystem::instance().dispatchEvent(
|
||||
IWingPlugin::RegisteredEvent::ScriptPragmaInit, {});
|
||||
m_consoleout->machine()->executeScript(e->fileName());
|
||||
updateRunDebugMode();
|
||||
}
|
||||
|
|
|
@ -477,6 +477,7 @@ public:
|
|||
PluginFileOpened = 1u << 9,
|
||||
PluginFileClosed = 1u << 10,
|
||||
ScriptUnSafeFnRegistering = 1u << 11,
|
||||
ScriptPragmaInit = 1u << 12
|
||||
};
|
||||
Q_DECLARE_FLAGS(RegisteredEvents, RegisteredEvent)
|
||||
|
||||
|
@ -591,6 +592,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual void eventOnScriptPragmaInit() {}
|
||||
|
||||
signals:
|
||||
bool existsServiceHost(const QString &puid);
|
||||
|
||||
|
|
|
@ -475,6 +475,12 @@ bool PluginSystem::dispatchEvent(IWingPlugin::RegisteredEvent event,
|
|||
}
|
||||
return (*r)->eventOnScriptPragma(section, params.at(3).toStringList());
|
||||
} break;
|
||||
case WingHex::IWingPlugin::RegisteredEvent::ScriptPragmaInit: {
|
||||
Q_ASSERT(params.isEmpty());
|
||||
for (auto &plg : _evplgs[event]) {
|
||||
plg->eventOnScriptPragmaInit();
|
||||
}
|
||||
} break;
|
||||
case WingHex::IWingPlugin::RegisteredEvent::PluginFileOpened: {
|
||||
Q_ASSERT(params.size() == 4);
|
||||
auto plg =
|
||||
|
@ -893,6 +899,10 @@ void PluginSystem::registerEvents(IWingPlugin *plg) {
|
|||
_evplgs[IWingPlugin::RegisteredEvent::ScriptPragma].append(plg);
|
||||
}
|
||||
|
||||
if (evs.testFlag(IWingPlugin::RegisteredEvent::ScriptPragmaInit)) {
|
||||
_evplgs[IWingPlugin::RegisteredEvent::ScriptPragmaInit].append(plg);
|
||||
}
|
||||
|
||||
if (evs.testFlag(IWingPlugin::RegisteredEvent::PluginFileOpened)) {
|
||||
_evplgs[IWingPlugin::RegisteredEvent::PluginFileOpened].append(plg);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue