forked from qt-creator/qt-creator
Lua: Implement Utils::Lua
Change-Id: Ib5a7f63d1c37b29beb424707962d21102db5927c Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/lua.h>
|
||||||
#include <utils/stringutils.h>
|
#include <utils/stringutils.h>
|
||||||
#include <utils/theme/theme.h>
|
#include <utils/theme/theme.h>
|
||||||
|
|
||||||
@@ -20,6 +21,25 @@ using namespace Utils;
|
|||||||
|
|
||||||
namespace Lua {
|
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
|
class LuaEnginePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -29,6 +49,8 @@ public:
|
|||||||
QList<std::function<void(sol::state_view)>> m_autoProviders;
|
QList<std::function<void(sol::state_view)>> m_autoProviders;
|
||||||
|
|
||||||
QMap<QString, std::function<void(sol::function)>> m_hooks;
|
QMap<QString, std::function<void(sol::function)>> m_hooks;
|
||||||
|
|
||||||
|
std::unique_ptr<LuaInterfaceImpl> m_luaInterface;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LuaEngine *s_instance = nullptr;
|
static LuaEngine *s_instance = nullptr;
|
||||||
@@ -43,6 +65,7 @@ LuaEngine::LuaEngine()
|
|||||||
: d(new LuaEnginePrivate())
|
: d(new LuaEnginePrivate())
|
||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
d->m_luaInterface.reset(new LuaInterfaceImpl(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaEngine::~LuaEngine()
|
LuaEngine::~LuaEngine()
|
||||||
@@ -50,6 +73,70 @@ LuaEngine::~LuaEngine()
|
|||||||
s_instance = nullptr;
|
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)
|
void LuaEngine::registerProvider(const QString &packageName, const PackageProvider &provider)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!instance().d->m_providers.contains(packageName), return);
|
QTC_ASSERT(!instance().d->m_providers.contains(packageName), return);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <utils/expected.h>
|
#include <utils/expected.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
|
#include <utils/lua.h>
|
||||||
|
|
||||||
#include <sol/sol.hpp>
|
#include <sol/sol.hpp>
|
||||||
|
|
||||||
@@ -108,6 +109,9 @@ public:
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Runs the given script in a new Lua state. The returned Object manages the lifetime of the state.
|
||||||
|
std::unique_ptr<Utils::LuaState> runScript(const QString &script, const QString &name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Utils::expected_str<void> connectHooks(
|
Utils::expected_str<void> connectHooks(
|
||||||
sol::state_view lua, const sol::table &table, const QString &path);
|
sol::state_view lua, const sol::table &table, const QString &path);
|
||||||
|
|||||||
Reference in New Issue
Block a user