fix: 更好的代码填充和一些 Bug 修复;
This commit is contained in:
parent
2ee3051a7d
commit
cf3d4da8e8
|
@ -109,6 +109,15 @@ QString QConsoleWidget::getCommandLine() {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QConsoleWidget::paste() {
|
||||||
|
QTextCursor textCursor = this->textCursor();
|
||||||
|
const QMimeData *const clipboard = QApplication::clipboard()->mimeData();
|
||||||
|
const QString text = clipboard->text();
|
||||||
|
if (!text.isNull()) {
|
||||||
|
textCursor.insertText(text, channelCharFormat(StandardInput));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QConsoleWidget::handleReturnKey() {
|
void QConsoleWidget::handleReturnKey() {
|
||||||
QString code = getCommandLine();
|
QString code = getCommandLine();
|
||||||
|
|
||||||
|
@ -189,12 +198,7 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
|
||||||
// Allow paste only if the selection is in the interactive area ...
|
// Allow paste only if the selection is in the interactive area ...
|
||||||
if (e->key() == Qt::Key_V && e->modifiers() == Qt::ControlModifier) {
|
if (e->key() == Qt::Key_V && e->modifiers() == Qt::ControlModifier) {
|
||||||
if (selectionInEditZone || isCursorInEditZone()) {
|
if (selectionInEditZone || isCursorInEditZone()) {
|
||||||
const QMimeData *const clipboard =
|
paste();
|
||||||
QApplication::clipboard()->mimeData();
|
|
||||||
const QString text = clipboard->text();
|
|
||||||
if (!text.isNull()) {
|
|
||||||
textCursor.insertText(text, channelCharFormat(StandardInput));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e->accept();
|
e->accept();
|
||||||
|
|
|
@ -77,6 +77,8 @@ public:
|
||||||
// get the current command line
|
// get the current command line
|
||||||
QString getCommandLine();
|
QString getCommandLine();
|
||||||
|
|
||||||
|
virtual void paste();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
// write to StandardOutput
|
// write to StandardOutput
|
||||||
|
@ -94,6 +96,7 @@ signals:
|
||||||
protected:
|
protected:
|
||||||
bool canPaste() const;
|
bool canPaste() const;
|
||||||
bool canCut() const;
|
bool canCut() const;
|
||||||
|
|
||||||
virtual void handleReturnKey();
|
virtual void handleReturnKey();
|
||||||
virtual void handleTabKey();
|
virtual void handleTabKey();
|
||||||
// reimp QPlainTextEdit functions
|
// reimp QPlainTextEdit functions
|
||||||
|
|
|
@ -253,8 +253,6 @@ set(CLASS_SRC
|
||||||
src/class/ascompletion.h
|
src/class/ascompletion.h
|
||||||
src/class/asbuilder.h
|
src/class/asbuilder.h
|
||||||
src/class/asbuilder.cpp
|
src/class/asbuilder.cpp
|
||||||
src/class/ascontextmgr.h
|
|
||||||
src/class/ascontextmgr.cpp
|
|
||||||
src/class/clangformatmanager.h
|
src/class/clangformatmanager.h
|
||||||
src/class/clangformatmanager.cpp
|
src/class/clangformatmanager.cpp
|
||||||
src/class/aspreprocesser.h
|
src/class/aspreprocesser.h
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -45,6 +45,8 @@ AppManager::AppManager(int &argc, char *argv[])
|
||||||
: QtSingleApplication(argc, argv) {
|
: QtSingleApplication(argc, argv) {
|
||||||
ASSERT_SINGLETON;
|
ASSERT_SINGLETON;
|
||||||
|
|
||||||
|
_instance = this;
|
||||||
|
|
||||||
LanguageManager::instance();
|
LanguageManager::instance();
|
||||||
InspectQtLogHelper::instance().init();
|
InspectQtLogHelper::instance().init();
|
||||||
CrashHandler::instance().init();
|
CrashHandler::instance().init();
|
||||||
|
@ -102,6 +104,8 @@ AppManager::AppManager(int &argc, char *argv[])
|
||||||
his.add(cmd);
|
his.add(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_timer.start();
|
||||||
|
|
||||||
_w = new MainWindow(splash);
|
_w = new MainWindow(splash);
|
||||||
|
|
||||||
setActivationWindow(_w);
|
setActivationWindow(_w);
|
||||||
|
@ -133,7 +137,6 @@ AppManager::AppManager(int &argc, char *argv[])
|
||||||
|
|
||||||
connect(_w, &MainWindow::closed, this,
|
connect(_w, &MainWindow::closed, this,
|
||||||
[]() { AppManager::instance()->exit(); });
|
[]() { AppManager::instance()->exit(); });
|
||||||
_instance = this;
|
|
||||||
|
|
||||||
if (splash)
|
if (splash)
|
||||||
splash->close();
|
splash->close();
|
||||||
|
@ -152,6 +155,8 @@ AppManager *AppManager::instance() { return _instance; }
|
||||||
|
|
||||||
MainWindow *AppManager::mainWindow() const { return _w; }
|
MainWindow *AppManager::mainWindow() const { return _w; }
|
||||||
|
|
||||||
|
uint AppManager::currentMSecsSinceEpoch() { return _timer.elapsed(); }
|
||||||
|
|
||||||
void AppManager::openFile(const QString &file, bool autoDetect) {
|
void AppManager::openFile(const QString &file, bool autoDetect) {
|
||||||
EditorView *editor = nullptr;
|
EditorView *editor = nullptr;
|
||||||
Q_ASSERT(_w);
|
Q_ASSERT(_w);
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "dialog/mainwindow.h"
|
#include "dialog/mainwindow.h"
|
||||||
#include "qtsingleapplication/src/qtsingleapplication.h"
|
#include "qtsingleapplication/src/qtsingleapplication.h"
|
||||||
|
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
class AppManager : public QtSingleApplication {
|
class AppManager : public QtSingleApplication {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -36,6 +38,8 @@ public:
|
||||||
QApplication::tr("WingCloudStudio");
|
QApplication::tr("WingCloudStudio");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint currentMSecsSinceEpoch();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void openFile(const QString &file, bool autoDetect = true);
|
void openFile(const QString &file, bool autoDetect = true);
|
||||||
void openRawFile(const QString &file);
|
void openRawFile(const QString &file);
|
||||||
|
@ -43,6 +47,8 @@ public slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MainWindow *_w = nullptr;
|
MainWindow *_w = nullptr;
|
||||||
|
QElapsedTimer _timer;
|
||||||
|
|
||||||
static AppManager *_instance;
|
static AppManager *_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "wingcodeedit.h"
|
#include "wingcodeedit.h"
|
||||||
|
|
||||||
#include <QAbstractItemView>
|
#include <QAbstractItemView>
|
||||||
|
#include <QApplication>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
|
@ -41,8 +42,7 @@ 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(WingCodeEdit *p)
|
AsCompletion::AsCompletion(WingCodeEdit *p)
|
||||||
: WingCompleter(p), parser(ScriptMachine::instance().engine()),
|
: WingCompleter(p), parser(ScriptMachine::instance().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,
|
||||||
|
@ -126,10 +126,43 @@ void AsCompletion::applyClassNodes(QList<CodeInfoTip> &nodes) {
|
||||||
nodes = clsNodes;
|
nodes = clsNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsCompletion::parseDocument() const { return m_parseDocument; }
|
int AsCompletion::includeCallBack(const QString &include, bool quotedInclude,
|
||||||
|
const QString &from, AsPreprocesser *builder,
|
||||||
|
void *userParam) {
|
||||||
|
Q_UNUSED(userParam);
|
||||||
|
|
||||||
void AsCompletion::setParseDocument(bool newParseDocument) {
|
QFileInfo info(include);
|
||||||
m_parseDocument = newParseDocument;
|
bool isAbsolute = info.isAbsolute();
|
||||||
|
bool hasNoExt = info.suffix().isEmpty();
|
||||||
|
QString inc;
|
||||||
|
if (quotedInclude) {
|
||||||
|
if (isAbsolute) {
|
||||||
|
inc = include;
|
||||||
|
} else {
|
||||||
|
auto pwd = QFileInfo(from).absoluteDir();
|
||||||
|
inc = pwd.absoluteFilePath(include);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// absolute include is not allowed in #include<>
|
||||||
|
if (isAbsolute) {
|
||||||
|
// ignored in code completion
|
||||||
|
return asSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir dir(qApp->applicationDirPath());
|
||||||
|
if (!dir.cd(QStringLiteral("aslib"))) {
|
||||||
|
// someone crash the software, ignored
|
||||||
|
return asSUCCESS;
|
||||||
|
}
|
||||||
|
inc = dir.absoluteFilePath(include);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasNoExt) {
|
||||||
|
inc += QStringLiteral(".as");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder->loadSectionFromFile(inc);
|
||||||
|
return asSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsCompletion::clearFunctionTip() { emit onFunctionTip({}); }
|
void AsCompletion::clearFunctionTip() { emit onFunctionTip({}); }
|
||||||
|
@ -235,10 +268,7 @@ bool AsCompletion::processTrigger(const QString &trigger,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<CodeInfoTip> docNodes;
|
QList<CodeInfoTip> docNodes = parseDocument();
|
||||||
if (m_parseDocument) {
|
|
||||||
docNodes = parseDocument();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if trigger is empty, it's making editing
|
// if trigger is empty, it's making editing
|
||||||
if (trigger.isEmpty()) {
|
if (trigger.isEmpty()) {
|
||||||
|
@ -383,8 +413,7 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
|
||||||
|
|
||||||
// first preprocess the code
|
// first preprocess the code
|
||||||
AsPreprocesser prepc(engine);
|
AsPreprocesser prepc(engine);
|
||||||
// TODO: set include callback
|
prepc.setIncludeCallback(&AsCompletion::includeCallBack, this);
|
||||||
// prepc.setIncludeCallback();
|
|
||||||
|
|
||||||
auto r = prepc.loadSectionFromMemory(QStringLiteral("ASCOMPLETION"),
|
auto r = prepc.loadSectionFromMemory(QStringLiteral("ASCOMPLETION"),
|
||||||
code.toUtf8());
|
code.toUtf8());
|
||||||
|
@ -396,99 +425,109 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
|
||||||
QList<CodeInfoTip> ret;
|
QList<CodeInfoTip> ret;
|
||||||
|
|
||||||
for (auto &d : data) {
|
for (auto &d : data) {
|
||||||
QAsCodeParser parser(engine);
|
qsizetype offset = -1;
|
||||||
auto syms =
|
if (d.section == QStringLiteral("ASCOMPLETION")) {
|
||||||
parser.parseAndIntell(editor->textCursor().position(), d.script);
|
offset = editor->textCursor().position();
|
||||||
|
|
||||||
for (auto &sym : syms) {
|
|
||||||
CodeInfoTip tip;
|
|
||||||
tip.name = sym.name;
|
|
||||||
tip.nameSpace = QString::fromUtf8(sym.scope.join("::"));
|
|
||||||
|
|
||||||
switch (sym.symtype) {
|
|
||||||
case QAsCodeParser::SymbolType::Function:
|
|
||||||
case QAsCodeParser::SymbolType::FnDef:
|
|
||||||
tip.type = CodeInfoTip::Type::Function;
|
|
||||||
tip.addinfo.insert(CodeInfoTip::RetType,
|
|
||||||
QString::fromUtf8(sym.type));
|
|
||||||
tip.addinfo.insert(CodeInfoTip::Args,
|
|
||||||
QString::fromUtf8(sym.additonalInfo));
|
|
||||||
for (auto &var : sym.children) {
|
|
||||||
CodeInfoTip va;
|
|
||||||
va.dontAddGlobal = true;
|
|
||||||
va.name = var.name;
|
|
||||||
va.nameSpace = QString::fromUtf8(var.scope.join("::"));
|
|
||||||
va.addinfo.insert(CodeInfoTip::RetType, var.type);
|
|
||||||
va.type = CodeInfoTip::Type::Variable;
|
|
||||||
ret.append(va);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QAsCodeParser::SymbolType::Enum:
|
|
||||||
tip.type = CodeInfoTip::Type::Enum;
|
|
||||||
for (auto &e : sym.children) {
|
|
||||||
CodeInfoTip en;
|
|
||||||
en.dontAddGlobal = true;
|
|
||||||
en.name = e.name;
|
|
||||||
en.nameSpace = QString::fromUtf8(e.scope.join("::"));
|
|
||||||
en.type = CodeInfoTip::Type::Enumerater;
|
|
||||||
if (!e.additonalInfo.isEmpty()) {
|
|
||||||
en.addinfo.insert(CodeInfoTip::Comment,
|
|
||||||
en.name + QStringLiteral(" = ") +
|
|
||||||
e.additonalInfo);
|
|
||||||
}
|
|
||||||
ret.append(en);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QAsCodeParser::SymbolType::TypeDef:
|
|
||||||
tip.type = CodeInfoTip::Type::TypeDef;
|
|
||||||
break;
|
|
||||||
case QAsCodeParser::SymbolType::Variable:
|
|
||||||
tip.addinfo.insert(CodeInfoTip::RetType, sym.type);
|
|
||||||
tip.type = CodeInfoTip::Type::Variable;
|
|
||||||
break;
|
|
||||||
case QAsCodeParser::SymbolType::Class:
|
|
||||||
case QAsCodeParser::SymbolType::Interface:
|
|
||||||
for (auto &mem : sym.children) {
|
|
||||||
if (mem.vis != QAsCodeParser::Visiblity::Public) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
CodeInfoTip ctip;
|
|
||||||
ctip.name = mem.name;
|
|
||||||
ctip.nameSpace = QString::fromUtf8(mem.scope.join("::"));
|
|
||||||
if (mem.symtype == QAsCodeParser::SymbolType::Function) {
|
|
||||||
ctip.type = CodeInfoTip::Type::Function;
|
|
||||||
ctip.addinfo.insert(CodeInfoTip::RetType,
|
|
||||||
QString::fromUtf8(mem.type));
|
|
||||||
ctip.addinfo.insert(
|
|
||||||
CodeInfoTip::Args,
|
|
||||||
QString::fromUtf8(mem.additonalInfo));
|
|
||||||
for (auto &var : mem.children) {
|
|
||||||
CodeInfoTip va;
|
|
||||||
va.dontAddGlobal = true;
|
|
||||||
va.name = var.name;
|
|
||||||
va.nameSpace =
|
|
||||||
QString::fromUtf8(var.scope.join("::"));
|
|
||||||
va.addinfo.insert(CodeInfoTip::RetType, var.type);
|
|
||||||
va.type = CodeInfoTip::Type::Variable;
|
|
||||||
tip.children.append(va);
|
|
||||||
}
|
|
||||||
tip.children.append(ctip);
|
|
||||||
} else if (mem.symtype ==
|
|
||||||
QAsCodeParser::SymbolType::Variable) {
|
|
||||||
ctip.addinfo.insert(CodeInfoTip::RetType, mem.type);
|
|
||||||
ctip.type = CodeInfoTip::Type::Variable;
|
|
||||||
tip.children.append(ctip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tip.type = CodeInfoTip::Type::Class;
|
|
||||||
break;
|
|
||||||
case QAsCodeParser::SymbolType::Invalid:
|
|
||||||
case QAsCodeParser::SymbolType::Import:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.append(tip);
|
|
||||||
}
|
}
|
||||||
|
ret.append(parseScriptData(offset, d.script));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<CodeInfoTip> AsCompletion::parseScriptData(qsizetype offset,
|
||||||
|
const QByteArray &code) {
|
||||||
|
QList<CodeInfoTip> ret;
|
||||||
|
|
||||||
|
auto engine = ScriptMachine::instance().engine();
|
||||||
|
QAsCodeParser parser(engine);
|
||||||
|
auto syms = parser.parseAndIntell(offset, code);
|
||||||
|
|
||||||
|
for (auto &sym : syms) {
|
||||||
|
CodeInfoTip tip;
|
||||||
|
tip.name = sym.name;
|
||||||
|
tip.nameSpace = QString::fromUtf8(sym.scope.join("::"));
|
||||||
|
|
||||||
|
switch (sym.symtype) {
|
||||||
|
case QAsCodeParser::SymbolType::Function:
|
||||||
|
case QAsCodeParser::SymbolType::FnDef:
|
||||||
|
tip.type = CodeInfoTip::Type::Function;
|
||||||
|
tip.addinfo.insert(CodeInfoTip::RetType,
|
||||||
|
QString::fromUtf8(sym.type));
|
||||||
|
tip.addinfo.insert(CodeInfoTip::Args,
|
||||||
|
QString::fromUtf8(sym.additonalInfo));
|
||||||
|
for (auto &var : sym.children) {
|
||||||
|
CodeInfoTip va;
|
||||||
|
va.dontAddGlobal = true;
|
||||||
|
va.name = var.name;
|
||||||
|
va.nameSpace = QString::fromUtf8(var.scope.join("::"));
|
||||||
|
va.addinfo.insert(CodeInfoTip::RetType, var.type);
|
||||||
|
va.type = CodeInfoTip::Type::Variable;
|
||||||
|
ret.append(va);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QAsCodeParser::SymbolType::Enum:
|
||||||
|
tip.type = CodeInfoTip::Type::Enum;
|
||||||
|
for (auto &e : sym.children) {
|
||||||
|
CodeInfoTip en;
|
||||||
|
en.dontAddGlobal = true;
|
||||||
|
en.name = e.name;
|
||||||
|
en.nameSpace = QString::fromUtf8(e.scope.join("::"));
|
||||||
|
en.type = CodeInfoTip::Type::Enumerater;
|
||||||
|
if (!e.additonalInfo.isEmpty()) {
|
||||||
|
en.addinfo.insert(CodeInfoTip::Comment,
|
||||||
|
en.name + QStringLiteral(" = ") +
|
||||||
|
e.additonalInfo);
|
||||||
|
}
|
||||||
|
ret.append(en);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QAsCodeParser::SymbolType::TypeDef:
|
||||||
|
tip.type = CodeInfoTip::Type::TypeDef;
|
||||||
|
break;
|
||||||
|
case QAsCodeParser::SymbolType::Variable:
|
||||||
|
tip.addinfo.insert(CodeInfoTip::RetType, sym.type);
|
||||||
|
tip.type = CodeInfoTip::Type::Variable;
|
||||||
|
break;
|
||||||
|
case QAsCodeParser::SymbolType::Class:
|
||||||
|
case QAsCodeParser::SymbolType::Interface:
|
||||||
|
for (auto &mem : sym.children) {
|
||||||
|
if (mem.vis != QAsCodeParser::Visiblity::Public) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CodeInfoTip ctip;
|
||||||
|
ctip.name = mem.name;
|
||||||
|
ctip.nameSpace = QString::fromUtf8(mem.scope.join("::"));
|
||||||
|
if (mem.symtype == QAsCodeParser::SymbolType::Function) {
|
||||||
|
ctip.type = CodeInfoTip::Type::Function;
|
||||||
|
ctip.addinfo.insert(CodeInfoTip::RetType,
|
||||||
|
QString::fromUtf8(mem.type));
|
||||||
|
ctip.addinfo.insert(CodeInfoTip::Args,
|
||||||
|
QString::fromUtf8(mem.additonalInfo));
|
||||||
|
for (auto &var : mem.children) {
|
||||||
|
CodeInfoTip va;
|
||||||
|
va.dontAddGlobal = true;
|
||||||
|
va.name = var.name;
|
||||||
|
va.nameSpace = QString::fromUtf8(var.scope.join("::"));
|
||||||
|
va.addinfo.insert(CodeInfoTip::RetType, var.type);
|
||||||
|
va.type = CodeInfoTip::Type::Variable;
|
||||||
|
tip.children.append(va);
|
||||||
|
}
|
||||||
|
tip.children.append(ctip);
|
||||||
|
} else if (mem.symtype == QAsCodeParser::SymbolType::Variable) {
|
||||||
|
ctip.addinfo.insert(CodeInfoTip::RetType, mem.type);
|
||||||
|
ctip.type = CodeInfoTip::Type::Variable;
|
||||||
|
tip.children.append(ctip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tip.type = CodeInfoTip::Type::Class;
|
||||||
|
break;
|
||||||
|
case QAsCodeParser::SymbolType::Invalid:
|
||||||
|
case QAsCodeParser::SymbolType::Import:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.append(tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "WingCodeEdit/wingcompleter.h"
|
#include "WingCodeEdit/wingcompleter.h"
|
||||||
#include "class/asdatabase.h"
|
#include "class/asdatabase.h"
|
||||||
|
|
||||||
|
class AsPreprocesser;
|
||||||
|
|
||||||
class AsCompletion : public WingCompleter {
|
class AsCompletion : public WingCompleter {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -32,9 +34,6 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual QString wordSeperators() const override;
|
virtual QString wordSeperators() const override;
|
||||||
|
|
||||||
bool parseDocument() const;
|
|
||||||
void setParseDocument(bool newParseDocument);
|
|
||||||
|
|
||||||
void clearFunctionTip();
|
void clearFunctionTip();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -43,6 +42,9 @@ protected:
|
||||||
|
|
||||||
virtual QList<CodeInfoTip> parseDocument();
|
virtual QList<CodeInfoTip> parseDocument();
|
||||||
|
|
||||||
|
QList<CodeInfoTip> parseScriptData(qsizetype offset,
|
||||||
|
const QByteArray &code);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onFunctionTip(const QString &content);
|
void onFunctionTip(const QString &content);
|
||||||
|
|
||||||
|
@ -55,9 +57,13 @@ private:
|
||||||
const QList<CodeInfoTip> &docNodes);
|
const QList<CodeInfoTip> &docNodes);
|
||||||
void applyClassNodes(QList<CodeInfoTip> &nodes);
|
void applyClassNodes(QList<CodeInfoTip> &nodes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int includeCallBack(const QString &include, bool quotedInclude,
|
||||||
|
const QString &from, AsPreprocesser *builder,
|
||||||
|
void *userParam);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASDataBase parser;
|
ASDataBase parser;
|
||||||
bool m_parseDocument;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _CPP_COMPLETION_H_
|
#endif // _CPP_COMPLETION_H_
|
||||||
|
|
|
@ -17,9 +17,46 @@
|
||||||
|
|
||||||
#include "asconsolecompletion.h"
|
#include "asconsolecompletion.h"
|
||||||
|
|
||||||
|
#include "class/qascodeparser.h"
|
||||||
#include "control/scriptingconsole.h"
|
#include "control/scriptingconsole.h"
|
||||||
|
|
||||||
AsConsoleCompletion::AsConsoleCompletion(ScriptingConsole *p)
|
AsConsoleCompletion::AsConsoleCompletion(ScriptingConsole *p)
|
||||||
: AsCompletion(p), _console(p) {
|
: AsCompletion(p), _console(p) {}
|
||||||
setParseDocument(false);
|
|
||||||
|
QList<CodeInfoTip> AsConsoleCompletion::parseDocument() {
|
||||||
|
auto editor = _console;
|
||||||
|
if (editor == nullptr) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto code = editor->currentCodes();
|
||||||
|
auto engine = ScriptMachine::instance().engine();
|
||||||
|
|
||||||
|
QAsCodeParser parser(engine);
|
||||||
|
auto seg = parser.parse(code.toUtf8());
|
||||||
|
if (std::find_if(seg.begin(), seg.end(),
|
||||||
|
[](const QAsCodeParser::CodeSegment &seg) {
|
||||||
|
return seg.isValid();
|
||||||
|
}) == seg.end()) {
|
||||||
|
// wrap it to let code-completion work
|
||||||
|
code.prepend("void main(){").append('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
// first preprocess the code
|
||||||
|
AsPreprocesser prepc(engine);
|
||||||
|
|
||||||
|
// including is not supported in console
|
||||||
|
auto r = prepc.loadSectionFromMemory(QStringLiteral("ASConCOMPLETION"),
|
||||||
|
code.toUtf8());
|
||||||
|
if (r <= 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = prepc.scriptData();
|
||||||
|
if (data.size() == 1) {
|
||||||
|
auto d = data[0];
|
||||||
|
return parseScriptData(d.script.length() - 1, d.script);
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@ public:
|
||||||
explicit AsConsoleCompletion(ScriptingConsole *p);
|
explicit AsConsoleCompletion(ScriptingConsole *p);
|
||||||
virtual ~AsConsoleCompletion() = default;
|
virtual ~AsConsoleCompletion() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual QList<CodeInfoTip> parseDocument();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScriptingConsole *_console;
|
ScriptingConsole *_console;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,41 +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 "ascontextmgr.h"
|
|
||||||
|
|
||||||
// copy from base class
|
|
||||||
struct SContextInfo {
|
|
||||||
asUINT sleepUntil;
|
|
||||||
std::vector<asIScriptContext *> coRoutines;
|
|
||||||
asUINT currentCoRoutine;
|
|
||||||
asIScriptContext *keepCtxAfterExecution;
|
|
||||||
};
|
|
||||||
|
|
||||||
asContextMgr::asContextMgr() : CContextMgr() {}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,30 +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 ASCONTEXTMGR_H
|
|
||||||
#define ASCONTEXTMGR_H
|
|
||||||
|
|
||||||
#include "AngelScript/sdk/add_on/contextmgr/contextmgr.h"
|
|
||||||
|
|
||||||
class asContextMgr : public CContextMgr {
|
|
||||||
public:
|
|
||||||
asContextMgr();
|
|
||||||
|
|
||||||
bool findThreadWithUserData(asPWORD index, void *data) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ASCONTEXTMGR_H
|
|
|
@ -71,6 +71,9 @@ void asDebugger::takeCommands(asIScriptContext *ctx) {
|
||||||
void asDebugger::lineCallback(asIScriptContext *ctx) {
|
void asDebugger::lineCallback(asIScriptContext *ctx) {
|
||||||
Q_ASSERT(ctx);
|
Q_ASSERT(ctx);
|
||||||
|
|
||||||
|
// prevent UI freezing
|
||||||
|
qApp->processEvents();
|
||||||
|
|
||||||
// This should never happen, but it doesn't hurt to validate it
|
// This should never happen, but it doesn't hurt to validate it
|
||||||
if (ctx == nullptr)
|
if (ctx == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -456,7 +456,7 @@ void CTypeParser::stripComments(QStringList &lines) const {
|
||||||
QStringLiteral("]");
|
QStringLiteral("]");
|
||||||
|
|
||||||
// search comment start
|
// search comment start
|
||||||
while ((pos = line.indexOf(kSlash, pos)) != -1) {
|
while ((pos = line.indexOf(char(kSlash), pos)) != -1) {
|
||||||
if (line.length() <= pos + 1)
|
if (line.length() <= pos + 1)
|
||||||
break; // the 1st '/' is at the end of line, so not a comment
|
break; // the 1st '/' is at the end of line, so not a comment
|
||||||
|
|
||||||
|
@ -1070,7 +1070,7 @@ bool CTypeParser::parseDeclaration(const QString &line,
|
||||||
if (line.isEmpty()) {
|
if (line.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (line[line.length() - 1] != kSemicolon)
|
if (line[line.length() - 1] != char(kSemicolon))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QStringList tokens;
|
QStringList tokens;
|
||||||
|
@ -1090,7 +1090,7 @@ bool CTypeParser::parseDeclaration(const QString &line,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokens[++index].at(0) == kAsterisk) {
|
if (tokens[++index].at(0) == char(kAsterisk)) {
|
||||||
decl.is_pointer = true;
|
decl.is_pointer = true;
|
||||||
// size of a pointer is 4 types on a 32-bit system
|
// size of a pointer is 4 types on a 32-bit system
|
||||||
length =
|
length =
|
||||||
|
@ -1148,14 +1148,14 @@ bool CTypeParser::parseEnumDeclaration(const QString &line, int &last_value,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
if (kComma != tokens[1].at(0)) {
|
if (char(kComma) != tokens[1].at(0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
decl.second = ++last_value;
|
decl.second = ++last_value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
if (kEqual != tokens[1].at(0)) {
|
if (char(kEqual) != tokens[1].at(0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,7 +1171,8 @@ bool CTypeParser::parseEnumDeclaration(const QString &line, int &last_value,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
if (!(kEqual == tokens[1].at(0) && kComma == tokens[3].at(0))) {
|
if (!(char(kEqual) == tokens[1].at(0) &&
|
||||||
|
char(kComma) == tokens[3].at(0))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1208,8 +1209,8 @@ bool CTypeParser::parseAssignExpression(const QString &line) {
|
||||||
|
|
||||||
// only 4 tokens for an assignment expression: var = number;
|
// only 4 tokens for an assignment expression: var = number;
|
||||||
if (4 == splitLineIntoTokens(line, tokens) &&
|
if (4 == splitLineIntoTokens(line, tokens) &&
|
||||||
kEqual == tokens[1].at(tokens[1].length() - 1) &&
|
char(kEqual) == tokens[1].at(tokens[1].length() - 1) &&
|
||||||
kSemicolon == tokens[3].at(tokens[3].length() - 1) &&
|
char(kSemicolon) == tokens[3].at(tokens[3].length() - 1) &&
|
||||||
isNumericToken(tokens[2], number)) {
|
isNumericToken(tokens[2], number)) {
|
||||||
const_defs_.insert(tokens[0], number);
|
const_defs_.insert(tokens[0], number);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1244,7 +1245,7 @@ bool CTypeParser::parsePreProcDirective(const QString &src, qsizetype &pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// only handle header file included with ""
|
// only handle header file included with ""
|
||||||
if (kQuotation == token[token.length() - 1]) {
|
if (char(kQuotation) == token[token.length() - 1]) {
|
||||||
// get included header file name
|
// get included header file name
|
||||||
if (!getNextToken(src, pos, token, false)) {
|
if (!getNextToken(src, pos, token, false)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1371,7 +1372,7 @@ bool CTypeParser::parseStructUnion(const bool is_struct, const bool is_typedef,
|
||||||
if (is_typedef) {
|
if (is_typedef) {
|
||||||
// format 1
|
// format 1
|
||||||
if (!(getNextToken(src, pos, next_token) &&
|
if (!(getNextToken(src, pos, next_token) &&
|
||||||
kSemicolon == next_token.at(0))) {
|
char(kSemicolon) == next_token.at(0))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1392,7 +1393,7 @@ bool CTypeParser::parseStructUnion(const bool is_struct, const bool is_typedef,
|
||||||
type_maps_[type_name] = type_maps_[type_alias];
|
type_maps_[type_name] = type_maps_[type_alias];
|
||||||
}
|
}
|
||||||
} else { // non-typedef
|
} else { // non-typedef
|
||||||
if (kSemicolon == token.at(0)) {
|
if (char(kSemicolon) == token.at(0)) {
|
||||||
// format 2
|
// format 2
|
||||||
is_decl = false;
|
is_decl = false;
|
||||||
if (type_name.isEmpty()) {
|
if (type_name.isEmpty()) {
|
||||||
|
@ -1547,7 +1548,7 @@ bool CTypeParser::parseEnum(const bool is_typedef, const QString &src,
|
||||||
if (is_typedef) {
|
if (is_typedef) {
|
||||||
// format 1
|
// format 1
|
||||||
if (!(getNextToken(src, pos, next_token) &&
|
if (!(getNextToken(src, pos, next_token) &&
|
||||||
kSemicolon == next_token.at(0))) {
|
char(kSemicolon) == next_token.at(0))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1564,7 +1565,7 @@ bool CTypeParser::parseEnum(const bool is_typedef, const QString &src,
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
} else { // non-typedef
|
} else { // non-typedef
|
||||||
if (kSemicolon == token.at(0)) {
|
if (char(kSemicolon) == token.at(0)) {
|
||||||
// format 2
|
// format 2
|
||||||
is_decl = false;
|
is_decl = false;
|
||||||
if (type_name.isEmpty()) {
|
if (type_name.isEmpty()) {
|
||||||
|
|
|
@ -1194,7 +1194,7 @@ QList<QAsCodeParser::CodeSegment> QAsCodeParser::parseScript(bool inBlock) {
|
||||||
seg.offset = begin;
|
seg.offset = begin;
|
||||||
seg.scope = currentNs;
|
seg.scope = currentNs;
|
||||||
seg.type = SymbolType::Variable;
|
seg.type = SymbolType::Variable;
|
||||||
seg.codes = _code.sliced(begin, end - begin + 1);
|
seg.codes = _code.sliced(begin, end - begin);
|
||||||
rewindTo(&t1);
|
rewindTo(&t1);
|
||||||
|
|
||||||
segs.append(seg);
|
segs.append(seg);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "AngelScript/sdk/add_on/weakref/weakref.h"
|
#include "AngelScript/sdk/add_on/weakref/weakref.h"
|
||||||
|
|
||||||
#include "angelobjstring.h"
|
#include "angelobjstring.h"
|
||||||
|
#include "class/appmanager.h"
|
||||||
#include "class/asbuilder.h"
|
#include "class/asbuilder.h"
|
||||||
#include "class/pluginsystem.h"
|
#include "class/pluginsystem.h"
|
||||||
#include "class/qascodeparser.h"
|
#include "class/qascodeparser.h"
|
||||||
|
@ -42,13 +43,7 @@
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QScopeGuard>
|
#include <QScopeGuard>
|
||||||
|
|
||||||
ScriptMachine::~ScriptMachine() {
|
ScriptMachine::~ScriptMachine() { destoryMachine(); }
|
||||||
if (_ctxMgr) {
|
|
||||||
delete _ctxMgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
destoryMachine();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScriptMachine::init() {
|
bool ScriptMachine::init() {
|
||||||
if (isInited()) {
|
if (isInited()) {
|
||||||
|
@ -74,9 +69,7 @@ bool ScriptMachine::init() {
|
||||||
bool ScriptMachine::isInited() const { return _engine != nullptr; }
|
bool ScriptMachine::isInited() const { return _engine != nullptr; }
|
||||||
|
|
||||||
bool ScriptMachine::isRunning(ConsoleMode mode) const {
|
bool ScriptMachine::isRunning(ConsoleMode mode) const {
|
||||||
return _ctxMgr->findThreadWithUserData(
|
return _ctx.value(mode) != nullptr;
|
||||||
AsUserDataType::UserData_ContextMode,
|
|
||||||
reinterpret_cast<void *>(asPWORD(mode)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMachine::configureEngine() {
|
bool ScriptMachine::configureEngine() {
|
||||||
|
@ -171,9 +164,12 @@ bool ScriptMachine::configureEngine() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the context manager and register the support for co-routines
|
_ctxMgr = new CContextMgr;
|
||||||
_ctxMgr = new asContextMgr();
|
|
||||||
_ctxMgr->RegisterCoRoutineSupport(_engine);
|
_ctxMgr->RegisterCoRoutineSupport(_engine);
|
||||||
|
_ctxMgr->SetGetTimeCallback([]() -> asUINT {
|
||||||
|
return AppManager::instance()->currentMSecsSinceEpoch();
|
||||||
|
});
|
||||||
|
_ctxMgr->RegisterThreadSupport(_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
|
||||||
|
@ -227,6 +223,9 @@ QString ScriptMachine::getCallStack(asIScriptContext *context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::destoryMachine() {
|
void ScriptMachine::destoryMachine() {
|
||||||
|
_ctxMgr->AbortAll();
|
||||||
|
delete _ctxMgr;
|
||||||
|
|
||||||
_debugger->setEngine(nullptr);
|
_debugger->setEngine(nullptr);
|
||||||
_engine->ShutDownAndRelease();
|
_engine->ShutDownAndRelease();
|
||||||
_engine = nullptr;
|
_engine = nullptr;
|
||||||
|
@ -389,9 +388,10 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
outputMessage(mode, 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
|
||||||
// variables Since we've set up the request context callback we will be able
|
// global variables Since we've set up the request context callback we
|
||||||
// to debug the initialization without passing in a pre-created context
|
// will be able to debug the initialization without passing in a
|
||||||
|
// pre-created context
|
||||||
r = mod->ResetGlobalVars(0);
|
r = mod->ResetGlobalVars(0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
|
@ -405,9 +405,11 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &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);
|
||||||
|
_ctx[mode] = ctx;
|
||||||
|
|
||||||
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
AsUserDataType::UserData_isDbg);
|
AsUserDataType::UserData_isDbg);
|
||||||
|
|
||||||
mod->SetUserData(reinterpret_cast<void *>(isDbg),
|
mod->SetUserData(reinterpret_cast<void *>(isDbg),
|
||||||
AsUserDataType::UserData_isDbg);
|
AsUserDataType::UserData_isDbg);
|
||||||
|
|
||||||
|
@ -421,8 +423,11 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
// Execute the script until completion
|
// Execute the script until completion
|
||||||
// The script may create co-routines. These will automatically
|
// The script may create co-routines. These will automatically
|
||||||
// be managed by the context manager
|
// be managed by the context manager
|
||||||
while (_ctxMgr->ExecuteScripts())
|
while (_ctxMgr->ExecuteScripts()) {
|
||||||
;
|
qApp->processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ctx[mode] = nullptr;
|
||||||
|
|
||||||
// Check if the main script finished normally
|
// Check if the main script finished normally
|
||||||
r = ctx->GetState();
|
r = ctx->GetState();
|
||||||
|
@ -479,13 +484,24 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
|
||||||
return r >= 0;
|
return r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::abortDbgScript(ConsoleMode mode) {
|
void ScriptMachine::abortDbgScript() {
|
||||||
if (_debugger->getEngine()) {
|
if (_debugger->getEngine()) {
|
||||||
_debugger->runDebugAction(asDebugger::ABORT);
|
_debugger->runDebugAction(asDebugger::ABORT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::abortScript() { _ctxMgr->AbortAll(); }
|
void ScriptMachine::abortScript(ConsoleMode mode) {
|
||||||
|
auto ctx = _ctx.value(mode, nullptr);
|
||||||
|
if (ctx) {
|
||||||
|
ctx->Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMachine::abortScript() {
|
||||||
|
abortScript(ConsoleMode::Interactive);
|
||||||
|
abortScript(ConsoleMode::Scripting);
|
||||||
|
abortScript(ConsoleMode::Background);
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptMachine::messageCallback(const asSMessageInfo *msg, void *param) {
|
void ScriptMachine::messageCallback(const asSMessageInfo *msg, void *param) {
|
||||||
MessageType t = MessageType::Print;
|
MessageType t = MessageType::Print;
|
||||||
|
@ -1805,16 +1821,6 @@ asDebugger *ScriptMachine::debugger() const { return _debugger; }
|
||||||
|
|
||||||
bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
||||||
asIScriptModule *mod = createModuleIfNotExist(mode);
|
asIScriptModule *mod = createModuleIfNotExist(mode);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, false);
|
_engine->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, false);
|
||||||
|
|
||||||
// first, preparse the code
|
// first, preparse the code
|
||||||
|
@ -1824,28 +1830,30 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
||||||
asIScriptFunction *func = nullptr;
|
asIScriptFunction *func = nullptr;
|
||||||
|
|
||||||
auto ret = parser.parse(ccode);
|
auto ret = parser.parse(ccode);
|
||||||
|
|
||||||
// check whether there is any enum/class
|
// check whether there is any enum/class
|
||||||
if (std::find_if(ret.begin(), ret.end(),
|
if (std::find_if(ret.begin(), ret.end(),
|
||||||
[](const QAsCodeParser::CodeSegment &seg) {
|
[](const QAsCodeParser::CodeSegment &seg) {
|
||||||
return seg.isValid();
|
switch (seg.type) {
|
||||||
}) == ret.end()) {
|
case QAsCodeParser::SymbolType::Enum:
|
||||||
|
case QAsCodeParser::SymbolType::Class:
|
||||||
|
case QAsCodeParser::SymbolType::Function:
|
||||||
|
case QAsCodeParser::SymbolType::Interface:
|
||||||
|
case QAsCodeParser::SymbolType::Import:
|
||||||
|
case QAsCodeParser::SymbolType::Variable:
|
||||||
|
return false;
|
||||||
|
case QAsCodeParser::SymbolType::Invalid:
|
||||||
|
case QAsCodeParser::SymbolType::TypeDef:
|
||||||
|
case QAsCodeParser::SymbolType::FnDef:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}) != ret.end()) {
|
||||||
// ok, wrap the codes
|
// ok, wrap the codes
|
||||||
ccode.prepend("void main(){").append("}");
|
ccode.prepend("void f(){").append("}");
|
||||||
// start to compile
|
// start to compile
|
||||||
auto r = mod->CompileFunction(nullptr, ccode, -1, 0, &func);
|
auto cr = mod->CompileFunction(nullptr, ccode, 0, 0, &func);
|
||||||
if (r < 0) {
|
if (cr < 0) {
|
||||||
MessageInfo info;
|
|
||||||
info.mode = mode;
|
|
||||||
info.message = tr("Script failed to build");
|
|
||||||
info.type = MessageType::Error;
|
|
||||||
outputMessage(mode, info);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mod->AddScriptSection("Runner", ccode, ccode.size(), 0);
|
|
||||||
|
|
||||||
auto r = mod->Build();
|
|
||||||
if (r < 0) {
|
|
||||||
MessageInfo info;
|
MessageInfo info;
|
||||||
info.mode = mode;
|
info.mode = mode;
|
||||||
info.message = tr("Script failed to build");
|
info.message = tr("Script failed to build");
|
||||||
|
@ -1854,85 +1862,98 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the main function
|
// Set up a context to execute the script
|
||||||
func = mod->GetFunctionByDecl("void main()");
|
// The context manager will request the context from the
|
||||||
if (func == nullptr) {
|
// pool, which will automatically attach the debugger
|
||||||
// Try again with "int main()"
|
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
||||||
func = mod->GetFunctionByDecl("int main()");
|
_ctx[mode] = ctx;
|
||||||
|
|
||||||
|
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, 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()) {
|
||||||
|
qApp->processEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func == nullptr) {
|
_ctx[mode] = nullptr;
|
||||||
MessageInfo info;
|
|
||||||
info.mode = mode;
|
|
||||||
info.message = tr("Cannot find 'int main()' or 'void main()'");
|
|
||||||
info.type = MessageType::Error;
|
|
||||||
outputMessage(mode, info);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up a context to execute the script
|
// Check if the main script finished normally
|
||||||
// The context manager will request the context from the
|
int r = ctx->GetState();
|
||||||
// pool, which will automatically attach the debugger
|
if (r != asEXECUTION_FINISHED) {
|
||||||
asIScriptContext *ctx = _ctxMgr->AddContext(_engine, func, true);
|
if (r == asEXECUTION_EXCEPTION) {
|
||||||
|
MessageInfo info;
|
||||||
asPWORD isDbg = 0;
|
info.mode = mode;
|
||||||
ctx->SetUserData(reinterpret_cast<void *>(isDbg),
|
info.message =
|
||||||
AsUserDataType::UserData_isDbg);
|
tr("The script failed with an exception") +
|
||||||
mod->SetUserData(reinterpret_cast<void *>(isDbg),
|
QStringLiteral("\n") +
|
||||||
AsUserDataType::UserData_isDbg);
|
QString::fromStdString(GetExceptionInfo(ctx, true));
|
||||||
|
info.type = MessageType::Error;
|
||||||
asPWORD umode = asPWORD(mode);
|
outputMessage(mode, info);
|
||||||
ctx->SetUserData(reinterpret_cast<void *>(umode),
|
r = -1;
|
||||||
AsUserDataType::UserData_ContextMode);
|
} else if (r == asEXECUTION_ABORTED) {
|
||||||
|
MessageInfo info;
|
||||||
ctx->SetExceptionCallback(asMETHOD(ScriptMachine, exceptionCallback), this,
|
info.mode = mode;
|
||||||
asCALL_THISCALL);
|
info.message = tr("The script was aborted");
|
||||||
|
info.type = MessageType::Error;
|
||||||
// Execute the script until completion
|
outputMessage(mode, info);
|
||||||
// The script may create co-routines. These will automatically
|
r = -1;
|
||||||
// be managed by the context manager
|
} else {
|
||||||
while (_ctxMgr->ExecuteScripts())
|
auto e = QMetaEnum::fromType<asEContextState>();
|
||||||
;
|
MessageInfo info;
|
||||||
|
info.message = tr("The script terminated unexpectedly") +
|
||||||
// Check if the main script finished normally
|
QStringLiteral(" (") + e.valueToKey(r) +
|
||||||
int r = ctx->GetState();
|
QStringLiteral(")");
|
||||||
if (r != asEXECUTION_FINISHED) {
|
info.type = MessageType::Error;
|
||||||
if (r == asEXECUTION_EXCEPTION) {
|
outputMessage(mode, info);
|
||||||
MessageInfo info;
|
r = -1;
|
||||||
info.mode = mode;
|
}
|
||||||
info.message = tr("The script failed with an exception") +
|
|
||||||
QStringLiteral("\n") +
|
|
||||||
QString::fromStdString(GetExceptionInfo(ctx, true));
|
|
||||||
info.type = MessageType::Error;
|
|
||||||
outputMessage(mode, info);
|
|
||||||
r = -1;
|
|
||||||
} else if (r == asEXECUTION_ABORTED) {
|
|
||||||
MessageInfo info;
|
|
||||||
info.mode = mode;
|
|
||||||
info.message = tr("The script was aborted");
|
|
||||||
info.type = MessageType::Error;
|
|
||||||
outputMessage(mode, info);
|
|
||||||
r = -1;
|
|
||||||
} else {
|
} else {
|
||||||
auto e = QMetaEnum::fromType<asEContextState>();
|
r = 0;
|
||||||
MessageInfo info;
|
|
||||||
info.message = tr("The script terminated unexpectedly") +
|
|
||||||
QStringLiteral(" (") + e.valueToKey(r) +
|
|
||||||
QStringLiteral(")");
|
|
||||||
info.type = MessageType::Error;
|
|
||||||
outputMessage(mode, info);
|
|
||||||
r = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func->Release();
|
||||||
|
|
||||||
|
// Return the context after retrieving the return value
|
||||||
|
_ctxMgr->DoneWithContext(ctx);
|
||||||
|
_engine->GarbageCollect();
|
||||||
|
|
||||||
|
return r >= 0;
|
||||||
} else {
|
} else {
|
||||||
r = 0;
|
if (ret.length() == 1) {
|
||||||
|
auto s = ret.first();
|
||||||
|
if (s.type == QAsCodeParser::SymbolType::Variable) {
|
||||||
|
auto r = mod->CompileGlobalVar(nullptr, ccode, 0);
|
||||||
|
if (r < 0 || mod->ResetGlobalVars() < 0) {
|
||||||
|
MessageInfo info;
|
||||||
|
info.mode = mode;
|
||||||
|
info.message = tr("GlobalBadDecl");
|
||||||
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MessageInfo info;
|
||||||
|
info.mode = mode;
|
||||||
|
info.message = tr("ScriptRunUnsupported");
|
||||||
|
info.type = MessageType::Error;
|
||||||
|
outputMessage(mode, info);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
// Return the context after retrieving the return value
|
|
||||||
_ctxMgr->DoneWithContext(ctx);
|
|
||||||
_engine->GarbageCollect();
|
|
||||||
|
|
||||||
return r >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScriptMachine::scriptGetExceptionInfo() {
|
QString ScriptMachine::scriptGetExceptionInfo() {
|
||||||
|
|
|
@ -18,13 +18,15 @@
|
||||||
#ifndef SCRIPTMACHINE_H
|
#ifndef SCRIPTMACHINE_H
|
||||||
#define SCRIPTMACHINE_H
|
#define SCRIPTMACHINE_H
|
||||||
|
|
||||||
|
#include "AngelScript/sdk/add_on/contextmgr/contextmgr.h"
|
||||||
#include "AngelScript/sdk/angelscript/include/angelscript.h"
|
#include "AngelScript/sdk/angelscript/include/angelscript.h"
|
||||||
|
|
||||||
#include "class/aspreprocesser.h"
|
#include "class/aspreprocesser.h"
|
||||||
|
|
||||||
#include "asdebugger.h"
|
#include "asdebugger.h"
|
||||||
#include "class/ascontextmgr.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QQueue>
|
||||||
|
|
||||||
class ScriptMachine : public QObject {
|
class ScriptMachine : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -97,7 +99,7 @@ private:
|
||||||
explicit ScriptMachine();
|
explicit ScriptMachine();
|
||||||
Q_DISABLE_COPY_MOVE(ScriptMachine)
|
Q_DISABLE_COPY_MOVE(ScriptMachine)
|
||||||
|
|
||||||
public:
|
private:
|
||||||
asIScriptModule *createModule(ConsoleMode mode);
|
asIScriptModule *createModule(ConsoleMode mode);
|
||||||
asIScriptModule *createModuleIfNotExist(ConsoleMode mode);
|
asIScriptModule *createModuleIfNotExist(ConsoleMode mode);
|
||||||
asIScriptModule *module(ConsoleMode mode);
|
asIScriptModule *module(ConsoleMode mode);
|
||||||
|
@ -143,7 +145,8 @@ public slots:
|
||||||
bool executeScript(ConsoleMode mode, const QString &script,
|
bool executeScript(ConsoleMode mode, const QString &script,
|
||||||
bool isInDebug = false);
|
bool isInDebug = false);
|
||||||
|
|
||||||
void abortDbgScript(ConsoleMode mode);
|
void abortDbgScript();
|
||||||
|
void abortScript(ConsoleMode mode);
|
||||||
void abortScript();
|
void abortScript();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -196,11 +199,13 @@ signals:
|
||||||
private:
|
private:
|
||||||
asIScriptEngine *_engine = nullptr;
|
asIScriptEngine *_engine = nullptr;
|
||||||
asDebugger *_debugger = nullptr;
|
asDebugger *_debugger = nullptr;
|
||||||
asContextMgr *_ctxMgr = nullptr;
|
CContextMgr *_ctxMgr = nullptr;
|
||||||
QVector<asIScriptContext *> _ctxPool;
|
|
||||||
|
QQueue<asIScriptContext *> _ctxPool;
|
||||||
|
|
||||||
QVector<asITypeInfo *> _rtypes;
|
QVector<asITypeInfo *> _rtypes;
|
||||||
QMap<ConsoleMode, RegCallBacks> _regcalls;
|
QMap<ConsoleMode, RegCallBacks> _regcalls;
|
||||||
|
QMap<ConsoleMode, asIScriptContext *> _ctx;
|
||||||
ConsoleMode _curMode = ConsoleMode::Background;
|
ConsoleMode _curMode = ConsoleMode::Background;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -250,16 +250,18 @@ ScriptManager::buildUpRibbonScriptRunner(RibbonButtonGroup *group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptManager::runScript(const QString &filename) {
|
void ScriptManager::runScript(const QString &filename) {
|
||||||
// ScriptMachine::instance().executeScript(filename);
|
auto &ins = ScriptMachine::instance();
|
||||||
|
if (ins.isRunning(ScriptMachine::Background)) {
|
||||||
|
auto ret = QMessageBox::question(nullptr, tr("ScriptRunning"),
|
||||||
|
tr("ScriptRunningRequestLastStop?"));
|
||||||
|
if (ret == QMessageBox::Yes) {
|
||||||
|
ins.abortScript(ScriptMachine::Background);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Q_ASSERT(_console);
|
ins.executeScript(ScriptMachine::Background, filename);
|
||||||
// _console->setMode(ScriptingConsole::Output);
|
|
||||||
// _console->stdWarn(tr("Excuting:") + filename);
|
|
||||||
// _console->newLine();
|
|
||||||
// // TODO
|
|
||||||
// // _console->machine()->executeScript(filename);
|
|
||||||
// _console->appendCommandPrompt();
|
|
||||||
// _console->setMode(ScriptingConsole::Input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ScriptManager::usrScriptsDbCats() const {
|
QStringList ScriptManager::usrScriptsDbCats() const {
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr qsizetype FILE_MAX_BUFFER = 0x6400000; // 100MB
|
constexpr qsizetype FILE_MAX_BUFFER = 0x32000000; // 800MB
|
||||||
constexpr auto CLONE_LIMIT = 3;
|
constexpr auto CLONE_LIMIT = 3;
|
||||||
|
|
||||||
constexpr auto VIEW_PROPERTY = "__VIEW__";
|
constexpr auto VIEW_PROPERTY = "__VIEW__";
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "scriptingconsole.h"
|
#include "scriptingconsole.h"
|
||||||
#include "QConsoleWidget/QConsoleIODevice.h"
|
#include "QConsoleWidget/QConsoleIODevice.h"
|
||||||
#include "class/logger.h"
|
|
||||||
#include "class/scriptmachine.h"
|
#include "class/scriptmachine.h"
|
||||||
#include "class/scriptsettings.h"
|
#include "class/scriptsettings.h"
|
||||||
#include "class/skinmanager.h"
|
#include "class/skinmanager.h"
|
||||||
|
@ -84,19 +83,15 @@ void ScriptingConsole::handleReturnKey() {
|
||||||
if (iodevice_->isOpen())
|
if (iodevice_->isOpen())
|
||||||
iodevice_->consoleWidgetInput(code);
|
iodevice_->consoleWidgetInput(code);
|
||||||
|
|
||||||
emit consoleCommand(code);
|
if (!_isWaitingRead) {
|
||||||
|
emit consoleCommand(code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingConsole::init() {
|
void ScriptingConsole::init() {
|
||||||
_getInputFn = std::bind(&ScriptingConsole::getInput, this);
|
_getInputFn = std::bind(&ScriptingConsole::getInput, this);
|
||||||
|
|
||||||
// _sp = new ScriptConsoleMachine(_getInputFn, this);
|
|
||||||
// connect(_sp, &ScriptConsoleMachine::onClearConsole, this,
|
|
||||||
// &ScriptingConsole::clear);
|
|
||||||
// connect(this, &ScriptingConsole::abortEvaluation, _sp,
|
|
||||||
// &ScriptConsoleMachine::abortScript);
|
|
||||||
|
|
||||||
connect(this, &QConsoleWidget::consoleCommand, this,
|
connect(this, &QConsoleWidget::consoleCommand, this,
|
||||||
&ScriptingConsole::runConsoleCommand);
|
&ScriptingConsole::runConsoleCommand);
|
||||||
|
|
||||||
|
@ -177,7 +172,7 @@ void ScriptingConsole::onOutput(const ScriptMachine::MessageInfo &message) {
|
||||||
flush();
|
flush();
|
||||||
break;
|
break;
|
||||||
case ScriptMachine::MessageType::Print:
|
case ScriptMachine::MessageType::Print:
|
||||||
if (lastInfo.first != message.type) {
|
if (lastInfo.first != message.type && isNotBlockStart) {
|
||||||
newLine();
|
newLine();
|
||||||
}
|
}
|
||||||
stdOut(message.message);
|
stdOut(message.message);
|
||||||
|
@ -219,7 +214,13 @@ void ScriptingConsole::applyScriptSettings() {
|
||||||
|
|
||||||
void ScriptingConsole::runConsoleCommand(const QString &code) {
|
void ScriptingConsole::runConsoleCommand(const QString &code) {
|
||||||
auto exec = code.trimmed();
|
auto exec = code.trimmed();
|
||||||
if (exec.endsWith('\\')) {
|
if (exec == QStringLiteral("#ls")) {
|
||||||
|
|
||||||
|
} else if (exec == QStringLiteral("#del")) {
|
||||||
|
|
||||||
|
} else if (exec == QStringLiteral("#cls")) {
|
||||||
|
|
||||||
|
} else if (exec.endsWith('\\')) {
|
||||||
static QRegularExpression ex(QStringLiteral("[\\\\\\s]+$"));
|
static QRegularExpression ex(QStringLiteral("[\\\\\\s]+$"));
|
||||||
_codes += exec.remove(ex);
|
_codes += exec.remove(ex);
|
||||||
setMode(Output);
|
setMode(Output);
|
||||||
|
@ -228,10 +229,8 @@ void ScriptingConsole::runConsoleCommand(const QString &code) {
|
||||||
} else {
|
} else {
|
||||||
setMode(Output);
|
setMode(Output);
|
||||||
_codes += exec;
|
_codes += exec;
|
||||||
if (!ScriptMachine::instance().executeCode(ScriptMachine::Interactive,
|
ScriptMachine::instance().executeCode(ScriptMachine::Interactive,
|
||||||
_codes)) {
|
_codes);
|
||||||
// WingMessageBox::
|
|
||||||
}
|
|
||||||
_codes.clear();
|
_codes.clear();
|
||||||
appendCommandPrompt();
|
appendCommandPrompt();
|
||||||
setMode(Input);
|
setMode(Input);
|
||||||
|
@ -239,11 +238,18 @@ void ScriptingConsole::runConsoleCommand(const QString &code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScriptingConsole::getInput() {
|
QString ScriptingConsole::getInput() {
|
||||||
|
auto &s = consoleStream();
|
||||||
appendCommandPrompt(true);
|
appendCommandPrompt(true);
|
||||||
setMode(Input);
|
setMode(Input);
|
||||||
consoleStream().device()->waitForReadyRead(-1);
|
s.status();
|
||||||
|
auto d = s.device();
|
||||||
|
auto ba = d->bytesAvailable();
|
||||||
|
d->skip(ba);
|
||||||
|
_isWaitingRead = true;
|
||||||
|
d->waitForReadyRead(-1);
|
||||||
QString instr;
|
QString instr;
|
||||||
consoleStream() >> instr;
|
s >> instr;
|
||||||
|
_isWaitingRead = false;
|
||||||
setMode(Output);
|
setMode(Output);
|
||||||
return instr;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ protected slots:
|
||||||
private:
|
private:
|
||||||
QString _codes;
|
QString _codes;
|
||||||
|
|
||||||
|
bool _isWaitingRead = false;
|
||||||
std::function<QString(void)> _getInputFn;
|
std::function<QString(void)> _getInputFn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ enum class CrashCode : int {
|
||||||
AlreadyStart,
|
AlreadyStart,
|
||||||
LanguageFile,
|
LanguageFile,
|
||||||
PluginSetting,
|
PluginSetting,
|
||||||
|
ScriptInitFailed,
|
||||||
GenericCallNotSupported
|
GenericCallNotSupported
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "class/wingmessagebox.h"
|
#include "class/wingmessagebox.h"
|
||||||
#include "class/wingupdater.h"
|
#include "class/wingupdater.h"
|
||||||
#include "control/toast.h"
|
#include "control/toast.h"
|
||||||
|
#include "define.h"
|
||||||
#include "encodingdialog.h"
|
#include "encodingdialog.h"
|
||||||
#include "fileinfodialog.h"
|
#include "fileinfodialog.h"
|
||||||
#include "finddialog.h"
|
#include "finddialog.h"
|
||||||
|
@ -254,7 +255,11 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
|
||||||
std::placeholders::_1);
|
std::placeholders::_1);
|
||||||
sm.registerCallBack(ScriptMachine::Background, callbacks);
|
sm.registerCallBack(ScriptMachine::Background, callbacks);
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
QMessageBox::critical(this, qAppName(),
|
||||||
|
tr("ScriptEngineInitFailed"));
|
||||||
|
set.setScriptEnabled(false);
|
||||||
|
set.save(SettingManager::SCRIPT);
|
||||||
|
throw CrashCode::ScriptInitFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this time, AngelScript service plugin has started
|
// At this time, AngelScript service plugin has started
|
||||||
|
@ -1011,6 +1016,10 @@ MainWindow::buildUpScriptConsoleDock(ads::CDockManager *dock,
|
||||||
showStatus(QStringLiteral("<b><font color=\"gold\">") +
|
showStatus(QStringLiteral("<b><font color=\"gold\">") +
|
||||||
content + QStringLiteral("</font></b>"));
|
content + QStringLiteral("</font></b>"));
|
||||||
});
|
});
|
||||||
|
connect(
|
||||||
|
m_scriptConsole, &ScriptingConsole::abortEvaluation, this, [this]() {
|
||||||
|
ScriptMachine::instance().abortScript(ScriptMachine::Interactive);
|
||||||
|
});
|
||||||
|
|
||||||
auto dw = buildDockWidget(dock, QStringLiteral("ScriptConsole"),
|
auto dw = buildDockWidget(dock, QStringLiteral("ScriptConsole"),
|
||||||
tr("ScriptConsole"), m_scriptConsole);
|
tr("ScriptConsole"), m_scriptConsole);
|
||||||
|
@ -3167,16 +3176,29 @@ void MainWindow::connectEditorView(EditorView *editor) {
|
||||||
editor->setProperty("__RELOAD__", false);
|
editor->setProperty("__RELOAD__", false);
|
||||||
connect(editor, &EditorView::need2Reload, this, [editor, this]() {
|
connect(editor, &EditorView::need2Reload, this, [editor, this]() {
|
||||||
if (editor->isBigFile()) {
|
if (editor->isBigFile()) {
|
||||||
editor->reload();
|
auto fileName = editor->fileName();
|
||||||
}
|
if (!QFile::exists(fileName)) {
|
||||||
if (currentEditor() == editor) {
|
editor->raise();
|
||||||
auto ret = WingMessageBox::question(this, tr("Reload"),
|
WingMessageBox::critical(this, tr("Error"),
|
||||||
tr("ReloadNeededYesOrNo"));
|
tr("FileCloseBigFile"));
|
||||||
if (ret == QMessageBox::Yes) {
|
closeEditor(editor, true);
|
||||||
|
}
|
||||||
|
if (currentEditor() == editor) {
|
||||||
editor->reload();
|
editor->reload();
|
||||||
|
} else {
|
||||||
|
editor->setProperty("__RELOAD__", true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
editor->setProperty("__RELOAD__", true);
|
editor->hexEditor()->document()->setDocSaved(false);
|
||||||
|
if (currentEditor() == editor) {
|
||||||
|
auto ret = WingMessageBox::question(this, tr("Reload"),
|
||||||
|
tr("ReloadNeededYesOrNo"));
|
||||||
|
if (ret == QMessageBox::Yes) {
|
||||||
|
editor->reload();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
editor->setProperty("__RELOAD__", true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3207,10 +3229,14 @@ void MainWindow::swapEditor(EditorView *old, EditorView *cur) {
|
||||||
auto hexeditor = cur->hexEditor();
|
auto hexeditor = cur->hexEditor();
|
||||||
auto needReload = cur->property("__RELOAD__").toBool();
|
auto needReload = cur->property("__RELOAD__").toBool();
|
||||||
if (needReload) {
|
if (needReload) {
|
||||||
auto ret = WingMessageBox::question(this, tr("Reload"),
|
if (cur->isBigFile()) {
|
||||||
tr("ReloadNeededYesOrNo"));
|
|
||||||
if (ret == QMessageBox::Yes) {
|
|
||||||
cur->reload();
|
cur->reload();
|
||||||
|
} else {
|
||||||
|
auto ret = WingMessageBox::question(this, tr("Reload"),
|
||||||
|
tr("ReloadNeededYesOrNo"));
|
||||||
|
if (ret == QMessageBox::Yes) {
|
||||||
|
cur->reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cur->setProperty("__RELOAD__", false);
|
cur->setProperty("__RELOAD__", false);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue