Skip to content

Commit

Permalink
feat: add optional debounce
Browse files Browse the repository at this point in the history
  • Loading branch information
willothy committed Jun 1, 2024
1 parent 724b3b6 commit f7cc9da
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 18 deletions.
48 changes: 30 additions & 18 deletions lua/precognition/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ local M = {}
---@field NextParagraph Precognition.HintOpts

---@class Precognition.Config
---@field debounce integer
---@field startVisible boolean
---@field showBlankVirtLine boolean
---@field highlightColor vim.api.keyset.highlight
Expand Down Expand Up @@ -74,6 +75,7 @@ local defaultHintConfig = {

---@type Precognition.Config
local default = {
debounce = 0,
startVisible = true,
showBlankVirtLine = true,
highlightColor = { link = "Comment" },
Expand Down Expand Up @@ -264,21 +266,6 @@ local function display_marks()
dirty = false
end

local function on_cursor_moved(ev)
local buf = ev and ev.buf or vim.api.nvim_get_current_buf()
if extmark then
local ext = vim.api.nvim_buf_get_extmark_by_id(buf, ns, extmark, {
details = true,
})
if ext and ext[1] ~= vim.api.nvim_win_get_cursor(0)[1] - 1 then
vim.api.nvim_buf_del_extmark(0, ns, extmark)
extmark = nil
end
end
dirty = true
display_marks()
end

local function on_insert_enter(ev)
if extmark then
vim.api.nvim_buf_del_extmark(ev.buf, ns, extmark)
Expand All @@ -287,6 +274,24 @@ local function on_insert_enter(ev)
dirty = true
end

---@param draw fun()
local function cursor_moved_handler(draw)
return function(ev)
local buf = ev and ev.buf or vim.api.nvim_get_current_buf()
if extmark then
local ext = vim.api.nvim_buf_get_extmark_by_id(buf, ns, extmark, {
details = true,
})
if ext and ext[1] ~= vim.api.nvim_win_get_cursor(0)[1] - 1 then
vim.api.nvim_buf_del_extmark(0, ns, extmark)
extmark = nil
end
end
dirty = true
draw()
end
end

local function on_buf_edit()
apply_gutter_hints(build_gutter_hints())
end
Expand Down Expand Up @@ -318,6 +323,11 @@ function M.show()
end
visible = true

local draw = display_marks
if config.debounce > 0 then
draw = utils.debounce_trailing(display_marks, config.debounce)
end

-- clear the extmark entirely when leaving a buffer (hints should only show in current buffer)
vim.api.nvim_create_autocmd("BufLeave", {
group = au,
Expand All @@ -328,19 +338,21 @@ function M.show()
group = au,
callback = on_buf_edit,
})

-- clear the extmark when the cursor moves, or when insert mode is entered
--
vim.api.nvim_create_autocmd("CursorMoved", {
group = au,
callback = on_cursor_moved,
-- callback = on_cursor_moved,
callback = cursor_moved_handler(draw),
})

vim.api.nvim_create_autocmd("InsertEnter", {
group = au,
callback = on_insert_enter,
})

display_marks()
draw()
end

--- Disable automatic showing of hints
Expand Down Expand Up @@ -396,7 +408,7 @@ local state = {
return build_gutter_hints
end,
on_cursor_moved = function()
return on_cursor_moved
return cursor_moved_handler(display_marks)
end,
extmark = function()
return extmark
Expand Down
38 changes: 38 additions & 0 deletions lua/precognition/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,42 @@ function M.add_multibyte_padding(cur_line, extra_padding, line_len)
end
end

---Debounces calls to a function, and ensures it only runs once per delay
---even if called repeatedly.
---@param fn fun(...: any)
---@param delay integer
function M.debounce_trailing(fn, delay)
local running = false
local timer = assert(vim.uv.new_timer())

-- Ugly hack to ensure timer is closed when the function is garbage collected
-- unfortunate but necessary to avoid creating a new timer for each call.
--
-- In LuaJIT, only userdata can have finalizers. `newproxy` creates an opaque userdata
-- which we can attach a finalizer to and use as a "canary."
local proxy = newproxy(true)
getmetatable(proxy).__gc = function()
if not timer:is_closing() then
timer:close()
end
end

return function(...)
local _ = proxy
if running then
return
end
running = true
local args = { ... }
timer:start(
delay,
0,
vim.schedule_wrap(function()
fn(unpack(args))
running = false
end)
)
end
end

return M

0 comments on commit f7cc9da

Please sign in to comment.