Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 8 additions & 6 deletions docs/chatterino.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions docs/wip-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
26 changes: 25 additions & 1 deletion src/controllers/plugins/LuaAPI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
extern "C" {
# include <lua.h>
}
# include "controllers/plugins/LuaUtilities.hpp"

# include <QString>

# include <cassert>
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions src/controllers/plugins/LuaUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Mm2PL marked this conversation as resolved.
Show resolved Hide resolved
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);
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/plugins/LuaUtilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace chatterino::lua {

namespace api {
struct CompletionList;
struct CompletionEvent;
} // namespace api

constexpr int ERROR_BAD_PEEK = LUA_OK - 1;
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions src/controllers/plugins/Plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ class Plugin

// 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())
Expand All @@ -123,7 +123,7 @@ class Plugin

// 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_));
}

Expand Down
8 changes: 6 additions & 2 deletions src/controllers/plugins/PluginController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading