mirror of
https://github.com/neovim/neovim.git
synced 2025-12-15 19:05:40 +00:00
fix(api): make open_win block only enter/leave events if !enter && !noautocmd
Problem: nvim_open_win blocking all win_set_buf autocommands when !enter && !noautocmd is too aggressive. Solution: temporarily block WinEnter/Leave and BufEnter/Leave events when setting the buffer. Delegate the firing of BufWinEnter back to win_set_buf, which also has the advantage of keeping the timing consistent (e.g: before the epilogue in enter_buffer, which also handles restoring the cursor position if autocommands didn't change it, among other things). Reword the documentation for noautocmd a bit. I pondered modifying do_buffer and callees to allow for BufEnter/Leave being conditionally disabled, but it seems too invasive (and potentially error-prone, especially if new code paths to BufEnter/Leave are added in the future). Unfortunately, doing this has the drawback of blocking ALL such events for the duration, which also means blocking unrelated such events; like if window switching occurs in a ++nested autocmd fired by win_set_buf. If this turns out to be a problem in practice, a different solution specialized for nvim_open_win could be considered. :-)
This commit is contained in:
@@ -1620,6 +1620,40 @@ describe('API/win', function()
|
||||
)
|
||||
command('new | quit')
|
||||
end)
|
||||
|
||||
it('restores last known cursor position if BufWinEnter did not move it', function()
|
||||
-- This test mostly exists to ensure BufWinEnter is executed before enter_buffer's epilogue.
|
||||
local buf = api.nvim_get_current_buf()
|
||||
insert([[
|
||||
foo
|
||||
bar baz .etc
|
||||
i love autocommand bugs!
|
||||
supercalifragilisticexpialidocious
|
||||
marvim is actually a human
|
||||
llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
|
||||
]])
|
||||
api.nvim_win_set_cursor(0, { 5, 2 })
|
||||
command('set nostartofline | enew')
|
||||
local new_win = api.nvim_open_win(buf, false, { split = 'left' })
|
||||
eq({ 5, 2 }, api.nvim_win_get_cursor(new_win))
|
||||
|
||||
exec([[
|
||||
only!
|
||||
autocmd BufWinEnter * ++once normal! j6l
|
||||
]])
|
||||
new_win = api.nvim_open_win(buf, false, { split = 'left' })
|
||||
eq({ 2, 6 }, api.nvim_win_get_cursor(new_win))
|
||||
end)
|
||||
|
||||
it('does not block all win_set_buf autocommands if !enter and !noautocmd', function()
|
||||
local new_buf = fn.bufadd('foobarbaz')
|
||||
exec([[
|
||||
let triggered = ""
|
||||
autocmd BufReadCmd * ++once let triggered = bufname()
|
||||
]])
|
||||
api.nvim_open_win(new_buf, false, { split = 'left' })
|
||||
eq('foobarbaz', eval('triggered'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('set_config', function()
|
||||
|
||||
Reference in New Issue
Block a user