summaryrefslogtreecommitdiff
path: root/start/cmp/lua/cmp/utils/async.lua
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-05-22 22:47:23 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2022-05-22 22:47:23 +0100
commit95aea6b533e71e478d61d18fac71cca116c56a4d (patch)
tree1a1f42f723772258cc54551495826768f374474a /start/cmp/lua/cmp/utils/async.lua
Add all the plugins I currently use
Diffstat (limited to 'start/cmp/lua/cmp/utils/async.lua')
-rw-r--r--start/cmp/lua/cmp/utils/async.lua127
1 files changed, 127 insertions, 0 deletions
diff --git a/start/cmp/lua/cmp/utils/async.lua b/start/cmp/lua/cmp/utils/async.lua
new file mode 100644
index 0000000..13f126b
--- /dev/null
+++ b/start/cmp/lua/cmp/utils/async.lua
@@ -0,0 +1,127 @@
+local async = {}
+
+---@class cmp.AsyncThrottle
+---@field public running boolean
+---@field public timeout number
+---@field public sync function(self: cmp.AsyncThrottle, timeout: number|nil)
+---@field public stop function
+---@field public __call function
+
+---@param fn function
+---@param timeout number
+---@return cmp.AsyncThrottle
+async.throttle = function(fn, timeout)
+ local time = nil
+ local timer = vim.loop.new_timer()
+ return setmetatable({
+ running = false,
+ timeout = timeout,
+ sync = function(self, timeout_)
+ vim.wait(timeout_ or 1000, function()
+ return not self.running
+ end)
+ end,
+ stop = function()
+ time = nil
+ timer:stop()
+ end,
+ }, {
+ __call = function(self, ...)
+ local args = { ... }
+
+ if time == nil then
+ time = vim.loop.now()
+ end
+
+ self.running = true
+ timer:stop()
+ timer:start(math.max(1, self.timeout - (vim.loop.now() - time)), 0, function()
+ vim.schedule(function()
+ time = nil
+ fn(unpack(args))
+ self.running = false
+ end)
+ end)
+ end,
+ })
+end
+
+---Control async tasks.
+async.step = function(...)
+ local tasks = { ... }
+ local next
+ next = function(...)
+ if #tasks > 0 then
+ table.remove(tasks, 1)(next, ...)
+ end
+ end
+ table.remove(tasks, 1)(next)
+end
+
+---Timeout callback function
+---@param fn function
+---@param timeout number
+---@return function
+async.timeout = function(fn, timeout)
+ local timer
+ local done = false
+ local callback = function(...)
+ if not done then
+ done = true
+ timer:stop()
+ timer:close()
+ fn(...)
+ end
+ end
+ timer = vim.loop.new_timer()
+ timer:start(timeout, 0, function()
+ callback()
+ end)
+ return callback
+end
+
+---@alias cmp.AsyncDedup fun(callback: function): function
+
+---Create deduplicated callback
+---@return function
+async.dedup = function()
+ local id = 0
+ return function(callback)
+ id = id + 1
+
+ local current = id
+ return function(...)
+ if current == id then
+ callback(...)
+ end
+ end
+ end
+end
+
+---Convert async process as sync
+async.sync = function(runner, timeout)
+ local done = false
+ runner(function()
+ done = true
+ end)
+ vim.wait(timeout, function()
+ return done
+ end, 10, false)
+end
+
+---Wait and callback for next safe state.
+async.debounce_next_tick = function(callback)
+ local running = false
+ return function()
+ if running then
+ return
+ end
+ running = true
+ vim.schedule(function()
+ running = false
+ callback()
+ end)
+ end
+end
+
+return async