From ec6b1ef24d517c9fe6f38c910b8e36c21ec38b4c Mon Sep 17 00:00:00 2001 From: nerix Date: Wed, 22 May 2024 15:23:33 +0200 Subject: [PATCH] fix(luals-meta): generate globals in `c2` and echo @lua commands (#5385) Co-authored-by: Mm2PL --- CHANGELOG.md | 1 + docs/plugin-meta.lua | 58 +++++++++++----------- scripts/make_luals_meta.py | 43 +++++++++------- src/common/Channel.hpp | 2 +- src/controllers/plugins/LuaAPI.hpp | 2 +- src/controllers/plugins/api/ChannelRef.hpp | 44 ++++++++-------- 6 files changed, 78 insertions(+), 72 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fb4f7e57..2c85db1b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Dev: Make printing of strings in tests easier. (#5379) - Dev: Refactor and document `Scrollbar`. (#5334, #5393) - Dev: Reduced the amount of scale events. (#5404, #5406) +- Dev: All Lua globals now show in the `c2` global in the LuaLS metadata. (#5385) ## 2.5.1 diff --git a/docs/plugin-meta.lua b/docs/plugin-meta.lua index 7b72b46d5..391b5745d 100644 --- a/docs/plugin-meta.lua +++ b/docs/plugin-meta.lua @@ -16,7 +16,7 @@ c2.EventType = {} ---@class CommandContext ---@field words string[] The words typed when executing the command. For example `/foo bar baz` will result in `{"/foo", "bar", "baz"}`. ----@field channel Channel The channel the command was executed in. +---@field channel c2.Channel The channel the command was executed in. ---@class CompletionList ---@field values string[] The completions @@ -30,98 +30,98 @@ c2.EventType = {} -- Begin src/common/Channel.hpp ----@alias ChannelType integer ----@type { None: ChannelType, Direct: ChannelType, Twitch: ChannelType, TwitchWhispers: ChannelType, TwitchWatching: ChannelType, TwitchMentions: ChannelType, TwitchLive: ChannelType, TwitchAutomod: ChannelType, TwitchEnd: ChannelType, Irc: ChannelType, Misc: ChannelType } -ChannelType = {} +---@alias c2.ChannelType integer +---@type { None: c2.ChannelType, Direct: c2.ChannelType, Twitch: c2.ChannelType, TwitchWhispers: c2.ChannelType, TwitchWatching: c2.ChannelType, TwitchMentions: c2.ChannelType, TwitchLive: c2.ChannelType, TwitchAutomod: c2.ChannelType, TwitchEnd: c2.ChannelType, Irc: c2.ChannelType, Misc: c2.ChannelType } +c2.ChannelType = {} -- End src/common/Channel.hpp -- Begin src/controllers/plugins/api/ChannelRef.hpp ----@alias Platform integer +---@alias c2.Platform integer --- This enum describes a platform for the purpose of searching for a channel. --- Currently only Twitch is supported because identifying IRC channels is tricky. ----@type { Twitch: Platform } -Platform = {} +---@type { Twitch: c2.Platform } +c2.Platform = {} ----@class Channel -Channel = {} +---@class c2.Channel +c2.Channel = {} --- Returns true if the channel this object points to is valid. --- If the object expired, returns false --- If given a non-Channel object, it errors. --- ---@return boolean success -function Channel:is_valid() end +function c2.Channel:is_valid() end --- Gets the channel's name. This is the lowercase login name. --- ---@return string name -function Channel:get_name() end +function c2.Channel:get_name() end --- Gets the channel's type --- ----@return ChannelType -function Channel:get_type() end +---@return c2.ChannelType +function c2.Channel:get_type() end --- Get the channel owner's display name. This may contain non-lowercase ascii characters. --- ---@return string name -function Channel:get_display_name() end +function c2.Channel:get_display_name() end --- Sends a message to the target channel. --- Note that this does not execute client-commands. --- ---@param message string ---@param execute_commands boolean Should commands be run on the text? -function Channel:send_message(message, execute_commands) end +function c2.Channel:send_message(message, execute_commands) end --- Adds a system message client-side --- ---@param message string -function Channel:add_system_message(message) end +function c2.Channel:add_system_message(message) end --- Returns true for twitch channels. --- Compares the channel Type. Note that enum values aren't guaranteed, just --- that they are equal to the exposed enum. --- ---@return boolean -function Channel:is_twitch_channel() end +function c2.Channel:is_twitch_channel() end --- Returns a copy of the channel mode settings (subscriber only, r9k etc.) --- ---@return RoomModes -function Channel:get_room_modes() end +function c2.Channel:get_room_modes() end --- Returns a copy of the stream status. --- ---@return StreamStatus -function Channel:get_stream_status() end +function c2.Channel:get_stream_status() end --- Returns the Twitch user ID of the owner of the channel. --- ---@return string -function Channel:get_twitch_id() end +function c2.Channel:get_twitch_id() end --- Returns true if the channel is a Twitch channel and the user owns it --- ---@return boolean -function Channel:is_broadcaster() end +function c2.Channel:is_broadcaster() end --- Returns true if the channel is a Twitch channel and the user is a moderator in the channel --- Returns false for broadcaster. --- ---@return boolean -function Channel:is_mod() end +function c2.Channel:is_mod() end --- Returns true if the channel is a Twitch channel and the user is a VIP in the channel --- Returns false for broadcaster. --- ---@return boolean -function Channel:is_vip() end +function c2.Channel:is_vip() end ---@return string -function Channel:__tostring() end +function c2.Channel:__tostring() end --- Finds a channel by name. --- Misc channels are marked as Twitch: @@ -132,15 +132,15 @@ function Channel:__tostring() end --- - /automod --- ---@param name string Which channel are you looking for? ----@param platform Platform Where to search for the channel? ----@return Channel? -function Channel.by_name(name, platform) end +---@param platform c2.Platform Where to search for the channel? +---@return c2.Channel? +function c2.Channel.by_name(name, platform) end --- Finds a channel by the Twitch user ID of its owner. --- ---@param id string ID of the owner of the channel. ----@return Channel? -function Channel.by_twitch_id(id) end +---@return c2.Channel? +function c2.Channel.by_twitch_id(id) end ---@class RoomModes ---@field unique_chat boolean You might know this as r9kbeta or robot9000. diff --git a/scripts/make_luals_meta.py b/scripts/make_luals_meta.py index 58a062428..adbbeb9df 100644 --- a/scripts/make_luals_meta.py +++ b/scripts/make_luals_meta.py @@ -134,11 +134,13 @@ class Reader: def read_class_body(self) -> list[list[str]]: """The reader must be at the first line of the class/struct body. All comments inside the class are returned.""" items = [] + nesting = -1 # for the opening brace while (line := self.peek_line()) is not None: - if line.startswith("};"): + if line.startswith("};") and nesting == 0: self.next_line() break if not is_comment_start(line): + nesting += line.count("{") - line.count("}") self.next_line() continue doc = self.next_doc_comment() @@ -231,21 +233,6 @@ def read_file(path: Path, out: TextIOWrapper): else: header = doc_comment - # include block - if header[0].startswith("@includefile "): - for comment in header: - if not comment.startswith("@includefile "): - panic( - path, - reader.line_no(), - f"Invalid include block - got line '{comment}'", - ) - filename = comment.split(" ", 1)[1] - out.write(f"-- Begin src/{filename}\n\n") - read_file(repo_root / "src" / filename, out) - out.write(f"-- End src/{filename}\n\n") - continue - # enum if header[0].startswith("@exposeenum "): if len(header) > 1: @@ -270,7 +257,7 @@ def read_file(path: Path, out: TextIOWrapper): continue # class - if header[0].startswith("@lua@class "): + elif header[0].startswith("@lua@class "): name = header[0].split(" ", 1)[1] classname = name.split(":")[0].strip() printmsg(path, reader.line_no(), f"class {classname}") @@ -311,11 +298,29 @@ def read_file(path: Path, out: TextIOWrapper): for func in funcs: write_func(path, reader.line_no(), func, out) continue - # global function - if header[-1].startswith("@exposed "): + elif header[-1].startswith("@exposed "): write_func(path, reader.line_no(), doc_comment, out) continue + else: + for comment in header: + inline_command(path, reader.line_no(), comment, out) + + +def inline_command(path: Path, line: int, comment: str, out: TextIOWrapper): + if comment.startswith("@includefile "): + filename = comment.split(" ", 1)[1] + out.write(f"-- Begin src/{filename}\n\n") + read_file(repo_root / "src" / filename, out) + out.write(f"-- End src/{filename}\n\n") + elif comment.startswith("@lua@class"): + panic( + path, + line, + "Unexpected @lua@class command. @lua@class must be placed at the start of the comment block!", + ) + elif comment.startswith("@lua@"): + out.write(f'---{comment.replace("@lua", "", 1)}\n') if __name__ == "__main__": diff --git a/src/common/Channel.hpp b/src/common/Channel.hpp index 6adac6a76..601142b4a 100644 --- a/src/common/Channel.hpp +++ b/src/common/Channel.hpp @@ -32,7 +32,7 @@ class Channel : public std::enable_shared_from_this public: // This is for Lua. See scripts/make_luals_meta.py /** - * @exposeenum ChannelType + * @exposeenum c2.ChannelType */ enum class Type { None, diff --git a/src/controllers/plugins/LuaAPI.hpp b/src/controllers/plugins/LuaAPI.hpp index 15be99c6f..fd2c12e41 100644 --- a/src/controllers/plugins/LuaAPI.hpp +++ b/src/controllers/plugins/LuaAPI.hpp @@ -39,7 +39,7 @@ enum class EventType { /** * @lua@class CommandContext * @lua@field words string[] The words typed when executing the command. For example `/foo bar baz` will result in `{"/foo", "bar", "baz"}`. - * @lua@field channel Channel The channel the command was executed in. + * @lua@field channel c2.Channel The channel the command was executed in. */ /** diff --git a/src/controllers/plugins/api/ChannelRef.hpp b/src/controllers/plugins/api/ChannelRef.hpp index abc6b421f..32e1946ab 100644 --- a/src/controllers/plugins/api/ChannelRef.hpp +++ b/src/controllers/plugins/api/ChannelRef.hpp @@ -13,7 +13,7 @@ namespace chatterino::lua::api { /** * This enum describes a platform for the purpose of searching for a channel. * Currently only Twitch is supported because identifying IRC channels is tricky. - * @exposeenum Platform + * @exposeenum c2.Platform */ enum class LPlatform { Twitch, @@ -21,7 +21,7 @@ enum class LPlatform { }; /** - * @lua@class Channel + * @lua@class c2.Channel */ struct ChannelRef { static void createMetatable(lua_State *L); @@ -49,7 +49,7 @@ public: * If given a non-Channel object, it errors. * * @lua@return boolean success - * @exposed Channel:is_valid + * @exposed c2.Channel:is_valid */ static int is_valid(lua_State *L); @@ -57,15 +57,15 @@ public: * Gets the channel's name. This is the lowercase login name. * * @lua@return string name - * @exposed Channel:get_name + * @exposed c2.Channel:get_name */ static int get_name(lua_State *L); /** * Gets the channel's type * - * @lua@return ChannelType - * @exposed Channel:get_type + * @lua@return c2.ChannelType + * @exposed c2.Channel:get_type */ static int get_type(lua_State *L); @@ -73,7 +73,7 @@ public: * Get the channel owner's display name. This may contain non-lowercase ascii characters. * * @lua@return string name - * @exposed Channel:get_display_name + * @exposed c2.Channel:get_display_name */ static int get_display_name(lua_State *L); @@ -83,7 +83,7 @@ public: * * @lua@param message string * @lua@param execute_commands boolean Should commands be run on the text? - * @exposed Channel:send_message + * @exposed c2.Channel:send_message */ static int send_message(lua_State *L); @@ -91,7 +91,7 @@ public: * Adds a system message client-side * * @lua@param message string - * @exposed Channel:add_system_message + * @exposed c2.Channel:add_system_message */ static int add_system_message(lua_State *L); @@ -101,7 +101,7 @@ public: * that they are equal to the exposed enum. * * @lua@return boolean - * @exposed Channel:is_twitch_channel + * @exposed c2.Channel:is_twitch_channel */ static int is_twitch_channel(lua_State *L); @@ -113,7 +113,7 @@ public: * Returns a copy of the channel mode settings (subscriber only, r9k etc.) * * @lua@return RoomModes - * @exposed Channel:get_room_modes + * @exposed c2.Channel:get_room_modes */ static int get_room_modes(lua_State *L); @@ -121,7 +121,7 @@ public: * Returns a copy of the stream status. * * @lua@return StreamStatus - * @exposed Channel:get_stream_status + * @exposed c2.Channel:get_stream_status */ static int get_stream_status(lua_State *L); @@ -129,7 +129,7 @@ public: * Returns the Twitch user ID of the owner of the channel. * * @lua@return string - * @exposed Channel:get_twitch_id + * @exposed c2.Channel:get_twitch_id */ static int get_twitch_id(lua_State *L); @@ -137,7 +137,7 @@ public: * Returns true if the channel is a Twitch channel and the user owns it * * @lua@return boolean - * @exposed Channel:is_broadcaster + * @exposed c2.Channel:is_broadcaster */ static int is_broadcaster(lua_State *L); @@ -146,7 +146,7 @@ public: * Returns false for broadcaster. * * @lua@return boolean - * @exposed Channel:is_mod + * @exposed c2.Channel:is_mod */ static int is_mod(lua_State *L); @@ -155,7 +155,7 @@ public: * Returns false for broadcaster. * * @lua@return boolean - * @exposed Channel:is_vip + * @exposed c2.Channel:is_vip */ static int is_vip(lua_State *L); @@ -165,7 +165,7 @@ public: /** * @lua@return string - * @exposed Channel:__tostring + * @exposed c2.Channel:__tostring */ static int to_string(lua_State *L); @@ -184,9 +184,9 @@ public: * - /automod * * @lua@param name string Which channel are you looking for? - * @lua@param platform Platform Where to search for the channel? - * @lua@return Channel? - * @exposed Channel.by_name + * @lua@param platform c2.Platform Where to search for the channel? + * @lua@return c2.Channel? + * @exposed c2.Channel.by_name */ static int get_by_name(lua_State *L); @@ -194,8 +194,8 @@ public: * Finds a channel by the Twitch user ID of its owner. * * @lua@param id string ID of the owner of the channel. - * @lua@return Channel? - * @exposed Channel.by_twitch_id + * @lua@return c2.Channel? + * @exposed c2.Channel.by_twitch_id */ static int get_by_twitch_id(lua_State *L); };