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

171 lines
3.8 KiB
Lua
Raw Normal View History

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 LazyTaskState fun():boolean?
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 private _task fun(task:LazyTask)
---@field private _running LazyPluginState[]
---@field private _started? number
---@field private _ended? number
2022-11-28 18:04:32 +08:00
---@field private _opts TaskOptions
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
2022-11-28 18:04:32 +08:00
---@param task fun(task:LazyTask)
function Task.new(plugin, name, task, opts)
2022-11-21 06:04:56 +08:00
local self = setmetatable({}, {
__index = Task,
})
2022-11-28 18:04:32 +08:00
self._opts = opts or {}
self._running = {}
self._task = task
self._started = nil
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 = ""
plugin._.tasks = plugin._.tasks or {}
---@param other LazyTask
plugin._.tasks = vim.tbl_filter(function(other)
return other.name ~= name or other:is_running()
end, plugin._.tasks)
table.insert(plugin._.tasks, self)
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
2022-11-28 18:04:32 +08:00
function Task:is_done()
return self:has_started() and not self:is_running()
2022-11-21 06:04:56 +08:00
end
2022-11-28 18:04:32 +08:00
function Task:is_running()
return self:has_started() and self._ended == nil
2022-11-21 06:04:56 +08:00
end
2022-11-28 18:04:32 +08:00
function Task:start()
if vim.in_fast_event() then
return vim.schedule(function()
self:start()
end)
end
self._started = vim.loop.hrtime()
2022-11-28 18:04:32 +08:00
---@type boolean, string|any
local ok, err = pcall(self._task, self, self._opts)
2022-11-28 18:04:32 +08:00
if not ok then
self.error = err or "failed"
2022-11-21 06:04:56 +08:00
end
2022-11-28 18:04:32 +08:00
self:_check()
2022-11-21 06:04:56 +08:00
end
2022-11-28 18:04:32 +08:00
---@private
function Task:_check()
for _, state in ipairs(self._running) do
if state() then
return
end
2022-11-28 18:04:32 +08:00
end
self._ended = vim.loop.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
if not self:is_done() then
return (vim.loop.hrtime() - self._started) / 1e6
end
return (self._ended - self._started) / 1e6
end
2022-11-28 18:04:32 +08:00
---@param fn fun()
function Task:schedule(fn)
local done = false
table.insert(self._running, function()
return not done
end)
vim.schedule(function()
---@type boolean, string|any
local ok, err = pcall(fn)
if not ok then
self.error = err or "failed"
end
done = true
self:_check()
end)
2022-11-23 23:12:43 +08:00
end
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
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
2022-11-28 18:04:32 +08:00
self:_check()
2022-11-21 06:04:56 +08:00
end
2022-11-28 18:04:32 +08:00
local proc = Process.spawn(cmd, opts)
table.insert(self._running, function()
return proc and not proc:is_closing()
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
---@param tasks (LazyTask?)[]
function Task.all_done(tasks)
for _, task in ipairs(tasks) do
if task and not task:is_done() then
return false
end
2022-11-23 23:12:43 +08:00
end
2022-11-28 18:04:32 +08:00
return true
2022-11-21 06:04:56 +08:00
end
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