aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/fileio.c11
-rw-r--r--src/nvim/window.c4
-rw-r--r--test/functional/autocmd/autocmd_spec.lua116
3 files changed, 129 insertions, 2 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 717ae6e602..507bf3c032 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -11,6 +11,7 @@
#include <fcntl.h>
#include "nvim/vim.h"
+#include "nvim/api/private/handle.h"
#include "nvim/ascii.h"
#include "nvim/fileio.h"
#include "nvim/buffer.h"
@@ -47,6 +48,7 @@
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
#include "nvim/types.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -6586,6 +6588,8 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
block_autocmds(); // We don't want BufEnter/WinEnter autocommands.
if (need_append) {
win_append(lastwin, aucmd_win);
+ handle_register_window(aucmd_win);
+ win_config_float(aucmd_win, aucmd_win->w_float_config);
}
// Prevent chdir() call in win_enter_ext(), through do_autochdir()
int save_acd = p_acd;
@@ -6625,6 +6629,13 @@ void aucmd_restbuf(aco_save_T *aco)
win_found:
win_remove(curwin, NULL);
+ handle_unregister_window(curwin);
+ if (curwin->w_grid.chars != NULL) {
+ ui_comp_remove_grid(&curwin->w_grid);
+ ui_call_win_hide(curwin->w_grid.handle);
+ grid_free(&curwin->w_grid);
+ }
+
aucmd_win_used = false;
last_status(false); // may need to remove last status line
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 200c651d1e..6bc082ffb2 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -3418,8 +3418,8 @@ void win_alloc_aucmd_win(void)
{
Error err = ERROR_INIT;
FloatConfig fconfig = FLOAT_CONFIG_INIT;
- fconfig.width = 20;
- fconfig.height = 20;
+ fconfig.width = Columns;
+ fconfig.height = 5;
fconfig.focusable = false;
aucmd_win = win_new_float(NULL, fconfig, &err);
aucmd_win->w_buffer->b_nwindows--;
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index 814624d8e2..337c5442ef 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local dedent = helpers.dedent
local eq = helpers.eq
@@ -6,11 +7,13 @@ local eval = helpers.eval
local feed = helpers.feed
local clear = helpers.clear
local meths = helpers.meths
+local meth_pcall = helpers.meth_pcall
local funcs = helpers.funcs
local expect = helpers.expect
local command = helpers.command
local exc_exec = helpers.exc_exec
local curbufmeths = helpers.curbufmeths
+local source = helpers.source
describe('autocmd', function()
before_each(clear)
@@ -144,4 +147,117 @@ describe('autocmd', function()
--- Autocommands ---]]),
funcs.execute('autocmd Tabnew'))
end)
+
+ it('window works', function()
+ -- Nvim uses a special window to execute certain actions for an invisible buffer,
+ -- internally called autcmd_win and mentioned in the docs at :help E813
+ -- Do some safety checks for redrawing and api accesses to this window.
+
+ local screen = Screen.new(50, 10)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [2] = {background = Screen.colors.LightMagenta},
+ [3] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1},
+ })
+
+ source([[
+ function! Doit()
+ let g:winid = nvim_get_current_win()
+ redraw!
+ echo getchar()
+ " API functions work when aucmd_win is in scope
+ let g:had_value = has_key(w:, "testvar")
+ call nvim_win_set_var(g:winid, "testvar", 7)
+ let g:test = w:testvar
+ endfunction
+ set hidden
+ " add dummy text to not discard the buffer
+ call setline(1,"bb")
+ autocmd User <buffer> call Doit()
+ ]])
+ screen:expect([[
+ ^bb |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]])
+
+ feed(":enew | doautoall User<cr>")
+ screen:expect([[
+ {2:bb }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^:enew | doautoall User |
+ ]])
+
+ feed('<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ 13 |
+ ]])
+ eq(7, eval('g:test'))
+
+ -- API calls are blocked when aucmd_win is not in scope
+ eq({false, 'Vim(call):Invalid window id'},
+ meth_pcall(command, "call nvim_set_current_win(g:winid)"))
+
+ -- second time aucmd_win is needed, a different code path is invoked
+ -- to reuse the same window, so check again
+ command("let g:test = v:null")
+ command("let g:had_value = v:null")
+ feed(":doautoall User<cr>")
+ screen:expect([[
+ {2:bb }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ ^:doautoall User |
+ ]])
+
+ feed('<cr>')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ 13 |
+ ]])
+ -- win vars in aucmd_win should have been reset
+ eq(0, eval('g:had_value'))
+ eq(7, eval('g:test'))
+
+ eq({false, 'Vim(call):Invalid window id'},
+ meth_pcall(command, "call nvim_set_current_win(g:winid)"))
+ end)
end)