lua: Change CompletionRequested handler to use an event table. (#5280)

This commit is contained in:
Mm2PL 2024-03-30 15:23:02 +01:00 committed by GitHub
parent b35f10fa54
commit d4b8feac7d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 62 additions and 15 deletions

View file

@ -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)

14
docs/chatterino.d.ts vendored
View file

@ -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> = T extends EventType.CompletionRequested
? CbFuncCompletionsRequested
: never;

View file

@ -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

View file

@ -5,6 +5,8 @@
extern "C" {
# include <lua.h>
}
# include "controllers/plugins/LuaUtilities.hpp"
# include <QString>
# include <cassert>
@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -98,8 +98,8 @@ public:
// Note: The CallbackFunction object's destructor will remove the function from the lua stack
using LuaCompletionCallback =
lua::CallbackFunction<lua::api::CompletionList, QString, QString, int,
bool>;
lua::CallbackFunction<lua::api::CompletionList,
lua::api::CompletionEvent>;
std::optional<LuaCompletionCallback> getCompletionCallback()
{
if (this->state_ == nullptr || !this->error_.isNull())
@ -123,7 +123,7 @@ public:
// move
return std::make_optional<lua::CallbackFunction<
lua::api::CompletionList, QString, QString, int, bool>>(
lua::api::CompletionList, lua::api::CompletionEvent>>(
this->state_, lua_gettop(this->state_));
}

View file

@ -433,8 +433,12 @@ std::pair<bool, QStringList> 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<int>(errOrList))
{
guard.handled();