Add support for reloading plugins

This commit is contained in:
Mm2PL 2023-01-30 23:55:16 +01:00
parent 03de6869c4
commit 56c7e78f48
No known key found for this signature in database
GPG key ID: 94AC9B80EFA15ED9
5 changed files with 75 additions and 33 deletions

View file

@ -3233,6 +3233,11 @@ bool CommandController::registerPluginCommand(const QString &commandName)
};
return true;
}
bool CommandController::unregisterPluginCommand(const QString &commandName)
{
return this->commands_.erase(commandName) != 0;
}
void CommandController::registerCommand(const QString &commandName,
CommandFunctionVariants commandFunction)
{

View file

@ -44,6 +44,7 @@ public:
std::unordered_map<QString, QString> context = {});
bool registerPluginCommand(const QString &commandName);
bool unregisterPluginCommand(const QString &commandName);
private:
void load(Paths &paths);

View file

@ -34,27 +34,32 @@ void PluginController::initialize(Settings &settings, Paths &paths)
{
if (info.isDir())
{
// look for index.lua
auto pluginDir = QDir(info.absoluteFilePath());
this->tryLoadFromDir(pluginDir);
}
}
}
bool PluginController::tryLoadFromDir(const QDir &pluginDir)
{
// look for index.lua
auto index = QFileInfo(pluginDir.filePath("index.lua"));
qCDebug(chatterinoLua)
<< "trying" << info << "," << index << "at" << pluginDir;
qCDebug(chatterinoLua) << "looking for index.lua and info.json in"
<< pluginDir.path();
if (!index.exists())
{
qCDebug(chatterinoLua)
<< "Missing index.lua in plugin directory" << pluginDir;
continue;
return false;
}
qCDebug(chatterinoLua)
<< "found index.lua, now looking for info.json!";
auto info = QFileInfo(pluginDir.filePath("info.json"));
if (!info.exists())
qCDebug(chatterinoLua) << "found index.lua, now looking for info.json!";
auto infojson = QFileInfo(pluginDir.filePath("info.json"));
if (!infojson.exists())
{
qCDebug(chatterinoLua)
<< "Missing info.json in plugin directory" << pluginDir;
continue;
return false;
}
QFile infoFile(info.absoluteFilePath());
QFile infoFile(infojson.absoluteFilePath());
infoFile.open(QIODevice::ReadOnly);
auto everything = infoFile.readAll();
auto doc = QJsonDocument::fromJson(everything);
@ -62,12 +67,11 @@ void PluginController::initialize(Settings &settings, Paths &paths)
{
qCDebug(chatterinoLua)
<< "info.json root is not an object" << pluginDir;
continue;
return false;
}
this->load(index, pluginDir, PluginMeta(doc.object()));
}
}
return true;
}
void PluginController::load(QFileInfo index, QDir pluginDir, PluginMeta meta)
@ -78,13 +82,31 @@ void PluginController::load(QFileInfo index, QDir pluginDir, PluginMeta meta)
this->loadChatterinoLib(l);
auto pluginName = pluginDir.dirName();
auto plugin = std::make_unique<Plugin>(pluginName, l, meta);
auto plugin = std::make_unique<Plugin>(pluginName, l, meta, pluginDir);
this->plugins_.insert({pluginName, std::move(plugin)});
luaL_dofile(l, index.absoluteFilePath().toStdString().c_str());
qCInfo(chatterinoLua) << "Loaded" << pluginName << "plugin from" << index;
}
bool PluginController::reload(const QString &codename)
{
auto it = this->plugins_.find(codename);
if (it == this->plugins_.end())
{
return false;
}
lua_close(it->second->state_);
for (const auto &[cmd, _] : it->second->ownedCommands)
{
getApp()->commands->unregisterPluginCommand(cmd);
}
QDir loadDir = it->second->loadDirectory_;
this->plugins_.erase(codename);
this->tryLoadFromDir(loadDir);
return true;
}
void PluginController::callEvery(const QString &functionName)
{
for (const auto &[name, plugin] : this->plugins_)

View file

@ -47,9 +47,12 @@ class Plugin
public:
QString codename;
PluginMeta meta;
Plugin(QString codename, lua_State *state, PluginMeta meta)
Plugin(QString codename, lua_State *state, PluginMeta meta,
const QDir &loadDirectory)
: codename(std::move(codename))
, meta(std::move(meta))
, loadDirectory_(loadDirectory)
, state_(state)
{
}
@ -71,6 +74,7 @@ public:
}
private:
QDir loadDirectory_;
lua_State *state_;
// maps command name -> function name
@ -112,9 +116,12 @@ public:
return this->plugins_;
}
bool reload(const QString &codename);
private:
void load(QFileInfo index, QDir pluginDir, PluginMeta meta);
void loadChatterinoLib(lua_State *l);
bool tryLoadFromDir(const QDir &pluginDir);
std::map<QString, std::unique_ptr<Plugin>> plugins_;
};

View file

@ -10,6 +10,7 @@
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
namespace chatterino {
@ -47,6 +48,12 @@ PluginsPage::PluginsPage()
homepage->setOpenExternalLinks(true);
pl->addRow("Homepage", homepage);
auto *reload = new QPushButton("Reload");
QObject::connect(reload, &QPushButton::pressed, [=]() {
getApp()->plugins->reload(codename);
});
pl->addRow(reload);
}
}
} // namespace chatterino