Skip to content

Commit 368747b

Browse files
committed
feat(build): build files and functions are now async. use coroutine.yield to interrupt and report progress
1 parent fcfd548 commit 368747b

File tree

4 files changed

+102
-38
lines changed

4 files changed

+102
-38
lines changed

lua/lazy/core/config.lua

-6
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,6 @@ M.defaults = {
183183
skip_if_doc_exists = true,
184184
},
185185
state = vim.fn.stdpath("state") .. "/lazy/state.json", -- state info for checker and other things
186-
build = {
187-
-- Plugins can provide a `build.lua` file that will be executed when the plugin is installed
188-
-- or updated. When the plugin spec also has a `build` command, the plugin's `build.lua` not be
189-
-- executed. In this case, a warning message will be shown.
190-
warn_on_override = true,
191-
},
192186
-- Enable profiling of lazy.nvim. This will add some overhead,
193187
-- so only enable this when you are debugging lazy.nvim
194188
profiling = {

lua/lazy/manage/task/init.lua

+26
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,32 @@ function Task:start()
7474
self:_check()
7575
end
7676

77+
---@param fn async fun()
78+
function Task:async(fn)
79+
local co = coroutine.create(fn)
80+
local check = vim.uv.new_check()
81+
check:start(vim.schedule_wrap(function()
82+
local status = coroutine.status(co)
83+
if status == "dead" then
84+
check:stop()
85+
self:_check()
86+
elseif status == "suspended" then
87+
local ok, res = coroutine.resume(co)
88+
if not ok then
89+
error(res)
90+
elseif res then
91+
self.status = res
92+
self.output = self.output .. "\n" .. res
93+
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
94+
end
95+
end
96+
end))
97+
98+
table.insert(self._running, function()
99+
return check:is_active()
100+
end)
101+
end
102+
77103
---@private
78104
function Task:_check()
79105
for _, state in ipairs(self._running) do

lua/lazy/manage/task/plugin.lua

+64-32
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,67 @@ local M = {}
88
---@param plugin LazyPlugin
99
local function get_build_file(plugin)
1010
for _, path in ipairs({ "build.lua", "build/init.lua" }) do
11-
path = plugin.dir .. "/" .. path
12-
if Util.file_exists(path) then
11+
if Util.file_exists(plugin.dir .. "/" .. path) then
1312
return path
1413
end
1514
end
1615
end
1716

17+
local B = {}
18+
19+
---@param task LazyTask
20+
function B.rockspec(task)
21+
local root = Config.options.rocks.root .. "/" .. task.plugin.name
22+
vim.fn.mkdir(root, "p")
23+
task:spawn("luarocks", {
24+
args = {
25+
"--tree",
26+
root,
27+
"--server",
28+
Config.options.rocks.server,
29+
"--dev",
30+
"--lua-version",
31+
"5.1",
32+
"make",
33+
"--force-fast",
34+
},
35+
cwd = task.plugin.dir,
36+
})
37+
end
38+
39+
---@param task LazyTask
40+
---@param build string
41+
function B.cmd(task, build)
42+
local cmd = vim.api.nvim_parse_cmd(build:sub(2), {}) --[[@as vim.api.keyset.cmd]]
43+
task.output = vim.api.nvim_cmd(cmd, { output = true })
44+
end
45+
46+
---@param task LazyTask
47+
---@param build string
48+
function B.shell(task, build)
49+
local shell = vim.env.SHELL or vim.o.shell
50+
local shell_args = shell:find("cmd.exe", 1, true) and "/c" or "-c"
51+
52+
task:spawn(shell, {
53+
args = { shell_args, build },
54+
cwd = task.plugin.dir,
55+
})
56+
end
57+
1858
M.build = {
1959
---@param opts? {force:boolean}
2060
skip = function(plugin, opts)
2161
if opts and opts.force then
2262
return false
2363
end
24-
return not (plugin._.dirty and (plugin.build or get_build_file(plugin)))
64+
return not ((plugin._.dirty or plugin._.build) and (plugin.build or get_build_file(plugin)))
2565
end,
2666
run = function(self)
2767
vim.cmd([[silent! runtime plugin/rplugin.vim]])
2868

29-
Loader.load(self.plugin, { task = "build" })
69+
if self.plugin.build ~= "rockspec" then
70+
Loader.load(self.plugin, { task = "build" })
71+
end
3072

3173
local builders = self.plugin.build
3274

@@ -35,39 +77,29 @@ M.build = {
3577
return
3678
end
3779

38-
local build_file = get_build_file(self.plugin)
39-
if build_file then
40-
if builders then
41-
if Config.options.build.warn_on_override then
42-
Util.warn(
43-
("Plugin **%s** provides its own build script, but you also defined a `build` command.\nThe `build.lua` file will not be used"):format(
44-
self.plugin.name
45-
)
46-
)
47-
end
48-
else
49-
builders = function()
50-
Loader.source(build_file)
51-
end
52-
end
53-
end
80+
builders = builders or get_build_file(self.plugin)
81+
5482
if builders then
5583
builders = type(builders) == "table" and builders or { builders }
5684
---@cast builders (string|fun(LazyPlugin))[]
5785
for _, build in ipairs(builders) do
58-
if type(build) == "string" and build:sub(1, 1) == ":" then
59-
local cmd = vim.api.nvim_parse_cmd(build:sub(2), {})
60-
self.output = vim.api.nvim_cmd(cmd, { output = true })
61-
elseif type(build) == "function" then
62-
build(self.plugin)
86+
if type(build) == "function" then
87+
self:async(function()
88+
build(self.plugin)
89+
end)
90+
elseif build == "rockspec" then
91+
B.rockspec(self)
92+
elseif build:sub(1, 1) == ":" then
93+
B.cmd(self, build)
94+
elseif build:match("%.lua$") then
95+
local file = self.plugin.dir .. "/" .. build
96+
local chunk, err = loadfile(file)
97+
if not chunk or err then
98+
error(err)
99+
end
100+
self:async(chunk)
63101
else
64-
local shell = vim.env.SHELL or vim.o.shell
65-
local shell_args = shell:find("cmd.exe", 1, true) and "/c" or "-c"
66-
67-
self:spawn(shell, {
68-
args = { shell_args, build },
69-
cwd = self.plugin.dir,
70-
})
102+
B.shell(self, build)
71103
end
72104
end
73105
end

lua/lazy/util.lua

+12
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,18 @@ function M.markdown(msg, opts)
231231
)
232232
end
233233

234+
---@async
235+
---@param ms number
236+
function M.sleep(ms)
237+
local continue = false
238+
vim.defer_fn(function()
239+
continue = true
240+
end, ms)
241+
while not continue do
242+
coroutine.yield()
243+
end
244+
end
245+
234246
function M._dump(value, result)
235247
local t = type(value)
236248
if t == "number" or t == "boolean" then

0 commit comments

Comments
 (0)