WingHexExplorer2/src/control/scriptingconsole.cpp

183 lines
5.3 KiB
C++

/*==============================================================================
** 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 "scriptingconsole.h"
#include "class/scriptconsolemachine.h"
#include "qregularexpression.h"
#include <QApplication>
#include <QColor>
#include <QShortcut>
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() {}
void ScriptingConsole::stdOut(const QString &str) { writeStdOut(str); }
void ScriptingConsole::stdErr(const QString &str) { writeStdErr(str); }
void ScriptingConsole::stdWarn(const QString &str) {
write(str, QStringLiteral("stdwarn"));
}
void ScriptingConsole::newLine() { _s << Qt::endl; }
void ScriptingConsole::init() {
_s.setDevice(this->device());
_getInputFn = std::bind(&ScriptingConsole::getInput, this);
_sp = new ScriptConsoleMachine(_getInputFn, this);
connect(_sp, &ScriptConsoleMachine::onClearConsole, this,
&ScriptingConsole::clear);
connect(_sp, &ScriptConsoleMachine::onOutput, this,
[=](ScriptConsoleMachine::MessageType type,
const ScriptConsoleMachine::MessageInfo &message) {
switch (type) {
case ScriptMachine::MessageType::Info:
stdOut(tr("[Info]") + message.message);
_s << Qt::flush;
newLine();
break;
case ScriptMachine::MessageType::Warn:
stdWarn(tr("[Warn]") + message.message);
_s << Qt::flush;
newLine();
break;
case ScriptMachine::MessageType::Error:
stdErr(tr("[Error]") + message.message);
_s << Qt::flush;
newLine();
break;
case ScriptMachine::MessageType::Print:
stdOut(message.message);
break;
}
});
connect(this, &QConsoleWidget::consoleCommand, this,
&ScriptingConsole::runConsoleCommand);
}
void ScriptingConsole::initOutput() {
stdWarn(tr("Scripting console for WingHexExplorer"));
_s << Qt::endl;
stdWarn(tr(">>>> Powered by AngelScript <<<<"));
_s << Qt::endl << Qt::endl;
appendCommandPrompt();
setMode(Input);
}
void ScriptingConsole::clearConsole() {
setMode(Output);
clear();
appendCommandPrompt(_lastCommandPrompt);
setMode(Input);
}
void ScriptingConsole::pushInputCmd(const QString &cmd) {
QMutexLocker locker(&_queueLocker);
_cmdQueue.append(cmd);
}
void ScriptingConsole::runConsoleCommand(const QString &code) {
if (_waitforRead) {
_waitforRead = false;
return;
}
auto exec = code.trimmed();
if (exec.endsWith('\\')) {
static QRegularExpression ex(QStringLiteral("[\\\\\\s]+$"));
_codes += exec.remove(ex);
setMode(Output);
appendCommandPrompt(true);
setMode(Input);
} else {
setMode(Output);
_codes += exec;
if (!_sp->executeCode(_codes)) {
}
_codes.clear();
appendCommandPrompt();
setMode(Input);
}
}
QString ScriptingConsole::getInput() {
appendCommandPrompt(true);
setMode(Input);
_waitforRead = true;
QString instr;
auto d = _s.device();
d->skip(d->bytesAvailable());
do {
{
QMutexLocker locker(&_queueLocker);
if (!_cmdQueue.isEmpty()) {
instr = _cmdQueue.takeFirst();
setMode(Output);
QConsoleWidget::write(instr);
setMode(Input);
break;
}
}
qApp->processEvents();
} while (!d->waitForReadyRead(100));
instr = _s.readAll();
setMode(Output);
return instr;
}
void ScriptingConsole::appendCommandPrompt(bool storeOnly) {
QString commandPrompt;
if (storeOnly) {
commandPrompt += QStringLiteral("... > ");
} else {
auto cursor = this->cursor();
if (!cursor.atBlockStart()) {
commandPrompt = QStringLiteral("\n");
}
if (_sp && _sp->isInDebugMode()) {
commandPrompt += QStringLiteral("[dbg] > ");
} else {
commandPrompt += QStringLiteral("as > ");
}
}
_lastCommandPrompt = storeOnly;
QConsoleWidget::write(commandPrompt);
}
ScriptMachine *ScriptingConsole::machine() const { return _sp; }
ScriptConsoleMachine *ScriptingConsole::consoleMachine() const { return _sp; }