Skip to content

Commit

Permalink
feat: don't process events that are disabled in config & disable ext …
Browse files Browse the repository at this point in the history
…that are enabled in the attached GUI
  • Loading branch information
folke committed Nov 15, 2022
1 parent 0fdedab commit abb5721
Showing 1 changed file with 80 additions and 18 deletions.
98 changes: 80 additions & 18 deletions lua/noice/ui/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,81 @@ local Manager = require("noice.message.manager")

local M = {}
M._attached = false
---@type table<string, any>
M._last = {}

---@type table<string, table|false>
M._handlers = {}

function M.setup()
local widgets = {
messages = "msg",
cmdline = "cmdline",
popupmenu = "popupmenu",
}

-- Check if we're running inside a GUI that already externalizes some widgets
---@type table<string, boolean>
local ui_widgets = {}
local uis = vim.api.nvim_list_uis()
for _, ui in ipairs(uis) do
for ext, _ in pairs(widgets) do
if ui["ext_" .. ext] then
ui_widgets[ext] = true
end
end
end

M._handlers = {}

---@type table<string, boolean>
local options = {}
for ext, widget in pairs(widgets) do
-- only enable if configured and not enabeled in the GUI
if Config.options[ext].enabled and not ui_widgets[ext] then
options["ext_" .. ext] = true
M._handlers[widget] = _G.require("noice.ui." .. widget)
else
if ui_widgets[ext] and Config.options.debug then
Util.warn("Disabling ext_" .. ext)
end
M._handlers[widget] = false
end
end
return options
end

function M.enable()
local options = M.setup()

if vim.tbl_isempty(options) then
if Config.options.debug then
vim.schedule(function()
Util.warn("No extensions enabled")
end)
end
return
end

local safe_handle = Util.protect(M.handle, { msg = "An error happened while handling a ui event" })
M._attached = true

local stack_level = 0

vim.ui_attach(Config.ns, {
ext_messages = Config.options.messages.enabled,
ext_cmdline = Config.options.cmdline.enabled,
ext_popupmenu = Config.options.popupmenu.enabled,
}, function(event, ...)
-- dont process any messages during redraw, since redraw triggers last messages
-- if not Hacks.inside_redraw then
---@diagnostic disable-next-line: redundant-parameter
vim.ui_attach(Config.ns, options, function(event, ...)
local handler = M.get_handler(event, ...)

if not handler then
return
end

if stack_level > 50 then
Util.panic("Event loop detected. Shutting down...")
return
end
stack_level = stack_level + 1

local tick = Manager.tick()
safe_handle(event, ...)
safe_handle(handler, event, ...)

-- check if we need to update the ui
if Manager.tick() > tick then
Expand All @@ -42,8 +93,8 @@ function M.enable()
Util.try(Router.update)
end
else
local handler = M.parse_event(event)
Util.stats.track(handler .. ".skipped")
local widget = M.parse_event(event)
Util.stats.track(widget .. ".skipped")
end
stack_level = stack_level - 1
end)
Expand All @@ -62,16 +113,21 @@ function M.parse_event(event)
end

---@param event string
function M.handle(event, ...)
function M.get_handler(event, ...)
local event_group, event_type = event:match("([a-z]+)_(.*)")
local on = "on_" .. event_type

local ok, handler = pcall(_G.require, "noice.ui." .. event_group)
local handler = M._handlers[event_group]

-- false means this is a disabled handler
if handler == false then
return
end

if not ok then
if not handler then
if Config.options.debug then
vim.schedule(function()
Util.error("No ui router for " .. event_group)
Util.error_once("No ui router for " .. event_group)
end)
end
return
Expand All @@ -81,7 +137,7 @@ function M.handle(event, ...)
local args = { ... }
if Config.options.debug then
vim.schedule(function()
Util.error(
Util.error_once(
"No ui router for **"
.. event
.. "** events\n```lua\n"
Expand All @@ -93,7 +149,13 @@ function M.handle(event, ...)
return
end

handler[on](event, ...)
return handler[on]
end

---@param handler fun(...)
---@param event string
function M.handle(handler, event, ...)
handler(event, ...)
end

return M

0 comments on commit abb5721

Please sign in to comment.