From d4b8feac7d86f941c09c4a1f54743d2882d9a54a Mon Sep 17 00:00:00 2001 From: Mm2PL Date: Sat, 30 Mar 2024 15:23:02 +0100 Subject: [PATCH] lua: Change CompletionRequested handler to use an event table. (#5280) --- CHANGELOG.md | 1 + docs/chatterino.d.ts | 14 ++++++----- docs/wip-plugins.md | 6 ++--- src/controllers/plugins/LuaAPI.hpp | 26 +++++++++++++++++++- src/controllers/plugins/LuaUtilities.cpp | 14 +++++++++++ src/controllers/plugins/LuaUtilities.hpp | 2 ++ src/controllers/plugins/Plugin.hpp | 6 ++--- src/controllers/plugins/PluginController.cpp | 8 ++++-- 8 files changed, 62 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d89ebd1ee..f9ec75070 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ - Minor: IPC files are now stored in the Chatterino directory instead of system directories on Windows. (#5226) - Minor: 7TV emotes now have a 4x image rather than a 3x image. (#5209) - Minor: Add `reward.cost` `reward.id`, `reward.title` filter variables. (#5275) +- Minor: Change Lua `CompletionRequested` handler to use an event table. (#5280) - Bugfix: Fixed an issue where certain emojis did not send to Twitch chat correctly. (#4840) - Bugfix: Fixed the `/shoutout` command not working with usernames starting with @'s (e.g. `/shoutout @forsen`). (#4800) - Bugfix: Fixed capitalized channel names in log inclusion list not being logged. (#4848) diff --git a/docs/chatterino.d.ts b/docs/chatterino.d.ts index 9bf6f57c0..95d2282be 100644 --- a/docs/chatterino.d.ts +++ b/docs/chatterino.d.ts @@ -75,6 +75,13 @@ declare module c2 { handler: (ctx: CommandContext) => void ): boolean; + class CompletionEvent { + query: string; + full_text_content: string; + cursor_position: number; + is_first_word: boolean; + } + class CompletionList { values: String[]; hide_others: boolean; @@ -84,12 +91,7 @@ declare module c2 { CompletionRequested = "CompletionRequested", } - type CbFuncCompletionsRequested = ( - query: string, - full_text_content: string, - cursor_position: number, - is_first_word: boolean - ) => CompletionList; + type CbFuncCompletionsRequested = (ev: CompletionEvent) => CompletionList; type CbFunc = T extends EventType.CompletionRequested ? CbFuncCompletionsRequested : never; diff --git a/docs/wip-plugins.md b/docs/wip-plugins.md index 1309d7bab..32eda387f 100644 --- a/docs/wip-plugins.md +++ b/docs/wip-plugins.md @@ -167,7 +167,7 @@ Limitations/known issues: #### `register_callback("CompletionRequested", handler)` -Registers a callback (`handler`) to process completions. The callback gets the following parameters: +Registers a callback (`handler`) to process completions. The callback takes a single table with the following entries: - `query`: The queried word. - `full_text_content`: The whole input. @@ -190,8 +190,8 @@ end c2.register_callback( "CompletionRequested", - function(query, full_text_content, cursor_position, is_first_word) - if ("!join"):startswith(query) then + function(event) + if ("!join"):startswith(event.query) then ---@type CompletionList return { hide_others = true, values = { "!join" } } end diff --git a/src/controllers/plugins/LuaAPI.hpp b/src/controllers/plugins/LuaAPI.hpp index df042b24f..39df15216 100644 --- a/src/controllers/plugins/LuaAPI.hpp +++ b/src/controllers/plugins/LuaAPI.hpp @@ -5,6 +5,8 @@ extern "C" { # include } +# include "controllers/plugins/LuaUtilities.hpp" + # include # include @@ -55,6 +57,28 @@ struct CompletionList { bool hideOthers{}; }; +/** + * @lua@class CompletionEvent + */ +struct CompletionEvent { + /** + * @lua@field query string The word being completed + */ + QString query; + /** + * @lua@field full_text_content string Content of the text input + */ + QString full_text_content; + /** + * @lua@field cursor_position integer Position of the cursor in the text input in unicode codepoints (not bytes) + */ + int cursor_position{}; + /** + * @lua@field is_first_word boolean True if this is the first word in the input + */ + bool is_first_word{}; +}; + /** * @includefile common/Channel.hpp * @includefile controllers/plugins/api/ChannelRef.hpp @@ -74,7 +98,7 @@ int c2_register_command(lua_State *L); * Registers a callback to be invoked when completions for a term are requested. * * @lua@param type "CompletionRequested" - * @lua@param func fun(query: string, full_text_content: string, cursor_position: integer, is_first_word: boolean): CompletionList The callback to be invoked. + * @lua@param func fun(event: CompletionEvent): CompletionList The callback to be invoked. * @exposed c2.register_callback */ int c2_register_callback(lua_State *L); diff --git a/src/controllers/plugins/LuaUtilities.cpp b/src/controllers/plugins/LuaUtilities.cpp index 9361cd1ff..64af18c01 100644 --- a/src/controllers/plugins/LuaUtilities.cpp +++ b/src/controllers/plugins/LuaUtilities.cpp @@ -142,6 +142,20 @@ StackIdx push(lua_State *L, const int &b) return lua_gettop(L); } +StackIdx push(lua_State *L, const api::CompletionEvent &ev) +{ + auto idx = pushEmptyTable(L, 4); +# define PUSH(field) \ + lua::push(L, ev.field); \ + lua_setfield(L, idx, #field) + PUSH(query); + PUSH(full_text_content); + PUSH(cursor_position); + PUSH(is_first_word); +# undef PUSH + return idx; +} + bool peek(lua_State *L, int *out, StackIdx idx) { StackGuard guard(L); diff --git a/src/controllers/plugins/LuaUtilities.hpp b/src/controllers/plugins/LuaUtilities.hpp index 4c78d6edc..5443a751f 100644 --- a/src/controllers/plugins/LuaUtilities.hpp +++ b/src/controllers/plugins/LuaUtilities.hpp @@ -28,6 +28,7 @@ namespace chatterino::lua { namespace api { struct CompletionList; + struct CompletionEvent; } // namespace api constexpr int ERROR_BAD_PEEK = LUA_OK - 1; @@ -66,6 +67,7 @@ StackIdx push(lua_State *L, const QString &str); StackIdx push(lua_State *L, const std::string &str); StackIdx push(lua_State *L, const bool &b); StackIdx push(lua_State *L, const int &b); +StackIdx push(lua_State *L, const api::CompletionEvent &ev); // returns OK? bool peek(lua_State *L, int *out, StackIdx idx = -1); diff --git a/src/controllers/plugins/Plugin.hpp b/src/controllers/plugins/Plugin.hpp index 4450b2a01..2adbe9067 100644 --- a/src/controllers/plugins/Plugin.hpp +++ b/src/controllers/plugins/Plugin.hpp @@ -98,8 +98,8 @@ public: // Note: The CallbackFunction object's destructor will remove the function from the lua stack using LuaCompletionCallback = - lua::CallbackFunction; + lua::CallbackFunction; std::optional getCompletionCallback() { if (this->state_ == nullptr || !this->error_.isNull()) @@ -123,7 +123,7 @@ public: // move return std::make_optional>( + lua::api::CompletionList, lua::api::CompletionEvent>>( this->state_, lua_gettop(this->state_)); } diff --git a/src/controllers/plugins/PluginController.cpp b/src/controllers/plugins/PluginController.cpp index 0f23df343..8c2d80556 100644 --- a/src/controllers/plugins/PluginController.cpp +++ b/src/controllers/plugins/PluginController.cpp @@ -433,8 +433,12 @@ std::pair PluginController::updateCustomCompletions( qCDebug(chatterinoLua) << "Processing custom completions from plugin" << name; auto &cb = *opt; - auto errOrList = - cb(query, fullTextContent, cursorPosition, isFirstWord); + auto errOrList = cb(lua::api::CompletionEvent{ + .query = query, + .full_text_content = fullTextContent, + .cursor_position = cursorPosition, + .is_first_word = isFirstWord, + }); if (std::holds_alternative(errOrList)) { guard.handled();