diff options
| author | Marcus Tillmanns <[email protected]> | 2024-06-13 14:50:37 +0200 |
|---|---|---|
| committer | Marcus Tillmanns <[email protected]> | 2024-06-24 14:29:31 +0000 |
| commit | 0214cac51d7ebda76c0fa56d9ce63663afce70fc (patch) | |
| tree | 32544c7203225c3f8fb7b37359956dac78915df9 /src/plugins/lua/luaplugin.cpp | |
| parent | c0bfd9bbd64db0bfecab1e091a01b96b60c453f1 (diff) | |
Lua: Interactive Shell
Change-Id: Iedd620abcb62b9dd3e640bcb80ae011016386484
Reviewed-by: hjk <[email protected]>
Diffstat (limited to 'src/plugins/lua/luaplugin.cpp')
| -rw-r--r-- | src/plugins/lua/luaplugin.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/plugins/lua/luaplugin.cpp b/src/plugins/lua/luaplugin.cpp index 0290df988c3..54beafafe12 100644 --- a/src/plugins/lua/luaplugin.cpp +++ b/src/plugins/lua/luaplugin.cpp @@ -3,8 +3,10 @@ #include "luaengine.h" #include "luapluginspec.h" +#include "luatr.h" #include <coreplugin/icore.h> +#include <coreplugin/ioutputpane.h> #include <coreplugin/jsexpander.h> #include <coreplugin/messagemanager.h> @@ -12,8 +14,15 @@ #include <extensionsystem/pluginmanager.h> #include <utils/algorithm.h> +#include <utils/layoutbuilder.h> +#include <utils/qtcprocess.h> +#include <utils/theme/theme.h> #include <QDebug> +#include <QLabel> +#include <QLineEdit> +#include <QListView> +#include <QStringListModel> using namespace Core; using namespace Utils; @@ -49,6 +58,164 @@ public: } }; +class LuaTerminal : public QListView +{ + Q_OBJECT + + std::unique_ptr<LuaState> m_luaState; + sol::function m_readCallback; + + QStringListModel m_model; + +public: + LuaTerminal(QWidget *parent = nullptr) + : QListView(parent) + { + setModel(&m_model); + } + + void showEvent(QShowEvent *) override + { + if (m_luaState) { + return; + } + resetTerminal(); + } + + void keyPressEvent(QKeyEvent *e) override { emit keyPressed(e); } + + void handleRequestResult(const QString &result) + { + auto cb = m_readCallback; + m_readCallback = {}; + cb(result); + } + + void resetTerminal() + { + m_model.setStringList({}); + m_readCallback = {}; + + QFile f(":/lua/scripts/ilua.lua"); + f.open(QIODevice::ReadOnly); + const auto ilua = QString::fromUtf8(f.readAll()); + m_luaState = LuaEngine::instance().runScript(ilua, "ilua.lua", [this](sol::state &lua) { + lua["print"] = [this](sol::variadic_args va) { + const QStringList msgs = LuaEngine::variadicToStringList(va) + .join("\t") + .replace("\r\n", "\n") + .split('\n'); + m_model.setStringList(m_model.stringList() + msgs); + scrollToBottom(); + }; + + sol::table async = lua.script("return require('async')", "_ilua_").get<sol::table>(); + sol::function wrap = async["wrap"]; + + lua["readline_cb"] = [this](const QString &prompt, sol::function callback) { + m_model.setStringList(m_model.stringList() << prompt); + scrollToBottom(); + emit inputRequested(prompt); + m_readCallback = callback; + }; + + lua["readline"] = wrap(lua["readline_cb"]); + }); + + QListView::reset(); + } + +signals: + void inputRequested(const QString &prompt); + void keyPressed(QKeyEvent *e); +}; + +class LineEdit : public FancyLineEdit +{ +public: + using FancyLineEdit::FancyLineEdit; + void keyPressEvent(QKeyEvent *e) override { FancyLineEdit::keyPressEvent(e); } +}; + +class LuaPane : public Core::IOutputPane +{ + Q_OBJECT + +protected: + QWidget *m_ui{nullptr}; + LuaTerminal *m_terminal{nullptr}; + +public: + LuaPane(QObject *parent = nullptr) + : Core::IOutputPane(parent) + { + setId("LuaPane"); + setDisplayName(Tr::tr("Lua")); + setPriorityInStatusBar(20); + } + + QWidget *outputWidget(QWidget *parent) override + { + using namespace Layouting; + + if (!m_ui && parent) { + m_terminal = new LuaTerminal; + LineEdit *inputEdit = new LineEdit; + QLabel *prompt = new QLabel; + + // clang-format off + m_ui = Column { + m_terminal, + Row { prompt, inputEdit }, + }.emerge(); + // clang-format on + + inputEdit->setReadOnly(true); + inputEdit->setHistoryCompleter(Utils::Key("LuaREPL.InputHistory")); + + connect(inputEdit, &QLineEdit::returnPressed, this, [this, inputEdit] { + inputEdit->setReadOnly(true); + m_terminal->handleRequestResult(inputEdit->text()); + inputEdit->onEditingFinished(); + inputEdit->clear(); + }); + connect( + m_terminal, + &LuaTerminal::inputRequested, + this, + [prompt, inputEdit](const QString &p) { + prompt->setText(p); + inputEdit->setReadOnly(false); + }); + connect(m_terminal, &LuaTerminal::keyPressed, this, [inputEdit](QKeyEvent *e) { + inputEdit->keyPressEvent(e); + inputEdit->setFocus(); + }); + } + + return m_ui; + } + + void visibilityChanged(bool) override {}; + + void clearContents() override + { + if (m_terminal) + m_terminal->resetTerminal(); + } + void setFocus() override { outputWidget(nullptr)->setFocus(); } + bool hasFocus() const override { return true; } + bool canFocus() const override { return true; } + + bool canNavigate() const override { return false; } + bool canNext() const override { return false; } + bool canPrevious() const override { return false; } + void goToNext() override {} + void goToPrev() override {} + + QList<QWidget *> toolBarWidgets() const override { return {}; } +}; + class LuaPlugin : public IPlugin { Q_OBJECT @@ -56,6 +223,7 @@ class LuaPlugin : public IPlugin private: std::unique_ptr<LuaEngine> m_luaEngine; + LuaPane *m_pane = nullptr; public: LuaPlugin() {} @@ -79,6 +247,9 @@ public: addInstallModule(); Core::JsExpander::registerGlobalObject("Lua", [] { return new LuaJsExtension(); }); + + m_pane = new LuaPane; + ExtensionSystem::PluginManager::addObject(m_pane); } bool delayedInitialize() final |
