diff options
Diffstat (limited to '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 |
