diff options
-rw-r--r-- | src/nvim/fileio.c | 11 | ||||
-rw-r--r-- | src/nvim/window.c | 4 | ||||
-rw-r--r-- | test/functional/autocmd/autocmd_spec.lua | 116 |
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) |