mirror of
https://github.com/neovim/neovim.git
synced 2026-07-18 23:21:35 +00:00
fix(lua): vim.wait(0) does not call loop_poll #39679
Problem:
Regression from c822a2657c: `vim.wait(0)` does not call `loop_poll`,
so `vim.wait(1)` is needed to "yield" from Lua.
Solution:
- Ensure that `vim._core.loop_poll()` is always called, even when `time=0`.
- Document how to interrupt Lua code (ctrl-c).
ref https://github.com/neovim/neovim/issues/6800
This commit is contained in:
@@ -69,6 +69,15 @@ vim._extra = {
|
||||
--- if vim.wait(10000, function() return vim.g.timer_result end) then
|
||||
--- print('Only waiting a little bit of time!')
|
||||
--- end
|
||||
---
|
||||
--- -- Yield via vim.wait() to allow CTRL-C to interrupt Lua code.
|
||||
--- while true do
|
||||
--- -- ...work...
|
||||
--- local _, code = vim.wait(0, nil, 0)
|
||||
--- if code == -2 then -- CTRL-C.
|
||||
--- break
|
||||
--- end
|
||||
--- end
|
||||
--- ```
|
||||
---
|
||||
--- @param time number Number of milliseconds to wait. Must be non-negative number, any fractional
|
||||
@@ -156,19 +165,26 @@ function vim.wait(time, callback, interval, fast_only)
|
||||
local poll_timeout = -1
|
||||
if has_deadline then
|
||||
local remaining_ms = time - (vim.uv.hrtime() - start) / 1e6
|
||||
if remaining_ms <= 0 then
|
||||
cleanup()
|
||||
return false, -1
|
||||
end
|
||||
|
||||
-- loop_poll() takes an integer timeout, so cap each individual poll
|
||||
-- while still honoring larger overall waits.
|
||||
poll_timeout = math.min(math.ceil(remaining_ms), vim._maxint)
|
||||
-- loop_poll() takes an integer timeout, so cap each individual poll while still honoring
|
||||
-- larger overall waits. Always poll at least once, so vim.wait(0) still pumps the event loop
|
||||
-- (lets user code "yield" to CTRL-C).
|
||||
poll_timeout = math.max(0, math.min(math.ceil(remaining_ms), vim._maxint))
|
||||
end
|
||||
|
||||
-- The dummy timer wakes `vim._core.loop_poll()` on interval boundaries. Without it,
|
||||
-- polling would only resume for unrelated events or the final timeout.
|
||||
vim._core.loop_poll(poll_timeout, fast_only)
|
||||
|
||||
-- Check deadline AFTER polling (mirrors LOOP_PROCESS_EVENTS_UNTIL behavior).
|
||||
-- `got_int` may have been set during poll; let check_interrupt() catch it.
|
||||
if has_deadline and time - (vim.uv.hrtime() - start) / 1e6 <= 0 then
|
||||
if vim._core.check_interrupt() then
|
||||
cleanup()
|
||||
return false, -2
|
||||
end
|
||||
cleanup()
|
||||
return false, -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user