feat: 更好用的代码填充;更强大的控制台;一些 Bug 修复;

This commit is contained in:
寂静的羽夏 2025-04-27 23:32:03 +08:00
parent cf3d4da8e8
commit d8069aedde
18 changed files with 1614 additions and 1250 deletions

View File

@ -365,14 +365,14 @@ void QConsoleWidget::replaceCommandLine(const QString &str) {
} }
QString QConsoleWidget::currentCommandLine() const { QString QConsoleWidget::currentCommandLine() const {
// Select the text after the last command prompt ...
QTextCursor textCursor = this->textCursor(); QTextCursor textCursor = this->textCursor();
textCursor.movePosition(QTextCursor::End); textCursor.movePosition(QTextCursor::End);
textCursor.setPosition(inpos_, QTextCursor::KeepAnchor); textCursor.setPosition(inpos_, QTextCursor::KeepAnchor);
return textCursor.selectedText(); return textCursor.selectedText();
} }
int QConsoleWidget::currentHeaderPos() const { return inpos_; }
void QConsoleWidget::write(const QString &message, const QTextCharFormat &fmt) { void QConsoleWidget::write(const QString &message, const QTextCharFormat &fmt) {
QTextCharFormat currfmt = currentCharFormat(); QTextCharFormat currfmt = currentCharFormat();
QTextCursor tc = textCursor(); QTextCursor tc = textCursor();

View File

@ -79,6 +79,8 @@ public:
virtual void paste(); virtual void paste();
int currentHeaderPos() const;
public slots: public slots:
// write to StandardOutput // write to StandardOutput
@ -115,7 +117,6 @@ protected:
static History history_; static History history_;
ConsoleMode mode_; ConsoleMode mode_;
int inpos_; int inpos_;
QString currentMultiLineCode_;
QConsoleIODevice *iodevice_; QConsoleIODevice *iodevice_;
QTextCharFormat chanFormat_[nConsoleChannels]; QTextCharFormat chanFormat_[nConsoleChannels];
}; };

View File

@ -33,7 +33,8 @@ QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId)
#endif #endif
prefix = id.section(QLatin1Char('/'), -1); prefix = id.section(QLatin1Char('/'), -1);
} }
prefix.remove(QRegularExpression("[^a-zA-Z]")); static QRegularExpression regex("[^a-zA-Z]");
prefix.remove(regex);
prefix.truncate(6); prefix.truncate(6);
QByteArray idc = id.toUtf8(); QByteArray idc = id.toUtf8();
@ -69,6 +70,8 @@ QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId)
lockFile.open(QIODevice::ReadWrite); lockFile.open(QIODevice::ReadWrite);
} }
QtLocalPeer::~QtLocalPeer() { server->close(); }
bool QtLocalPeer::isClient() { bool QtLocalPeer::isClient() {
if (lockFile.isLocked()) if (lockFile.isLocked())
return false; return false;

View File

@ -15,6 +15,8 @@ class QtLocalPeer : public QObject {
public: public:
QtLocalPeer(QObject *parent = nullptr, const QString &appId = QString()); QtLocalPeer(QObject *parent = nullptr, const QString &appId = QString());
~QtLocalPeer();
bool isClient(); bool isClient();
bool sendMessage(const QByteArray &uMsg, int timeout); bool sendMessage(const QByteArray &uMsg, int timeout);
QString applicationId() const { return id; } QString applicationId() const { return id; }

View File

@ -8,7 +8,7 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PROJECT_VERSION "2.2.1") set(PROJECT_VERSION "2.2.2")
find_package( find_package(
QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network Concurrent QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network Concurrent

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{ {
"Id": "WingAngelAPI", "Id": "WingAngelAPI",
"Author": "wingsummer", "Author": "wingsummer",
"Version": "2.1.0", "Version": "2.2.2",
"Vendor": "WingCloudStudio", "Vendor": "WingCloudStudio",
"License": "AGPL-3.0", "License": "AGPL-3.0",
"Url": "https://github.com/Wing-summer/WingHexExplorer2" "Url": "https://github.com/Wing-summer/WingHexExplorer2"

View File

@ -1,6 +1,6 @@
{ {
"Id" : "WingCStruct", "Id" : "WingCStruct",
"Version" : "0.0.1", "Version" : "0.0.2",
"Vendor" : "WingCloudStudio", "Vendor" : "WingCloudStudio",
"Author" : "wingsummer", "Author" : "wingsummer",
"License" : "AGPL-v3.0", "License" : "AGPL-v3.0",

View File

@ -145,9 +145,9 @@ AppManager::AppManager(int &argc, char *argv[])
AppManager::~AppManager() { AppManager::~AppManager() {
InspectQtLogHelper::instance().destory(); InspectQtLogHelper::instance().destory();
ClangFormatManager::instance().save(); ClangFormatManager::instance().save();
// CommandHistoryManager::save(QConsoleWidget::history().strings_); CommandHistoryManager::save(QConsoleWidget::history().strings_);
_w->deleteLater(); delete _w;
_w = nullptr; _w = nullptr;
} }

View File

@ -17,6 +17,7 @@
#include "asconsolecompletion.h" #include "asconsolecompletion.h"
#include "AngelScript/sdk/angelscript/source/as_module.h"
#include "class/qascodeparser.h" #include "class/qascodeparser.h"
#include "control/scriptingconsole.h" #include "control/scriptingconsole.h"
@ -39,7 +40,7 @@ QList<CodeInfoTip> AsConsoleCompletion::parseDocument() {
return seg.isValid(); return seg.isValid();
}) == seg.end()) { }) == seg.end()) {
// wrap it to let code-completion work // wrap it to let code-completion work
code.prepend("void main(){").append('}'); code.prepend("void f(){").append('}');
} }
// first preprocess the code // first preprocess the code
@ -52,11 +53,37 @@ QList<CodeInfoTip> AsConsoleCompletion::parseDocument() {
return {}; return {};
} }
QList<CodeInfoTip> citips;
// first, global variables should be added into
auto rmod = ScriptMachine::instance().module(ScriptMachine::Interactive);
// I think hijack the internal will do the better
auto mod = dynamic_cast<asCModule *>(rmod);
if (mod) {
auto it = mod->m_scriptGlobals.List();
while (it) {
// lamda expression is great!
auto CString2ByteArray = [](const asCString &str) -> QByteArray {
return QByteArray(str.AddressOf(), str.GetLength());
};
CodeInfoTip tip;
tip.type = CodeInfoTip::Type::Variable;
tip.addinfo.insert(
CodeInfoTip::RetType,
CString2ByteArray(it->type.Format(mod->m_defaultNamespace)));
tip.nameSpace = CString2ByteArray(it->nameSpace->name);
tip.name = CString2ByteArray(it->name);
citips.append(tip);
it++;
}
}
auto data = prepc.scriptData(); auto data = prepc.scriptData();
if (data.size() == 1) { if (data.size() == 1) {
auto d = data[0]; auto d = data[0];
return parseScriptData(d.script.length() - 1, d.script); return citips + parseScriptData(d.script.length() - 1, d.script);
} else { } else {
return {}; return citips;
} }
} }

View File

@ -243,11 +243,12 @@ void ScriptMachine::exceptionCallback(asIScriptContext *context) {
const char *section; const char *section;
MessageInfo msg; MessageInfo msg;
msg.mode = mode;
msg.row = context->GetExceptionLineNumber(&msg.col, &section); msg.row = context->GetExceptionLineNumber(&msg.col, &section);
msg.type = MessageType::Error; msg.type = MessageType::Error;
msg.message = message; msg.message = message;
outputMessage(mode, msg); outputMessage(msg);
} }
} }
@ -258,10 +259,11 @@ void ScriptMachine::print(void *ref, int typeId) {
context->GetUserData(AsUserDataType::UserData_ContextMode))); context->GetUserData(AsUserDataType::UserData_ContextMode)));
MessageInfo info; MessageInfo info;
info.mode = mode;
info.type = MessageType::Print; info.type = MessageType::Print;
info.message = _debugger->toString(ref, typeId, _engine); info.message = _debugger->toString(ref, typeId, _engine);
outputMessage(mode, info); outputMessage(info);
} }
} }
@ -279,8 +281,8 @@ QString ScriptMachine::getInput() {
return {}; return {};
} }
void ScriptMachine::outputMessage(ConsoleMode mode, const MessageInfo &info) { void ScriptMachine::outputMessage(const MessageInfo &info) {
auto cbs = _regcalls.value(mode); auto cbs = _regcalls.value(info.mode);
if (cbs.printMsgFn) { if (cbs.printMsgFn) {
cbs.printMsgFn(info); cbs.printMsgFn(info);
} }
@ -356,12 +358,14 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
return false; return false;
} }
_curMode = mode;
r = builder.build(mod); r = builder.build(mod);
if (r < 0) { if (r < 0) {
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("Script failed to build"); info.message = tr("Script failed to build");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
return false; return false;
} }
@ -374,18 +378,20 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
if (func == nullptr) { if (func == nullptr) {
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("Cannot find 'int main()' or 'void main()'"); info.message = tr("Cannot find 'int main()' or 'void main()'");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
return false; return false;
} }
if (isInDebug) { if (isInDebug) {
// Allow the user to initialize the debugging before moving on // Allow the user to initialize the debugging before moving on
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("Debugging, waiting for commands."); info.message = tr("Debugging, waiting for commands.");
info.type = MessageType::Info; info.type = MessageType::Info;
outputMessage(mode, info); outputMessage(info);
} }
// Once we have the main function, we first need to initialize the // Once we have the main function, we first need to initialize the
@ -395,9 +401,10 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
r = mod->ResetGlobalVars(0); r = mod->ResetGlobalVars(0);
if (r < 0) { if (r < 0) {
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("Failed while initializing global variables"); info.message = tr("Failed while initializing global variables");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
return false; return false;
} }
@ -434,26 +441,29 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
if (r != asEXECUTION_FINISHED) { if (r != asEXECUTION_FINISHED) {
if (r == asEXECUTION_EXCEPTION) { if (r == asEXECUTION_EXCEPTION) {
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("The script failed with an exception") + info.message = tr("The script failed with an exception") +
QStringLiteral("\n") + QStringLiteral("\n") +
QString::fromStdString(GetExceptionInfo(ctx, true)); QString::fromStdString(GetExceptionInfo(ctx, true));
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
r = -1; r = -1;
} else if (r == asEXECUTION_ABORTED) { } else if (r == asEXECUTION_ABORTED) {
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("The script was aborted"); info.message = tr("The script was aborted");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
r = -1; r = -1;
} else { } else {
auto e = QMetaEnum::fromType<asEContextState>(); auto e = QMetaEnum::fromType<asEContextState>();
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("The script terminated unexpectedly") + info.message = tr("The script terminated unexpectedly") +
QStringLiteral(" (") + e.valueToKey(r) + QStringLiteral(" (") + e.valueToKey(r) +
QStringLiteral(")"); QStringLiteral(")");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
r = -1; r = -1;
} }
} else { } else {
@ -465,9 +475,10 @@ bool ScriptMachine::executeScript(ConsoleMode mode, const QString &script,
} }
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("The script exited with ") + QString::number(r); info.message = tr("The script exited with ") + QString::number(r);
info.type = MessageType::Info; info.type = MessageType::Info;
outputMessage(mode, info); outputMessage(info);
// Return the context after retrieving the return value // Return the context after retrieving the return value
_ctxMgr->DoneWithContext(ctx); _ctxMgr->DoneWithContext(ctx);
@ -523,12 +534,13 @@ void ScriptMachine::messageCallback(const asSMessageInfo *msg, void *param) {
return; return;
} }
MessageInfo info; MessageInfo info;
info.mode = ins->_curMode;
info.row = msg->row; info.row = msg->row;
info.col = msg->col; info.col = msg->col;
info.section = msg->section; info.section = msg->section;
info.message = m; info.message = m;
info.type = t; info.type = t;
ins->outputMessage(ins->_curMode, info); ins->outputMessage(info);
} }
void ScriptMachine::cleanUpDbgContext(asIScriptContext *context) { void ScriptMachine::cleanUpDbgContext(asIScriptContext *context) {
@ -1852,13 +1864,14 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
// ok, wrap the codes // ok, wrap the codes
ccode.prepend("void f(){").append("}"); ccode.prepend("void f(){").append("}");
// start to compile // start to compile
_curMode = mode;
auto cr = mod->CompileFunction(nullptr, ccode, 0, 0, &func); auto cr = mod->CompileFunction(nullptr, ccode, 0, 0, &func);
if (cr < 0) { if (cr < 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");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
return false; return false;
} }
@ -1901,23 +1914,24 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
QStringLiteral("\n") + QStringLiteral("\n") +
QString::fromStdString(GetExceptionInfo(ctx, true)); QString::fromStdString(GetExceptionInfo(ctx, true));
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
r = -1; r = -1;
} else if (r == asEXECUTION_ABORTED) { } else if (r == asEXECUTION_ABORTED) {
MessageInfo info; MessageInfo info;
info.mode = mode; info.mode = mode;
info.message = tr("The script was aborted"); info.message = tr("The script was aborted");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
r = -1; r = -1;
} else { } else {
auto e = QMetaEnum::fromType<asEContextState>(); auto e = QMetaEnum::fromType<asEContextState>();
MessageInfo info; MessageInfo info;
info.mode = mode;
info.message = tr("The script terminated unexpectedly") + info.message = tr("The script terminated unexpectedly") +
QStringLiteral(" (") + e.valueToKey(r) + QStringLiteral(" (") + e.valueToKey(r) +
QStringLiteral(")"); QStringLiteral(")");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
r = -1; r = -1;
} }
} else { } else {
@ -1932,26 +1946,39 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
return r >= 0; return r >= 0;
} else { } else {
if (ret.length() == 1) { if (std::all_of(ret.begin(), ret.end(),
auto s = ret.first(); [](const QAsCodeParser::CodeSegment &seg) {
if (s.type == QAsCodeParser::SymbolType::Variable) { return seg.type ==
auto r = mod->CompileGlobalVar(nullptr, ccode, 0); QAsCodeParser::SymbolType::Variable;
if (r < 0 || mod->ResetGlobalVars() < 0) { })) {
_curMode = mode;
for (auto &s : ret) {
auto r = mod->CompileGlobalVar(nullptr, s.codes, 0);
if (r < 0) {
MessageInfo info; MessageInfo info;
info.mode = mode; info.mode = mode;
info.message = tr("GlobalBadDecl"); info.message = tr("BadDecl:") + s.codes;
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
return false;
} }
return true;
} }
if (mod->ResetGlobalVars() < 0) {
MessageInfo info;
info.mode = mode;
info.message = tr("GlobalBadDecl");
info.type = MessageType::Error;
outputMessage(info);
}
return true;
} }
MessageInfo info; MessageInfo info;
info.mode = mode; info.mode = mode;
info.message = tr("ScriptRunUnsupported"); info.message = tr("Script failed to build");
info.type = MessageType::Error; info.type = MessageType::Error;
outputMessage(mode, info); outputMessage(info);
} }
return false; return false;
} }

View File

@ -102,10 +102,11 @@ private:
private: private:
asIScriptModule *createModule(ConsoleMode mode); asIScriptModule *createModule(ConsoleMode mode);
asIScriptModule *createModuleIfNotExist(ConsoleMode mode); asIScriptModule *createModuleIfNotExist(ConsoleMode mode);
asIScriptModule *module(ConsoleMode mode);
bool isModuleExists(ConsoleMode mode); bool isModuleExists(ConsoleMode mode);
public: public:
asIScriptModule *module(ConsoleMode mode);
static ScriptMachine &instance(); static ScriptMachine &instance();
virtual ~ScriptMachine(); virtual ~ScriptMachine();
@ -113,7 +114,7 @@ public:
public: public:
bool init(); bool init();
bool isInited() const; bool isInited() const;
bool isRunning(ConsoleMode mode = Scripting) const; bool isRunning(ConsoleMode mode) const;
static void registerEngineAddon(asIScriptEngine *engine); static void registerEngineAddon(asIScriptEngine *engine);
static void registerEngineAssert(asIScriptEngine *engine); static void registerEngineAssert(asIScriptEngine *engine);
@ -159,7 +160,8 @@ protected:
private: private:
void print(void *ref, int typeId); void print(void *ref, int typeId);
QString getInput(); QString getInput();
void outputMessage(ConsoleMode mode, const MessageInfo &info);
void outputMessage(const MessageInfo &info);
bool isType(asITypeInfo *tinfo, RegisteredType type); bool isType(asITypeInfo *tinfo, RegisteredType type);

View File

@ -21,6 +21,7 @@
#include "utilities.h" #include "utilities.h"
#include <QApplication> #include <QApplication>
#include <QPushButton>
#include <QResizeEvent> #include <QResizeEvent>
WingMessageBox::WingMessageBox() {} WingMessageBox::WingMessageBox() {}
@ -161,5 +162,10 @@ WingMessageBox::msgbox(QWidget *parent, QMessageBox::Icon icon,
QObject::connect(msgbox, &QMessageBox::finished, &d, QObject::connect(msgbox, &QMessageBox::finished, &d,
&FramelessDialogBase::done); &FramelessDialogBase::done);
return static_cast<QMessageBox::StandardButton>(d.exec()); auto ret = d.exec();
if (ret == 0) {
return msgbox->standardButton(msgbox->defaultButton());
}
return static_cast<QMessageBox::StandardButton>(ret);
} }

View File

@ -20,13 +20,17 @@
#include "class/scriptmachine.h" #include "class/scriptmachine.h"
#include "class/scriptsettings.h" #include "class/scriptsettings.h"
#include "class/skinmanager.h" #include "class/skinmanager.h"
#include "class/wingmessagebox.h"
#include "model/codecompletionmodel.h" #include "model/codecompletionmodel.h"
#include "utilities.h"
#include <QApplication> #include <QApplication>
#include <QClipboard>
#include <QColor> #include <QColor>
#include <QIcon> #include <QIcon>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMenu> #include <QMenu>
#include <QMimeData>
#include <QRegularExpression> #include <QRegularExpression>
#include <QTextBlock> #include <QTextBlock>
@ -102,9 +106,35 @@ void ScriptingConsole::init() {
void ScriptingConsole::clearConsole() { void ScriptingConsole::clearConsole() {
setMode(Output); setMode(Output);
auto cur = this->textCursor();
auto off = cur.position() - this->currentHeaderPos();
auto lastCmd = this->currentCommandLine();
auto dis = lastCmd.length() - off;
clear(); clear();
appendCommandPrompt(lastCommandPrompt());
if (lastCommandPrompt()) {
auto lines = _codes.split('\n');
auto pl = lines.begin();
appendCommandPrompt(false);
writeStdOut(*pl);
pl++;
for (; pl != lines.end(); pl++) {
appendCommandPrompt(true);
writeStdOut(*pl);
}
appendCommandPrompt(true);
} else {
appendCommandPrompt(false);
}
setMode(Input); setMode(Input);
replaceCommandLine(lastCmd);
cur = this->textCursor();
cur.movePosition(QTextCursor::EndOfBlock);
cur.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, dis);
setTextCursor(cur);
} }
void ScriptingConsole::processKeyEvent(QKeyEvent *e) { keyPressEvent(e); } void ScriptingConsole::processKeyEvent(QKeyEvent *e) { keyPressEvent(e); }
@ -183,6 +213,13 @@ void ScriptingConsole::onOutput(const ScriptMachine::MessageInfo &message) {
lastInfo.second = qMakePair(message.row, message.col); lastInfo.second = qMakePair(message.row, message.col);
} }
void ScriptingConsole::abortCurrentCode() {
setMode(Output);
_codes.clear();
appendCommandPrompt();
setMode(Input);
}
void ScriptingConsole::applyScriptSettings() { void ScriptingConsole::applyScriptSettings() {
auto &set = ScriptSettings::instance(); auto &set = ScriptSettings::instance();
auto dfont = QFont(set.consoleFontFamily()); auto dfont = QFont(set.consoleFontFamily());
@ -215,13 +252,95 @@ 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 == QStringLiteral("#ls")) { if (exec == QStringLiteral("#ls")) {
auto &ins = ScriptMachine::instance();
auto mod = ins.module(ScriptMachine::Interactive);
if (mod) {
QList<QPair<QByteArray, QByteArray>> vars;
auto total = mod->GetGlobalVarCount();
} else if (exec == QStringLiteral("#del")) { // generate codes to print
QString codes;
if (total == 0) {
codes = QStringLiteral("print(\"<none>\");");
} else {
for (asUINT i = 0; i < total; ++i) {
const char *name;
int typeId;
auto decl = mod->GetGlobalVarDeclaration(i);
if (decl && mod->GetGlobalVar(i, &name) == asSUCCESS) {
vars.emplaceBack(decl, name);
}
}
for (auto &var : vars) {
codes.append("print(\"" + var.first + " = \");print(" +
var.second + ");print(\";\\n\");");
}
}
setMode(Output);
ScriptMachine::instance().executeCode(ScriptMachine::Interactive,
codes);
_codes.clear();
appendCommandPrompt();
setMode(Input);
}
} else if (exec.startsWith(QStringLiteral("#del"))) {
// this is special command
auto &ins = ScriptMachine::instance();
auto mod = ins.module(ScriptMachine::Interactive);
if (mod) {
// first check whether contains \n
auto idx = exec.indexOf('\n');
if (idx >= 0) {
setMode(Output);
stdErr(tr("InvalidDelCmd"));
} else {
// ok, then tokens should be devided by the space
exec.remove(0, 4);
auto vars = exec.split(' ', Qt::SkipEmptyParts);
QList<asUINT> indices;
// then check
setMode(Output);
for (auto &v : vars) {
auto idx = mod->GetGlobalVarIndexByName(v.toUtf8());
if (idx >= 0) {
indices.append(idx);
} else {
stdWarn(tr("NotFoundIgnore:") + v);
}
}
std::sort(indices.begin(), indices.end(), std::greater<int>());
// ok, remove
for (auto &i : indices) {
mod->RemoveGlobalVar(i);
}
}
}
_codes.clear();
appendCommandPrompt();
setMode(Input);
} else if (exec == QStringLiteral("#cls")) { } else if (exec == QStringLiteral("#cls")) {
auto &ins = ScriptMachine::instance();
auto mod = ins.module(ScriptMachine::Interactive);
if (mod) {
auto total = mod->GetGlobalVarCount();
asUINT i = total;
do {
--i;
mod->RemoveGlobalVar(i);
} while (i);
}
_codes.clear();
appendCommandPrompt();
setMode(Input);
} else if (exec.endsWith('\\')) { } else if (exec.endsWith('\\')) {
static QRegularExpression ex(QStringLiteral("[\\\\\\s]+$")); static QRegularExpression ex(QStringLiteral("[\\\\\\s]+$"));
_codes.append('\n');
_codes += exec.remove(ex); _codes += exec.remove(ex);
setMode(Output); setMode(Output);
appendCommandPrompt(true); appendCommandPrompt(true);
@ -281,8 +400,49 @@ void ScriptingConsole::onCompletion(const QModelIndex &index) {
} }
} }
void ScriptingConsole::paste() {
if (ScriptMachine::instance().isRunning(ScriptMachine::Interactive)) {
return;
}
const QMimeData *const clipboard = QApplication::clipboard()->mimeData();
const QString text = clipboard->text();
if (!text.isEmpty()) {
if (text.indexOf('\n') < 0) {
replaceCommandLine(text);
} else {
auto ret = WingMessageBox::question(
nullptr, tr("MultiCodeCanNotUndo"), text);
if (ret == QMessageBox::No) {
return;
}
auto lines = text.split('\n');
if (lines.isEmpty()) {
return;
}
setMode(Output);
auto pl = lines.begin();
auto pend = std::prev(lines.end());
writeStdOut(*pl);
pl++;
for (; pl != pend; pl++) {
appendCommandPrompt(true);
writeStdOut(*pl);
}
appendCommandPrompt(true);
setMode(Input);
replaceCommandLine(*pl);
lines.removeLast();
_codes = lines.join('\n');
}
}
}
QString ScriptingConsole::currentCodes() const { QString ScriptingConsole::currentCodes() const {
return _codes + currentCommandLine(); QTextCursor textCursor = this->textCursor();
textCursor.setPosition(inpos_, QTextCursor::KeepAnchor);
return _codes + textCursor.selectedText();
} }
void ScriptingConsole::contextMenuEvent(QContextMenuEvent *event) { void ScriptingConsole::contextMenuEvent(QContextMenuEvent *event) {
@ -297,6 +457,15 @@ void ScriptingConsole::contextMenuEvent(QContextMenuEvent *event) {
menu.addAction(QIcon(QStringLiteral(":/qeditor/paste.png")), tr("Paste"), menu.addAction(QIcon(QStringLiteral(":/qeditor/paste.png")), tr("Paste"),
QKeySequence(QKeySequence::Paste), this, QKeySequence(QKeySequence::Paste), this,
&ScriptingConsole::paste); &ScriptingConsole::paste);
menu.addAction(ICONRES(QStringLiteral("del")), tr("Clear"),
QKeySequence(Qt::ControlModifier | Qt::Key_L), this,
&ScriptingConsole::clearConsole);
menu.addSeparator();
menu.addAction(ICONRES(QStringLiteral("dbgstop")), tr("AbortScript"),
QKeySequence(Qt::ControlModifier | Qt::Key_Q), []() {
ScriptMachine::instance().abortScript(
ScriptMachine::Background);
});
menu.exec(event->globalPos()); menu.exec(event->globalPos());
} }

View File

@ -49,6 +49,8 @@ public slots:
void onOutput(const ScriptMachine::MessageInfo &message); void onOutput(const ScriptMachine::MessageInfo &message);
void abortCurrentCode();
private slots: private slots:
void applyScriptSettings(); void applyScriptSettings();
@ -64,6 +66,7 @@ protected:
protected slots: protected slots:
virtual void onCompletion(const QModelIndex &index) override; virtual void onCompletion(const QModelIndex &index) override;
virtual void paste() override;
private: private:
QString _codes; QString _codes;

View File

@ -1016,10 +1016,15 @@ 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( connect(m_scriptConsole, &ScriptingConsole::abortEvaluation, this,
m_scriptConsole, &ScriptingConsole::abortEvaluation, this, [this]() { [this]() {
ScriptMachine::instance().abortScript(ScriptMachine::Interactive); auto &sm = ScriptMachine::instance();
}); if (sm.isRunning(ScriptMachine::Interactive)) {
sm.abortScript(ScriptMachine::Interactive);
} else {
m_scriptConsole->abortCurrentCode();
}
});
auto dw = buildDockWidget(dock, QStringLiteral("ScriptConsole"), auto dw = buildDockWidget(dock, QStringLiteral("ScriptConsole"),
tr("ScriptConsole"), m_scriptConsole); tr("ScriptConsole"), m_scriptConsole);
@ -1031,8 +1036,32 @@ MainWindow::buildUpScriptBgOutputDock(ads::CDockManager *dock,
ads::DockWidgetArea area, ads::DockWidgetArea area,
ads::CDockAreaWidget *areaw) { ads::CDockAreaWidget *areaw) {
m_bgScriptOutput = new QPlainTextEdit(this); m_bgScriptOutput = new QPlainTextEdit(this);
m_bgScriptOutput->setPlaceholderText(tr("BgScriptOutputHere"));
m_bgScriptOutput->setReadOnly(true); m_bgScriptOutput->setReadOnly(true);
auto a = newAction(
ICONRES(QStringLiteral("mStr")), tr("SelectAll"),
[this]() { m_bgScriptOutput->selectAll(); }, QKeySequence::SelectAll);
m_bgScriptOutput->addAction(a);
a = newAction(
ICONRES(QStringLiteral("copy")), tr("Copy"),
[this]() { m_bgScriptOutput->copy(); }, QKeySequence::Copy);
m_bgScriptOutput->addAction(a);
a = newAction(ICONRES(QStringLiteral("del")), tr("Clear"),
[this]() { m_bgScriptOutput->clear(); });
m_bgScriptOutput->addAction(a);
a = new QAction(this);
a->setSeparator(true);
m_bgScriptOutput->addAction(a);
a = newAction(
ICONRES(QStringLiteral("dbgstop")), tr("AbortScript"),
[]() {
ScriptMachine::instance().abortScript(ScriptMachine::Background);
},
QKeySequence(Qt::ControlModifier | Qt::Key_Q));
m_bgScriptOutput->addAction(a);
m_bgScriptOutput->setContextMenuPolicy(Qt::ActionsContextMenu);
auto dw = buildDockWidget(dock, QStringLiteral("BgScriptOutput"), auto dw = buildDockWidget(dock, QStringLiteral("BgScriptOutput"),
tr("BgScriptOutput"), m_bgScriptOutput); tr("BgScriptOutput"), m_bgScriptOutput);
return dock->addDockWidget(area, dw, areaw); return dock->addDockWidget(area, dw, areaw);

View File

@ -506,7 +506,7 @@ RibbonTabContent *ScriptingDialog::buildDebugPage(RibbonTabContent *tab) {
bool isDbg = false; bool isDbg = false;
bool isPaused = false; bool isPaused = false;
isRun = runner.isRunning(); isRun = runner.isRunning(ScriptMachine::Scripting);
isDbg = runner.isDebugMode(); isDbg = runner.isDebugMode();
auto dbg = runner.debugger(); auto dbg = runner.debugger();
isPaused = dbg->currentState() == asDebugger::PAUSE; isPaused = dbg->currentState() == asDebugger::PAUSE;
@ -740,7 +740,8 @@ void ScriptingDialog::registerEditorView(ScriptEditor *editor) {
Q_ASSERT(m_views.contains(editor)); Q_ASSERT(m_views.contains(editor));
auto &m = ScriptMachine::instance(); auto &m = ScriptMachine::instance();
if (m.isRunning() && _DebugingEditor == editor) { if (m.isRunning(ScriptMachine::Scripting) &&
_DebugingEditor == editor) {
if (WingMessageBox::warning( if (WingMessageBox::warning(
this, this->windowTitle(), tr("ScriptStillRunning"), this, this->windowTitle(), tr("ScriptStillRunning"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
@ -881,7 +882,7 @@ void ScriptingDialog::updateRunDebugMode(bool disable) {
bool isDbg = false; bool isDbg = false;
bool isPaused = false; bool isPaused = false;
isRun = runner.isRunning(); isRun = runner.isRunning(ScriptMachine::Scripting);
isDbg = runner.isDebugMode(); isDbg = runner.isDebugMode();
auto dbg = runner.debugger(); auto dbg = runner.debugger();
isPaused = dbg->currentState() == asDebugger::PAUSE; isPaused = dbg->currentState() == asDebugger::PAUSE;
@ -1437,7 +1438,7 @@ void ScriptingDialog::on_removebreakpoint() {
void ScriptingDialog::closeEvent(QCloseEvent *event) { void ScriptingDialog::closeEvent(QCloseEvent *event) {
auto &runner = ScriptMachine::instance(); auto &runner = ScriptMachine::instance();
if (runner.isRunning()) { if (runner.isRunning(ScriptMachine::Scripting)) {
if (WingMessageBox::warning( if (WingMessageBox::warning(
this, this->windowTitle(), tr("ScriptStillRunning"), this, this->windowTitle(), tr("ScriptStillRunning"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {