summaryrefslogtreecommitdiff
path: root/lua/telescope/debounce.lua
diff options
context:
space:
mode:
authorTJ DeVries <devries.timothyj@gmail.com>2020-09-29 22:52:38 -0400
committerGitHub <noreply@github.com>2020-09-29 22:52:38 -0400
commitae7fd0d27a72fa3088e84992eb5040853164dad6 (patch)
tree8b2ecd59ffee6c00fa8fee5f2b570edee5da8724 /lua/telescope/debounce.lua
parent2ce23696de096733e32135b2f9698a9cca6fdcd4 (diff)
feat: Add status, better debug, and some associated refactors
* [WIP]: Mon 28 Sep 2020 01:08:24 PM EDT * add much much better tracking. so much less hax * status updates, oneshot job updates, etc. * remove temp function * add status function * asdfasdfasdf
Diffstat (limited to 'lua/telescope/debounce.lua')
-rw-r--r--lua/telescope/debounce.lua179
1 files changed, 179 insertions, 0 deletions
diff --git a/lua/telescope/debounce.lua b/lua/telescope/debounce.lua
new file mode 100644
index 0000000..329cdc5
--- /dev/null
+++ b/lua/telescope/debounce.lua
@@ -0,0 +1,179 @@
+-- Credit: https://gist.github.com/runiq/31aa5c4bf00f8e0843cd267880117201
+--
+
+local M = {}
+
+---Validates args for `throttle()` and `debounce()`.
+local function td_validate(fn, ms)
+ vim.validate{
+ fn = { fn, 'f' },
+ ms = {
+ ms,
+ function(ms)
+ return type(ms) == 'number' and ms > 0
+ end,
+ "number > 0",
+ },
+ }
+end
+
+--- Throttles a function on the leading edge. Automatically `schedule_wrap()`s.
+---
+--@param fn (function) Function to throttle
+--@param timeout (number) Timeout in ms
+--@returns (function, timer) throttled function and timer. Remember to call
+---`timer:close()` at the end or you will leak memory!
+function M.throttle_leading(fn, ms)
+ td_validate(fn, ms)
+ local timer = vim.loop.new_timer()
+ local running = false
+
+ local function wrapped_fn(...)
+ if not running then
+ timer:start(ms, 0, function()
+ running = false
+ end)
+ running = true
+ pcall(vim.schedule_wrap(fn), select(1, ...))
+ end
+ end
+ return wrapped_fn, timer
+end
+
+--- Throttles a function on the trailing edge. Automatically
+--- `schedule_wrap()`s.
+---
+--@param fn (function) Function to throttle
+--@param timeout (number) Timeout in ms
+--@param last (boolean, optional) Whether to use the arguments of the last
+---call to `fn` within the timeframe. Default: Use arguments of the first call.
+--@returns (function, timer) Throttled function and timer. Remember to call
+---`timer:close()` at the end or you will leak memory!
+function M.throttle_trailing(fn, ms, last)
+ td_validate(fn, ms)
+ local timer = vim.loop.new_timer()
+ local running = false
+
+ local wrapped_fn
+ if not last then
+ function wrapped_fn(...)
+ if not running then
+ local argv = {...}
+ local argc = select('#', ...)
+
+ timer:start(ms, 0, function()
+ running = false
+ pcall(vim.schedule_wrap(fn), unpack(argv, 1, argc))
+ end)
+ running = true
+ end
+ end
+ else
+ local argv, argc
+ function wrapped_fn(...)
+ argv = {...}
+ argc = select('#', ...)
+
+ if not running then
+ timer:start(ms, 0, function()
+ running = false
+ pcall(vim.schedule_wrap(fn), unpack(argv, 1, argc))
+ end)
+ running = true
+ end
+ end
+ end
+ return wrapped_fn, timer
+end
+
+--- Debounces a function on the leading edge. Automatically `schedule_wrap()`s.
+---
+--@param fn (function) Function to debounce
+--@param timeout (number) Timeout in ms
+--@returns (function, timer) Debounced function and timer. Remember to call
+---`timer:close()` at the end or you will leak memory!
+function M.debounce_leading(fn, ms)
+ td_validate(fn, ms)
+ local timer = vim.loop.new_timer()
+ local running = false
+
+ local function wrapped_fn(...)
+ timer:start(ms, 0, function()
+ running = false
+ end)
+
+ if not running then
+ running = true
+ pcall(vim.schedule_wrap(fn), select(1, ...))
+ end
+ end
+ return wrapped_fn, timer
+end
+
+--- Debounces a function on the trailing edge. Automatically
+--- `schedule_wrap()`s.
+---
+--@param fn (function) Function to debounce
+--@param timeout (number) Timeout in ms
+--@param first (boolean, optional) Whether to use the arguments of the first
+---call to `fn` within the timeframe. Default: Use arguments of the last call.
+--@returns (function, timer) Debounced function and timer. Remember to call
+---`timer:close()` at the end or you will leak memory!
+function M.debounce_trailing(fn, ms, first)
+ td_validate(fn, ms)
+ local timer = vim.loop.new_timer()
+ local wrapped_fn
+
+ if not first then
+ function wrapped_fn(...)
+ local argv = {...}
+ local argc = select('#', ...)
+
+ timer:start(ms, 0, function()
+ pcall(vim.schedule_wrap(fn), unpack(argv, 1, argc))
+ end)
+ end
+ else
+ local argv, argc
+ function wrapped_fn(...)
+ argv = argv or {...}
+ argc = argc or select('#', ...)
+
+ timer:start(ms, 0, function()
+ pcall(vim.schedule_wrap(fn), unpack(argv, 1, argc))
+ end)
+ end
+ end
+ return wrapped_fn, timer
+end
+
+--- Test deferment methods (`{throttle,debounce}_{leading,trailing}()`).
+---
+--@param bouncer (string) Bouncer function to test
+--@param ms (number, optional) Timeout in ms, default 2000.
+--@param firstlast (bool, optional) Whether to use the 'other' fn call
+---strategy.
+function M.test_defer(bouncer, ms, firstlast)
+ local bouncers = {
+ tl = M.throttle_leading,
+ tt = M.throttle_trailing,
+ dl = M.debounce_leading,
+ dt = M.debounce_trailing,
+ }
+
+ local timeout = ms or 2000
+
+ local bounced = bouncers[bouncer](
+ function(i) vim.cmd('echom "' .. bouncer .. ': ' .. i .. '"') end,
+ timeout,
+ firstlast
+ )
+
+ for i, _ in ipairs{1,2,3,4,5} do
+ bounced(i)
+ vim.schedule(function () vim.cmd('echom ' .. i) end)
+ vim.fn.call("wait", {1000, "v:false"})
+ end
+end
+
+return M