aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/lua/luaengine.cpp
diff options
context:
space:
mode:
authorMarcus Tillmanns <marcus.tillmanns@qt.io>2024-05-28 12:37:08 +0200
committerMarcus Tillmanns <marcus.tillmanns@qt.io>2024-05-28 11:55:07 +0000
commitbd50ee75737688f3d8a7e81b8ad33d75f358accb (patch)
tree900923bbf36635b251efc881ecc7dfe1bf6a6ea5 /src/plugins/lua/luaengine.cpp
parent06e08178f001989e5b0a348999e4461dbfe28e6f (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.cpp87
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);