aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/api.txt6
-rw-r--r--runtime/lua/vim/_meta/api.lua6
-rw-r--r--src/nvim/api/win_config.c30
-rw-r--r--test/functional/api/window_spec.lua34
4 files changed, 55 insertions, 21 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index 125976342b..adaf66c2d9 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -3265,9 +3265,9 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
• footer_pos: Footer position. Must be set with `footer`
option. Value can be one of "left", "center", or "right".
Default is `"left"`.
- • noautocmd: If true then no buffer-related autocommand
- events such as |BufEnter|, |BufLeave| or |BufWinEnter| may
- fire from calling this function.
+ • noautocmd: If true then autocommands triggered from
+ setting the `buffer` to display are blocked (e.g:
+ |BufEnter|, |BufLeave|, |BufWinEnter|).
• fixed: If true when anchor is NW or SW, the float window
would be kept fixed even if the window would be truncated.
• hide: If true the floating window will be hidden.
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index 4a179d49f3..f2f5f43c26 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -1719,9 +1719,9 @@ function vim.api.nvim_open_term(buffer, opts) end
--- • footer_pos: Footer position. Must be set with `footer`
--- option. Value can be one of "left", "center", or "right".
--- Default is `"left"`.
---- • noautocmd: If true then no buffer-related autocommand
---- events such as `BufEnter`, `BufLeave` or `BufWinEnter` may
---- fire from calling this function.
+--- • noautocmd: If true then autocommands triggered from
+--- setting the `buffer` to display are blocked (e.g:
+--- `BufEnter`, `BufLeave`, `BufWinEnter`).
--- • fixed: If true when anchor is NW or SW, the float window
--- would be kept fixed even if the window would be truncated.
--- • hide: If true the floating window will be hidden.
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 21d6d59b1e..8608b0dde9 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -199,9 +199,9 @@
/// - footer_pos: Footer position. Must be set with `footer` option.
/// Value can be one of "left", "center", or "right".
/// Default is `"left"`.
-/// - noautocmd: If true then no buffer-related autocommand events such as
-/// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from
-/// calling this function.
+/// - noautocmd: If true then autocommands triggered from setting the
+/// `buffer` to display are blocked (e.g: |BufEnter|, |BufLeave|,
+/// |BufWinEnter|).
/// - fixed: If true when anchor is NW or SW, the float window
/// would be kept fixed even if the window would be truncated.
/// - hide: If true the floating window will be hidden.
@@ -302,20 +302,20 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
tp = win_find_tabpage(wp);
}
if (tp && bufref_valid(&bufref) && buf != wp->w_buffer) {
- const bool noautocmd = curwin != wp || fconfig.noautocmd;
- win_set_buf(wp, buf, noautocmd, err);
- if (!noautocmd) {
+ // win_set_buf temporarily makes `wp` the curwin to set the buffer.
+ // If not entering `wp`, block Enter and Leave events. (cringe)
+ const bool au_no_enter_leave = curwin != wp && !fconfig.noautocmd;
+ if (au_no_enter_leave) {
+ autocmd_no_enter++;
+ autocmd_no_leave++;
+ }
+ win_set_buf(wp, buf, fconfig.noautocmd, err);
+ if (!fconfig.noautocmd) {
tp = win_find_tabpage(wp);
}
- // win_set_buf autocommands were blocked if we didn't enter, but we still want BufWinEnter.
- if (noautocmd && !fconfig.noautocmd && wp->w_buffer == buf) {
- const int result = switch_win_noblock(&switchwin, wp, tp, true);
- assert(result == OK);
- (void)result;
- if (apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, false, buf)) {
- tp = win_find_tabpage(wp);
- }
- restore_win_noblock(&switchwin, true);
+ if (au_no_enter_leave) {
+ autocmd_no_enter--;
+ autocmd_no_leave--;
}
}
if (!tp) {
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 246ff50ddc..6e20c81fc2 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -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()