aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/core/async/init.lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2022-02-21 20:56:16 +0100
committerGitHub <noreply@github.com>2022-02-21 20:56:16 +0100
commit12d97eeabf44c2dd2cf841db218aac449022143d (patch)
tree5c8b996a262761ae2433663351861e505dbceb8d /lua/nvim-lsp-installer/core/async/init.lua
parentrun autogen_metadata.lua (diff)
downloadmason-12d97eeabf44c2dd2cf841db218aac449022143d.tar
mason-12d97eeabf44c2dd2cf841db218aac449022143d.tar.gz
mason-12d97eeabf44c2dd2cf841db218aac449022143d.tar.bz2
mason-12d97eeabf44c2dd2cf841db218aac449022143d.tar.lz
mason-12d97eeabf44c2dd2cf841db218aac449022143d.tar.xz
mason-12d97eeabf44c2dd2cf841db218aac449022143d.tar.zst
mason-12d97eeabf44c2dd2cf841db218aac449022143d.zip
feat: add async module (#499)
Diffstat (limited to 'lua/nvim-lsp-installer/core/async/init.lua')
-rw-r--r--lua/nvim-lsp-installer/core/async/init.lua107
1 files changed, 107 insertions, 0 deletions
diff --git a/lua/nvim-lsp-installer/core/async/init.lua b/lua/nvim-lsp-installer/core/async/init.lua
new file mode 100644
index 00000000..a9c1704c
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/async/init.lua
@@ -0,0 +1,107 @@
+local co = coroutine
+
+local exports = {}
+
+local Promise = {}
+Promise.__index = Promise
+
+function Promise.new(resolver)
+ return setmetatable({ resolver = resolver }, Promise)
+end
+
+function Promise:__call(callback)
+ self.resolver(function(...)
+ callback(true, ...)
+ end, function(...)
+ callback(false, ...)
+ end)
+end
+
+local function await(resolver)
+ return co.yield(Promise.new(resolver))
+end
+
+local function table_pack(...)
+ return { n = select("#", ...), ... }
+end
+
+local function promisify(async_fn)
+ return function(...)
+ local args = table_pack(...)
+ return await(function(resolve)
+ args[args.n + 1] = resolve
+ async_fn(unpack(args, 1, args.n + 1))
+ end)
+ end
+end
+
+local function new_execution_context(suspend_fn, callback, ...)
+ local thread = co.create(suspend_fn)
+ local cancelled = false
+ local step
+ step = function(...)
+ if cancelled then
+ return
+ end
+ local ok, promise_or_result = co.resume(thread, ...)
+ if ok then
+ if getmetatable(promise_or_result) == Promise then
+ promise_or_result(step)
+ else
+ callback(true, promise_or_result)
+ thread = nil
+ end
+ else
+ callback(false, promise_or_result)
+ thread = nil
+ end
+ end
+
+ step(...)
+ return function()
+ cancelled = true
+ thread = nil
+ end
+end
+
+exports.scope = function(suspend_fn)
+ return function(...)
+ return new_execution_context(suspend_fn, function() end, ...)
+ end
+end
+
+exports.run_blocking = function(suspend_fn)
+ local resolved, ok, result
+ local cancel_coroutine = new_execution_context(suspend_fn, function(a, b)
+ resolved = true
+ ok = a
+ result = b
+ end)
+
+ if vim.wait(60000, function()
+ return resolved == true
+ end, 50) then
+ if not ok then
+ error(result)
+ end
+ return result
+ else
+ cancel_coroutine()
+ error "async function failed to resolve in time."
+ end
+end
+
+exports.wait = await
+exports.promisify = promisify
+
+exports.sleep = function(ms)
+ await(function(resolve)
+ vim.defer_fn(resolve, ms)
+ end)
+end
+
+exports.scheduler = function()
+ await(vim.schedule)
+end
+
+return exports