lazy.nvim/lua/lazy/manage/task/init.lua

176 lines
4.2 KiB
Lua
Raw Normal View History

2024-06-26 21:11:31 +08:00
local Async = require("lazy.async")
local Process = require("lazy.manage.process")
2022-11-28 18:04:32 +08:00
---@class LazyTaskDef
---@field skip? fun(plugin:LazyPlugin, opts?:TaskOptions):any?
---@field run fun(task:LazyTask, opts:TaskOptions)
2022-11-28 18:04:32 +08:00
---@alias LazyTaskFn async fun(task:LazyTask, opts:TaskOptions)
2024-06-26 20:28:53 +08:00
2022-11-21 06:04:56 +08:00
---@class LazyTask
---@field plugin LazyPlugin
---@field name string
2022-11-28 18:04:32 +08:00
---@field output string
---@field status string
---@field error? string
---@field warn? string
---@field private _started? number
---@field private _ended? number
2022-11-28 18:04:32 +08:00
---@field private _opts TaskOptions
---@field private _running Async
2022-11-21 06:04:56 +08:00
local Task = {}
---@class TaskOptions: {[string]:any}
2022-11-28 14:35:58 +08:00
---@field on_done? fun(task:LazyTask)
2022-11-21 06:04:56 +08:00
---@param plugin LazyPlugin
---@param name string
2022-11-23 23:12:43 +08:00
---@param opts? TaskOptions
---@param task LazyTaskFn
function Task.new(plugin, name, task, opts)
local self = setmetatable({}, { __index = Task })
2022-11-28 18:04:32 +08:00
self._opts = opts or {}
2022-11-21 06:04:56 +08:00
self.plugin = plugin
self.name = name
2022-11-21 06:04:56 +08:00
self.output = ""
self.status = ""
---@param other LazyTask
plugin._.tasks = vim.tbl_filter(function(other)
return other.name ~= name or other:is_running()
2024-06-26 20:28:53 +08:00
end, plugin._.tasks or {})
table.insert(plugin._.tasks, self)
self:_start(task)
2022-11-21 06:04:56 +08:00
return self
end
2022-11-28 18:04:32 +08:00
function Task:has_started()
return self._started ~= nil
2022-11-21 06:04:56 +08:00
end
2024-06-26 20:28:53 +08:00
function Task:has_ended()
return self._ended ~= nil
end
2022-11-28 18:04:32 +08:00
function Task:is_running()
return not self:has_ended()
2022-11-21 06:04:56 +08:00
end
---@private
---@param task LazyTaskFn
function Task:_start(task)
2024-06-26 20:28:53 +08:00
assert(not self:has_started(), "task already started")
assert(not self:has_ended(), "task already done")
self._started = vim.uv.hrtime()
---@async
self._running = Async.run(function()
task(self, self._opts)
end, {
on_done = function()
self:_done()
end,
on_error = function(err)
self:notify_error(err)
end,
on_yield = function(res)
self:notify(res)
end,
})
2022-11-21 06:04:56 +08:00
end
---@param msg string|string[]
---@param severity? vim.diagnostic.Severity
function Task:notify(msg, severity)
local var = severity == vim.diagnostic.severity.ERROR and "error"
or severity == vim.diagnostic.severity.WARN and "warn"
or "output"
msg = type(msg) == "table" and table.concat(msg, "\n") or msg
---@cast msg string
---@diagnostic disable-next-line: no-unknown
self[var] = self[var] and (self[var] .. "\n" .. msg) or msg
self.status = msg
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
end
---@param msg string|string[]
function Task:notify_error(msg)
self:notify(msg, vim.diagnostic.severity.ERROR)
end
---@param msg string|string[]
function Task:notify_warn(msg)
self:notify(msg, vim.diagnostic.severity.WARN)
end
2024-06-26 20:28:53 +08:00
---@private
function Task:_done()
assert(self:has_started(), "task not started")
assert(not self:has_ended(), "task already done")
2024-06-26 21:11:31 +08:00
if self._running and self._running:running() then
return
2024-06-26 21:11:31 +08:00
end
self._ended = vim.uv.hrtime()
2022-11-28 18:04:32 +08:00
if self._opts.on_done then
self._opts.on_done(self)
2022-11-23 23:12:43 +08:00
end
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
2022-11-28 18:04:32 +08:00
vim.api.nvim_exec_autocmds("User", {
pattern = "LazyPlugin" .. self.name:sub(1, 1):upper() .. self.name:sub(2),
2022-11-28 18:04:32 +08:00
data = { plugin = self.plugin.name },
})
end
function Task:time()
if not self:has_started() then
return 0
end
2024-06-26 20:28:53 +08:00
if not self:has_ended() then
return (vim.uv.hrtime() - self._started) / 1e6
end
return (self._ended - self._started) / 1e6
end
2024-06-26 20:28:53 +08:00
---@async
2022-11-21 06:04:56 +08:00
---@param cmd string
2022-11-28 18:04:32 +08:00
---@param opts? ProcessOpts
2022-11-21 06:04:56 +08:00
function Task:spawn(cmd, opts)
opts = opts or {}
local on_line = opts.on_line
local on_exit = opts.on_exit
function opts.on_line(line)
self.status = line
if on_line then
pcall(on_line, line)
end
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
2022-11-21 06:04:56 +08:00
end
2024-06-26 20:28:53 +08:00
local running = true
2022-11-28 18:04:32 +08:00
---@param output string
2022-11-21 06:04:56 +08:00
function opts.on_exit(ok, output)
2022-11-28 18:04:32 +08:00
self.output = self.output .. output
2022-11-21 06:04:56 +08:00
if not ok then
2022-11-28 18:04:32 +08:00
self.error = self.error and (self.error .. "\n" .. output) or output
2022-11-21 06:04:56 +08:00
end
if on_exit then
pcall(on_exit, ok, output)
end
2024-06-26 20:28:53 +08:00
running = false
end
Process.spawn(cmd, opts)
while running do
coroutine.yield()
2022-11-21 06:04:56 +08:00
end
2022-11-23 04:12:50 +08:00
end
2022-11-21 06:04:56 +08:00
2022-11-28 18:04:32 +08:00
function Task:wait()
while self:is_running() do
vim.wait(10)
2022-11-21 06:04:56 +08:00
end
end
return Task