diff options
| author | Marcus Tillmanns <marcus.tillmanns@qt.io> | 2024-05-28 12:37:08 +0200 |
|---|---|---|
| committer | Marcus Tillmanns <marcus.tillmanns@qt.io> | 2024-05-28 11:55:07 +0000 |
| commit | bd50ee75737688f3d8a7e81b8ad33d75f358accb (patch) | |
| tree | 900923bbf36635b251efc881ecc7dfe1bf6a6ea5 /src/plugins/lua/luaengine.cpp | |
| parent | 06e08178f001989e5b0a348999e4461dbfe28e6f (diff) | |
Lua: Implement Utils::Lua
Change-Id: Ib5a7f63d1c37b29beb424707962d21102db5927c
Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/plugins/lua/luaengine.cpp')
| -rw-r--r-- | src/plugins/lua/luaengine.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/plugins/lua/luaengine.cpp b/src/plugins/lua/luaengine.cpp index be589a3b146..10d75d0979a 100644 --- a/src/plugins/lua/luaengine.cpp +++ b/src/plugins/lua/luaengine.cpp @@ -9,6 +9,7 @@ #include <coreplugin/messagemanager.h> #include <utils/algorithm.h> +#include <utils/lua.h> #include <utils/stringutils.h> #include <utils/theme/theme.h> @@ -20,6 +21,25 @@ using namespace Utils; namespace Lua { +class LuaInterfaceImpl : public Utils::LuaInterface +{ + LuaEngine *m_engine; + +public: + LuaInterfaceImpl(LuaEngine *engine) + : m_engine(engine) + { + Utils::setLuaInterface(this); + } + ~LuaInterfaceImpl() override { Utils::setLuaInterface(nullptr); } + + expected_str<std::unique_ptr<LuaState>> runScript( + const QString &script, const QString &name) override + { + return m_engine->runScript(script, name); + } +}; + class LuaEnginePrivate { public: @@ -29,6 +49,8 @@ public: QList<std::function<void(sol::state_view)>> m_autoProviders; QMap<QString, std::function<void(sol::function)>> m_hooks; + + std::unique_ptr<LuaInterfaceImpl> m_luaInterface; }; static LuaEngine *s_instance = nullptr; @@ -43,6 +65,7 @@ LuaEngine::LuaEngine() : d(new LuaEnginePrivate()) { s_instance = this; + d->m_luaInterface.reset(new LuaInterfaceImpl(this)); } LuaEngine::~LuaEngine() @@ -50,6 +73,70 @@ LuaEngine::~LuaEngine() s_instance = nullptr; } +class LuaStateImpl : public Utils::LuaState +{ +public: + sol::state lua; +}; + +// Runs the gives script in a new Lua state. The returned Object manages the lifetime of the state. +std::unique_ptr<Utils::LuaState> LuaEngine::runScript(const QString &script, const QString &name) +{ + std::unique_ptr<LuaStateImpl> opaque = std::make_unique<LuaStateImpl>(); + + opaque->lua.open_libraries( + sol::lib::base, + sol::lib::bit32, + sol::lib::coroutine, + sol::lib::debug, + sol::lib::io, + sol::lib::math, + sol::lib::os, + sol::lib::package, + sol::lib::string, + sol::lib::table, + sol::lib::utf8); + + opaque->lua["print"] = [prefix = name, printToOutputPane = true](sol::variadic_args va) { + const QString msg = variadicToStringList(va).join("\t"); + + qDebug().noquote() << "[" << prefix << "]" << msg; + if (printToOutputPane) { + static const QString p + = ansiColoredText("[" + prefix + "]", creatorTheme()->color(Theme::Token_Text_Muted)); + Core::MessageManager::writeSilently(QString("%1 %2").arg(p, msg)); + } + }; + + opaque->lua.new_usertype<ScriptPluginSpec>( + "PluginSpec", sol::no_constructor, "name", sol::property([](ScriptPluginSpec &self) { + return self.name; + })); + + opaque->lua["PluginSpec"] = ScriptPluginSpec{name, {}, std::make_unique<QObject>()}; + + for (const auto &[name, func] : d->m_providers.asKeyValueRange()) { + opaque->lua["package"]["preload"][name.toStdString()] = + [func = func](const sol::this_state &s) { return func(s); }; + } + + for (const auto &func : d->m_autoProviders) + func(opaque->lua); + + auto result + = opaque->lua + .safe_script(script.toStdString(), sol::script_pass_on_error, name.toStdString()); + + if (!result.valid()) { + sol::error err = result; + qWarning() << "Failed to run script" << name << ":" << QString::fromUtf8(err.what()); + Core::MessageManager::writeFlashing( + tr("Failed to run script %1: %2").arg(name, QString::fromUtf8(err.what()))); + } + + return opaque; +} + void LuaEngine::registerProvider(const QString &packageName, const PackageProvider &provider) { QTC_ASSERT(!instance().d->m_providers.contains(packageName), return); |
