diff options
| author | William Boman <william@redwill.se> | 2022-02-21 20:56:16 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-21 20:56:16 +0100 |
| commit | 12d97eeabf44c2dd2cf841db218aac449022143d (patch) | |
| tree | 5c8b996a262761ae2433663351861e505dbceb8d /lua/nvim-lsp-installer/core/async/init.lua | |
| parent | run autogen_metadata.lua (diff) | |
| download | mason-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.lua | 107 |
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 |
