mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Add proper support for logging from lua
This commit is contained in:
parent
b1031c7211
commit
86c872d4af
4 changed files with 118 additions and 3 deletions
|
@ -55,7 +55,30 @@ The official manual for them is available [here](https://www.lua.org/manual/5.4/
|
||||||
|
|
||||||
### Chatterino API
|
### Chatterino API
|
||||||
|
|
||||||
All Chatterino functions are exposed in a global table called `c2`. The following functions are available
|
All Chatterino functions are exposed in a global table called `c2`. The following members are available:
|
||||||
|
|
||||||
|
#### `log(level, args...)`
|
||||||
|
|
||||||
|
Writes a message to the Chatterino log. The `level` argument should be a
|
||||||
|
`LogLevel` member. All `args` should be convertible to a string with
|
||||||
|
`tostring()`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
c2.log(c2.LogLevel.Warning, "Hello, this should show up in the Chatterino log by default")
|
||||||
|
|
||||||
|
c2.log(c2.LogLevel.Debug, "Hello world")
|
||||||
|
-- Equivalent to doing qCDebug(chatterinoLua) << "[pluginDirectory:Plugin Name]" << "Hello, world"; from C++
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `LogLevel` enum
|
||||||
|
|
||||||
|
This table describes log levels available to Lua Plugins. The values behind the names may change, do not count on them. It has the following keys:
|
||||||
|
|
||||||
|
- `Debug`
|
||||||
|
- `Info`
|
||||||
|
- `Warning`
|
||||||
|
- `Critical`
|
||||||
|
|
||||||
#### `register_command(name, handler)`
|
#### `register_command(name, handler)`
|
||||||
|
|
||||||
|
@ -139,3 +162,7 @@ execfile("./stuff.lua") -- executes Plugins/name/stuff.lua
|
||||||
execfile("../stuff.lua") -- tries to load Plugins/stuff.lua and errors
|
execfile("../stuff.lua") -- tries to load Plugins/stuff.lua and errors
|
||||||
execfile("luac.out") -- tried to load Plugins/name/luac.out and errors because it contains non-utf8 data
|
execfile("luac.out") -- tried to load Plugins/name/luac.out and errors because it contains non-utf8 data
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `print(Args...)`
|
||||||
|
|
||||||
|
The `print` global function is equivalent to calling `c2.log(c2.LogLevel.Debug, Args...)`
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# include "lualib.h"
|
# include "lualib.h"
|
||||||
|
|
||||||
# include <QFileInfo>
|
# include <QFileInfo>
|
||||||
|
# include <QLoggingCategory>
|
||||||
# include <QTextCodec>
|
# include <QTextCodec>
|
||||||
|
|
||||||
// NOLINTBEGIN(*vararg)
|
// NOLINTBEGIN(*vararg)
|
||||||
|
@ -102,6 +103,63 @@ int c2_system_msg(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void logHelper(lua_State *L, Plugin *pl, QDebug stream, int argc)
|
||||||
|
{
|
||||||
|
stream.noquote();
|
||||||
|
stream << "[" + pl->codename + ":" + pl->meta.name + "]";
|
||||||
|
for (int i = 1; i <= argc; i++)
|
||||||
|
{
|
||||||
|
stream << lua::toString(L, i);
|
||||||
|
}
|
||||||
|
lua_pop(L, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int c2_log(lua_State *L)
|
||||||
|
{
|
||||||
|
auto *pl = getApp()->plugins->getPluginByStatePtr(L);
|
||||||
|
if (pl == nullptr)
|
||||||
|
{
|
||||||
|
luaL_error(L, "print: internal error: no plugin?");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto logc = lua_gettop(L) - 1;
|
||||||
|
// this is the expansion of qCDebug() macro
|
||||||
|
auto temp =
|
||||||
|
(QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE,
|
||||||
|
QT_MESSAGELOG_FUNC, chatterinoLua().categoryName()));
|
||||||
|
|
||||||
|
LogLevel lvl{};
|
||||||
|
if (!lua::pop(L, &lvl, 1))
|
||||||
|
{
|
||||||
|
luaL_error(L, "Invalid log level, use one from c2.LogLevel.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
QDebug stream{(QString *)nullptr};
|
||||||
|
switch (lvl)
|
||||||
|
{
|
||||||
|
case LogLevel::Debug:
|
||||||
|
stream = temp.debug();
|
||||||
|
break;
|
||||||
|
case LogLevel::Critical:
|
||||||
|
stream = temp.critical();
|
||||||
|
break;
|
||||||
|
case LogLevel::Info:
|
||||||
|
stream = temp.info();
|
||||||
|
break;
|
||||||
|
case LogLevel::Warning:
|
||||||
|
stream = temp.warning();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false && "if this happens magic_enum must have failed us");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
logHelper(L, pl, stream, logc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int g_load(lua_State *L)
|
int g_load(lua_State *L)
|
||||||
{
|
{
|
||||||
auto countArgs = lua_gettop(L);
|
auto countArgs = lua_gettop(L);
|
||||||
|
@ -207,6 +265,24 @@ int g_dofile(lua_State *L)
|
||||||
return lua_gettop(L);
|
return lua_gettop(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int g_print(lua_State *L)
|
||||||
|
{
|
||||||
|
auto *pl = getApp()->plugins->getPluginByStatePtr(L);
|
||||||
|
if (pl == nullptr)
|
||||||
|
{
|
||||||
|
luaL_error(L, "print: internal error: no plugin?");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto argc = lua_gettop(L);
|
||||||
|
// this is the expansion of qCDebug() macro
|
||||||
|
auto stream =
|
||||||
|
(QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE,
|
||||||
|
QT_MESSAGELOG_FUNC, chatterinoLua().categoryName())
|
||||||
|
.debug());
|
||||||
|
logHelper(L, pl, stream, argc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino::lua::api
|
} // namespace chatterino::lua::api
|
||||||
// NOLINTEND(*vararg)
|
// NOLINTEND(*vararg)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,11 +9,16 @@ namespace chatterino::lua::api {
|
||||||
int c2_register_command(lua_State *L);
|
int c2_register_command(lua_State *L);
|
||||||
int c2_send_msg(lua_State *L);
|
int c2_send_msg(lua_State *L);
|
||||||
int c2_system_msg(lua_State *L);
|
int c2_system_msg(lua_State *L);
|
||||||
|
int c2_log(lua_State *L);
|
||||||
|
|
||||||
int g_load(lua_State *L);
|
int g_load(lua_State *L);
|
||||||
int g_dofile(lua_State *L);
|
int g_dofile(lua_State *L);
|
||||||
|
int g_print(lua_State *L);
|
||||||
// NOLINTEND(readability-identifier-naming)
|
// NOLINTEND(readability-identifier-naming)
|
||||||
|
|
||||||
|
// Represents "calls" to qCDebug, qCInfo ...
|
||||||
|
enum LogLevel { Debug, Info, Warning, Critical };
|
||||||
|
|
||||||
} // namespace chatterino::lua::api
|
} // namespace chatterino::lua::api
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -147,15 +147,20 @@ void PluginController::openLibrariesFor(lua_State *L,
|
||||||
{"system_msg", lua::api::c2_system_msg},
|
{"system_msg", lua::api::c2_system_msg},
|
||||||
{"register_command", lua::api::c2_register_command},
|
{"register_command", lua::api::c2_register_command},
|
||||||
{"send_msg", lua::api::c2_send_msg},
|
{"send_msg", lua::api::c2_send_msg},
|
||||||
|
{"log", lua::api::c2_log},
|
||||||
{nullptr, nullptr},
|
{nullptr, nullptr},
|
||||||
};
|
};
|
||||||
lua_pushglobaltable(L);
|
lua_pushglobaltable(L);
|
||||||
auto global = lua_gettop(L);
|
auto global = lua_gettop(L);
|
||||||
|
|
||||||
// count of elements in C2LIB - 1 (to account for terminator)
|
// count of elements in C2LIB + LogLevel
|
||||||
lua::pushEmptyTable(L, 3);
|
auto c2libIdx = lua::pushEmptyTable(L, 5);
|
||||||
|
|
||||||
luaL_setfuncs(L, c2Lib, 0);
|
luaL_setfuncs(L, c2Lib, 0);
|
||||||
|
|
||||||
|
lua::pushEnumTable<lua::api::LogLevel>(L);
|
||||||
|
lua_setfield(L, c2libIdx, "LogLevel");
|
||||||
|
|
||||||
lua_setfield(L, global, "c2");
|
lua_setfield(L, global, "c2");
|
||||||
|
|
||||||
// ban functions
|
// ban functions
|
||||||
|
@ -177,6 +182,8 @@ void PluginController::openLibrariesFor(lua_State *L,
|
||||||
|
|
||||||
// chatterino dofile is way more similar to require() than dofile()
|
// chatterino dofile is way more similar to require() than dofile()
|
||||||
{"execfile", lua::api::g_dofile},
|
{"execfile", lua::api::g_dofile},
|
||||||
|
|
||||||
|
{"print", lua::api::g_print},
|
||||||
{nullptr, nullptr},
|
{nullptr, nullptr},
|
||||||
};
|
};
|
||||||
luaL_setfuncs(L, replacementFuncs, 0);
|
luaL_setfuncs(L, replacementFuncs, 0);
|
||||||
|
|
Loading…
Reference in a new issue