gitsigns.nvim/lua/gitsigns/debounce.lua
2023-09-07 10:30:14 +01:00

75 lines
2.0 KiB
Lua

local uv = vim.loop
local M = {}
--- Debounces a function on the trailing edge.
---
--- @generic F: function
--- @param ms number Timeout in ms
--- @param fn F Function to debounce
--- @param hash? integer|fun(...): any Function that determines id from arguments to fn
--- @return F Debounced function.
function M.debounce_trailing(ms, fn, hash)
local running = {} --- @type table<any,uv.uv_timer_t>
if type(hash) == 'number' then
local hash_i = hash
hash = function(...)
return select(hash_i, ...)
end
end
return function(...)
local id = hash and hash(...) or true
if running[id] == nil then
running[id] = assert(uv.new_timer())
end
local timer = running[id]
local argv = { ... }
timer:start(ms, 0, function()
timer:stop()
running[id] = nil
fn(unpack(argv, 1, table.maxn(argv)))
end)
end
end
--- Throttles a function using the first argument as an ID
---
--- If function is already running then the function will be scheduled to run
--- again once the running call has finished.
---
--- fn#1 _/‾\__/‾\_/‾\_____________________________
--- throttled#1 _/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\/‾‾‾‾‾‾‾‾‾‾\____________
--
--- fn#2 ______/‾\___________/‾\___________________
--- throttled#2 ______/‾‾‾‾‾‾‾‾‾‾\__/‾‾‾‾‾‾‾‾‾‾\__________
---
---
--- @generic F: function
--- @param fn F Function to throttle
--- @param schedule? boolean
--- @return F throttled function.
function M.throttle_by_id(fn, schedule)
local scheduled = {} --- @type table<any,boolean>
local running = {} --- @type table<any,boolean>
return function(id, ...)
if scheduled[id] then
-- If fn is already scheduled, then drop
return
end
if not running[id] or schedule then
scheduled[id] = true
end
if running[id] then
return
end
while scheduled[id] do
scheduled[id] = nil
running[id] = true
fn(id, ...)
running[id] = nil
end
end
end
return M