diff --git a/lua/lazy/async.lua b/lua/lazy/async.lua index a7bcfac..1d348e9 100644 --- a/lua/lazy/async.lua +++ b/lua/lazy/async.lua @@ -9,10 +9,14 @@ local M = {} M._queue = {} M._executor = assert(vim.loop.new_check()) M._running = false +M.SLEEP = "sleep" +---@type Async +M.current = nil ---@class Async ---@field co thread ---@field opts AsyncOpts +---@field sleeping? boolean local Async = {} ---@param fn async fun() @@ -29,16 +33,38 @@ function Async:running() return coroutine.status(self.co) ~= "dead" end +function Async:sleep(ms) + self.sleeping = true + vim.defer_fn(function() + self.sleeping = false + end, ms) +end + +function Async:suspend() + self.sleeping = true +end + +function Async:resume() + self.sleeping = false +end + function Async:step() + if self.sleeping then + return true + end local status = coroutine.status(self.co) if status == "suspended" then + M.current = self local ok, res = coroutine.resume(self.co) + M.current = nil if not ok then if self.opts.on_error then self.opts.on_error(tostring(res)) end elseif res then - if self.opts.on_yield then + if res == M.SLEEP then + self.sleeping = true + elseif self.opts.on_yield then self.opts.on_yield(res) end end diff --git a/lua/lazy/manage/task/init.lua b/lua/lazy/manage/task/init.lua index 8dbffc5..e651f63 100644 --- a/lua/lazy/manage/task/init.lua +++ b/lua/lazy/manage/task/init.lua @@ -222,6 +222,8 @@ function Task:spawn(cmd, opts) end end + self._running:suspend() + local running = true local ret = true ---@param output string @@ -234,6 +236,7 @@ function Task:spawn(cmd, opts) end ret = ok running = false + self._running:resume() end if headless then @@ -244,9 +247,8 @@ function Task:spawn(cmd, opts) end end Process.spawn(cmd, opts) - while running do - coroutine.yield() - end + coroutine.yield() + assert(not running, "process still running?") return ret end diff --git a/lua/lazy/util.lua b/lua/lazy/util.lua index 09e4f54..4a3073e 100644 --- a/lua/lazy/util.lua +++ b/lua/lazy/util.lua @@ -232,13 +232,9 @@ end ---@async ---@param ms number function M.sleep(ms) - local continue = false - vim.defer_fn(function() - continue = true - end, ms) - while not continue do - coroutine.yield() - end + local async = require("lazy.async").current + assert(async, "Not in an async context") + async:sleep(ms) end function M._dump(value, result)