From 757aad92e84709a08320a06870b6acb086bc6876 Mon Sep 17 00:00:00 2001 From: Marcos ALMEIDA Date: Sat, 29 Sep 2018 20:40:53 +0200 Subject: autocmd: add WinClosed event - only fire once, just before freeing mem - trigger when on a different buffer - avoid recursive calls in another tab --- runtime/doc/autocmd.txt | 4 +- runtime/doc/vim_diff.txt | 1 + src/nvim/auevents.lua | 2 + src/nvim/window.c | 37 ++++++++++++++++-- test/functional/autocmd/autocmd_spec.lua | 66 ++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 5 deletions(-) diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 774e6a5d92..d15f5e7900 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -317,6 +317,7 @@ Name triggered by ~ |CursorMoved| the cursor was moved in Normal mode |CursorMovedI| the cursor was moved in Insert mode +|WinClosed| after closing a window |WinNew| after creating a new window |WinEnter| after entering another window |WinLeave| before leaving a window @@ -1131,6 +1132,8 @@ VimResized After the Vim window was resized, thus 'lines' VimResume After Nvim resumes from |suspend| state. *VimSuspend* VimSuspend Before Nvim enters |suspend| state. + *WinClosed* +WinClosed After closing a window. *WinEnter* WinEnter After entering another window. Not done for the first window, when Vim has just started. @@ -1148,7 +1151,6 @@ WinLeave Before leaving a window. If the window to be executes the BufLeave autocommands before the WinLeave autocommands (but not for ":new"). Not used for ":qa" or ":q" when exiting Vim. - *WinNew* WinNew When a new window was created. Not done for the first window, when Vim has just started. diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 2bb798a6e6..5835c7f314 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -159,6 +159,7 @@ Events: |UILeave| |VimResume| |VimSuspend| + |WinClosed| Functions: |dictwatcheradd()| notifies a callback whenever a |Dict| is modified diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index a52789c795..d596edf551 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -110,6 +110,7 @@ return { 'WinEnter', -- after entering a window 'WinLeave', -- before leaving a window 'WinNew', -- when entering a new window + 'WinClosed', -- after closing a window }, aliases = { BufCreate = 'BufAdd', @@ -129,5 +130,6 @@ return { TermOpen=true, UIEnter=true, UILeave=true, + WinClosed=true, }, } diff --git a/src/nvim/window.c b/src/nvim/window.c index e913d33de0..4743dca3ff 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2502,9 +2502,10 @@ int win_close(win_T *win, bool free_buf) return FAIL; } win->w_closing = true; - apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf); - if (!win_valid(win)) + apply_autocmds(EVENT_WINLEAVE, NULL, NULL, false, curbuf); + if (!win_valid(win)) { return FAIL; + } win->w_closing = false; if (last_window()) return FAIL; @@ -2534,6 +2535,12 @@ int win_close(win_T *win, bool free_buf) } } + // Fire WinClosed just before starting to free window-related resources. + do_autocmd_winclosed(win); + // autocmd may have freed the window already. + if (!win_valid_any_tab(win)) { + return OK; + } /* Free independent synblock before the buffer is freed. */ if (win->w_buffer != NULL) @@ -2576,6 +2583,7 @@ int win_close(win_T *win, bool free_buf) win_close_othertab(win, false, prev_curtab); return FAIL; } + // Autocommands may have closed the window already, or closed the only // other window or moved to another tab page. if (!win_valid(win) || (!win->w_floating && last_window()) @@ -2585,8 +2593,9 @@ int win_close(win_T *win, bool free_buf) // let terminal buffers know that this window dimensions may be ignored win->w_closing = true; - /* Free the memory used for the window and get the window that received - * the screen space. */ + + // Free the memory used for the window and get the window that received + // the screen space. wp = win_free_mem(win, &dir, NULL); if (help_window) { @@ -2678,6 +2687,19 @@ int win_close(win_T *win, bool free_buf) return OK; } +static void do_autocmd_winclosed(win_T *win) + FUNC_ATTR_NONNULL_ALL +{ + static bool recursive = false; + if (recursive || !has_event(EVENT_WINCLOSED)) { + return; + } + recursive = true; + apply_autocmds(EVENT_WINCLOSED, win->w_buffer->b_fname, + win->w_buffer->b_fname, false, win->w_buffer); + recursive = false; +} + /* * Close window "win" in tab page "tp", which is not the current tab page. * This may be the last window in that tab page and result in closing the tab, @@ -2698,6 +2720,13 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) return; // window is already being closed } + // Fire WinClosed just before starting to free window-related resources. + do_autocmd_winclosed(win); + // autocmd may have freed the window already. + if (!win_valid_any_tab(win)) { + return; + } + if (win->w_buffer != NULL) { // Close the link to the buffer. close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, false); diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 43534c9e7e..31c6edb940 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local dedent = helpers.dedent +local neq = helpers.neq local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed @@ -40,6 +41,71 @@ describe('autocmd', function() assert.same(expected, eval('g:foo')) end) + it(':close triggers WinClosed event', function() + command('let g:triggered = 0') + command('new') + command('autocmd WinClosed :let g:triggered+=1') + eq(0, eval('g:triggered')) + command('close') + eq(1, eval('g:triggered')) + end) + + it(':bdelete triggers WinClosed event', function() + command('let g:triggered = 0') + command('autocmd WinClosed :let g:triggered+=1') + local first_buffer = eval("bufnr('%')") + command('new') + command('bdelete ' .. first_buffer ) + eq(1, eval('g:triggered')) + end) + + it(':close triggers WinClosed event in another tab', function() + command('let g:triggered = 0') + local current_buffer = eval("bufnr('%')") + command('autocmd WinClosed :let g:triggered+=1') + command('tabnew') + command('bdelete ' .. current_buffer) + eq(1, eval('g:triggered')) + end) + + it('WinClosed events are not recursive in different window', function() + command('let g:triggered = 0') + local first_buffer = eval("bufnr('%')") + command('autocmd WinClosed :let g:triggered+=1') + command('new') + local second_buffer = eval("bufnr('%')") + command('autocmd WinClosed :bdelete ' .. first_buffer) + command('new') + neq(-1, funcs.bufwinnr(first_buffer)) + command('bdelete ' .. second_buffer ) + eq(0, eval('g:triggered')) + + -- first event was triggered, second wasn't + eq(-1, funcs.bufwinnr(first_buffer)) + end) + + it('WinClosed events are not recursive in the same window', function() + command('let g:triggered = 0') + command('new') + local second_buffer = eval("bufnr('%')") + command('autocmd WinClosed :let g:triggered+=1 | bdelete ' .. second_buffer) + neq(-1, funcs.bufwinnr(second_buffer)) + eq(0, eval('g:triggered')) + command('bdelete ' .. second_buffer ) + eq(-1, funcs.bufwinnr(second_buffer)) + eq(1, eval('g:triggered')) + end) + + it('WinClosed events are not recursive in different tab', function() + command('let g:triggered = 0') + command('new') + local second_buffer = eval("bufnr('%')") + command('autocmd WinClosed :let g:triggered+=1 | bdelete ' .. second_buffer) + command('tabnew') + command('bdelete ' .. second_buffer ) + eq(1, eval('g:triggered')) + end) + it('v:vim_did_enter is 1 after VimEnter', function() eq(1, eval('v:vim_did_enter')) end) -- cgit From 2b8e66c6ce0a5ccae09023732c06da90f96ed5f5 Mon Sep 17 00:00:00 2001 From: notomo Date: Tue, 14 Jan 2020 22:34:05 +0900 Subject: autocmd: WinClosed exposes window id as --- src/nvim/fileio.c | 3 ++- src/nvim/window.c | 6 ++++-- test/functional/autocmd/autocmd_spec.lua | 7 +++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 865da25009..7a46957151 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -6862,7 +6862,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, || event == EVENT_SPELLFILEMISSING || event == EVENT_SYNTAX || event == EVENT_SIGNAL - || event == EVENT_TABCLOSED) { + || event == EVENT_TABCLOSED + || event == EVENT_WINCLOSED) { fname = vim_strsave(fname); } else { fname = (char_u *)FullName_save((char *)fname, false); diff --git a/src/nvim/window.c b/src/nvim/window.c index 4743dca3ff..9efed49e70 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2695,8 +2695,10 @@ static void do_autocmd_winclosed(win_T *win) return; } recursive = true; - apply_autocmds(EVENT_WINCLOSED, win->w_buffer->b_fname, - win->w_buffer->b_fname, false, win->w_buffer); + + char_u winid[10]; + vim_snprintf((char *)winid, sizeof(winid), "%i", win->handle); + apply_autocmds(EVENT_WINCLOSED, winid, winid, false, win->w_buffer); recursive = false; } diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 31c6edb940..6cb12750a1 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -50,6 +50,13 @@ describe('autocmd', function() eq(1, eval('g:triggered')) end) + it('WinClosed event exposes window id as ', function() + command('new') + local id = meths.get_current_win().id + helpers.nvim('command', 'au! WinClosed * echom "winclosed:".expand("").":".expand("").":".win_getid()') + eq(string.format("winclosed:%s:%s:%s", id, id, id), helpers.nvim('exec', 'close', true)) + end) + it(':bdelete triggers WinClosed event', function() command('let g:triggered = 0') command('autocmd WinClosed :let g:triggered+=1') -- cgit From 156c25e4983d4c106ba70e5e3bcc6bbb012d8065 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 13 Jan 2020 00:19:20 -0800 Subject: WinClosed: sort auevents.lua; improve tests - test: reduce verbosity, condense redundancy, improve readability - auevents.lua: keep events sorted by name. ref afd1d412fa91 --- runtime/doc/autocmd.txt | 26 +++--- src/nvim/auevents.lua | 10 +-- src/nvim/window.c | 3 +- test/functional/autocmd/autocmd_spec.lua | 148 ++++++++++++++----------------- test/functional/helpers.lua | 13 +++ 5 files changed, 102 insertions(+), 98 deletions(-) diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index d15f5e7900..608f8bbf3d 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -576,8 +576,7 @@ ColorSchemePre Before loading a color scheme. |:colorscheme| CompleteChanged *CompleteChanged* After each time the Insert mode completion menu changed. Not fired on popup menu hide, - use |CompleteDone| for that. Never triggered - recursively. + use |CompleteDone| for that. Sets these |v:event| keys: completed_item See |complete-items|. @@ -588,7 +587,8 @@ CompleteChanged *CompleteChanged* size total nr of items scrollbar TRUE if visible - It is not allowed to change the text |textlock|. + Non-recursive (event cannot trigger itself). + Cannot change the text. |textlock| The size and position of the popup are also available by calling |pum_getpos()|. @@ -661,7 +661,7 @@ DirChanged After the |current-directory| was changed. Sets these |v:event| keys: cwd: current working directory scope: "global", "tab", "window" - Recursion is ignored. + Non-recursive (event cannot trigger itself). *FileAppendCmd* FileAppendCmd Before appending to a file. Should do the appending to the file. Use the '[ and '] @@ -697,6 +697,7 @@ ExitPre When using `:quit`, `:wq` in a way it makes cancelled if there is a modified buffer that isn't automatically saved, use |VimLeavePre| for really exiting. + See also |QuitPre|, |WinClosed|. *FileChangedShell* FileChangedShell When Vim notices that the modification time of a file has changed since editing started. @@ -841,7 +842,7 @@ TextYankPost Just after a |yank| or |deleting| command, but not and |']| marks can be used to calculate the precise region of the operation. - Recursion is ignored. + Non-recursive (event cannot trigger itself). Cannot change the text. |textlock| *InsertEnter* InsertEnter Just before starting Insert mode. Also for @@ -908,8 +909,8 @@ OptionSet After setting an option (except during always use |:noautocmd| to prevent triggering OptionSet. - Recursion is ignored, thus |:set| in the - autocommand does not trigger OptionSet again. + Non-recursive: |:set| in the autocommand does + not trigger OptionSet again. *QuickFixCmdPre* QuickFixCmdPre Before a quickfix command is run (|:make|, @@ -941,7 +942,7 @@ QuitPre When using `:quit`, `:wq` or `:qall`, before or quits Vim. Can be used to close any non-essential window if the current window is the last ordinary window. - Also see |ExitPre|. + See also |ExitPre|, ||WinClosed|. *RemoteReply* RemoteReply When a reply from a Vim that functions as server was received |server2client()|. The @@ -1042,8 +1043,8 @@ TabNew When creating a new tab page. |tab-page| TabNewEntered After entering a new tab page. |tab-page| After BufEnter. *TabClosed* -TabClosed After closing a tab page. can be used - for the tab page number. +TabClosed After closing a tab page. expands to + the tab page number. *TermOpen* TermOpen When a |terminal| job is starting. Can be used to configure the terminal buffer. @@ -1133,7 +1134,10 @@ VimResume After Nvim resumes from |suspend| state. *VimSuspend* VimSuspend Before Nvim enters |suspend| state. *WinClosed* -WinClosed After closing a window. +WinClosed After closing a window. expands to the + |window-ID|. + Non-recursive (event cannot trigger itself). + See also |ExitPre|, |QuitPre|. *WinEnter* WinEnter After entering another window. Not done for the first window, when Vim has just started. diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index d596edf551..96e170a9e1 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -21,12 +21,12 @@ return { 'BufWritePre', -- before writing a buffer 'ChanInfo', -- info was received about channel 'ChanOpen', -- channel was opened - 'CmdlineChanged', -- command line was modified - 'CmdlineEnter', -- after entering cmdline mode - 'CmdlineLeave', -- before leaving cmdline mode 'CmdUndefined', -- command undefined 'CmdWinEnter', -- after entering the cmdline window 'CmdWinLeave', -- before leaving the cmdline window + 'CmdlineChanged', -- command line was modified + 'CmdlineEnter', -- after entering cmdline mode + 'CmdlineLeave', -- before leaving cmdline mode 'ColorScheme', -- after loading a colorscheme 'ColorSchemePre', -- before loading a colorscheme 'CompleteChanged', -- after popup menu changed @@ -76,8 +76,8 @@ return { 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd". 'Signal', -- after nvim process received a signal 'SourceCmd', -- sourcing a Vim script using command - 'SourcePre', -- before sourcing a Vim script 'SourcePost', -- after sourcing a Vim script + 'SourcePre', -- before sourcing a Vim script 'SpellFileMissing', -- spell file missing 'StdinReadPost', -- after reading from stdin 'StdinReadPre', -- before reading from stdin @@ -107,10 +107,10 @@ return { 'VimResized', -- after Vim window was resized 'VimResume', -- after Nvim is resumed 'VimSuspend', -- before Nvim is suspended + 'WinClosed', -- after closing a window 'WinEnter', -- after entering a window 'WinLeave', -- before leaving a window 'WinNew', -- when entering a new window - 'WinClosed', -- after closing a window }, aliases = { BufCreate = 'BufAdd', diff --git a/src/nvim/window.c b/src/nvim/window.c index 9efed49e70..8181883426 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2695,8 +2695,7 @@ static void do_autocmd_winclosed(win_T *win) return; } recursive = true; - - char_u winid[10]; + char_u winid[NUMBUFLEN]; vim_snprintf((char *)winid, sizeof(winid), "%i", win->handle); apply_autocmds(EVENT_WINCLOSED, winid, winid, false, win->w_buffer); recursive = false; diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 6cb12750a1..e62d3bb66b 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -1,8 +1,8 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') +local assert_visible = helpers.assert_visible local dedent = helpers.dedent -local neq = helpers.neq local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed @@ -19,98 +19,86 @@ local source = helpers.source describe('autocmd', function() before_each(clear) - it(':tabnew triggers events in the correct order', function() + it(':tabnew, :split, :close events order, ', function() local expected = { - 'WinLeave', - 'TabLeave', - 'WinEnter', - 'TabNew', - 'TabEnter', - 'BufLeave', - 'BufEnter' + {'WinLeave', ''}, + {'TabLeave', ''}, + {'WinEnter', ''}, + {'TabNew', 'testfile1'}, -- :tabnew + {'TabEnter', ''}, + {'BufLeave', ''}, + {'BufEnter', 'testfile1'}, -- :split + {'WinLeave', 'testfile1'}, + {'WinEnter', 'testfile1'}, + {'WinLeave', 'testfile1'}, + {'WinClosed', '1002'}, -- :close, WinClosed = window-id + {'WinEnter', 'testfile1'}, + {'WinLeave', 'testfile1'}, -- :bdelete + {'WinEnter', 'testfile1'}, + {'BufLeave', 'testfile1'}, + {'BufEnter', 'testfile2'}, + {'WinClosed', '1000'}, } - command('let g:foo = []') - command('autocmd BufEnter * :call add(g:foo, "BufEnter")') - command('autocmd BufLeave * :call add(g:foo, "BufLeave")') - command('autocmd TabEnter * :call add(g:foo, "TabEnter")') - command('autocmd TabLeave * :call add(g:foo, "TabLeave")') - command('autocmd TabNew * :call add(g:foo, "TabNew")') - command('autocmd WinEnter * :call add(g:foo, "WinEnter")') - command('autocmd WinLeave * :call add(g:foo, "WinLeave")') - command('tabnew') - assert.same(expected, eval('g:foo')) - end) - - it(':close triggers WinClosed event', function() - command('let g:triggered = 0') - command('new') - command('autocmd WinClosed :let g:triggered+=1') - eq(0, eval('g:triggered')) + command('let g:evs = []') + command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("")])') + command('autocmd BufLeave * :call add(g:evs, ["BufLeave", expand("")])') + command('autocmd TabEnter * :call add(g:evs, ["TabEnter", expand("")])') + command('autocmd TabLeave * :call add(g:evs, ["TabLeave", expand("")])') + command('autocmd TabNew * :call add(g:evs, ["TabNew", expand("")])') + command('autocmd WinEnter * :call add(g:evs, ["WinEnter", expand("")])') + command('autocmd WinLeave * :call add(g:evs, ["WinLeave", expand("")])') + command('autocmd WinClosed * :call add(g:evs, ["WinClosed", expand("")])') + command('tabnew testfile1') + command('split') command('close') - eq(1, eval('g:triggered')) + command('new testfile2') + command('bdelete 1') + eq(expected, eval('g:evs')) end) - it('WinClosed event exposes window id as ', function() - command('new') - local id = meths.get_current_win().id - helpers.nvim('command', 'au! WinClosed * echom "winclosed:".expand("").":".expand("").":".win_getid()') - eq(string.format("winclosed:%s:%s:%s", id, id, id), helpers.nvim('exec', 'close', true)) - end) - - it(':bdelete triggers WinClosed event', function() + it('WinClosed is non-recursive', function() command('let g:triggered = 0') - command('autocmd WinClosed :let g:triggered+=1') - local first_buffer = eval("bufnr('%')") - command('new') - command('bdelete ' .. first_buffer ) - eq(1, eval('g:triggered')) - end) + command('autocmd WinClosed * :let g:triggered+=1 | :bdelete 2') + command('new testfile2') + command('new testfile3') - it(':close triggers WinClosed event in another tab', function() - command('let g:triggered = 0') - local current_buffer = eval("bufnr('%')") - command('autocmd WinClosed :let g:triggered+=1') - command('tabnew') - command('bdelete ' .. current_buffer) - eq(1, eval('g:triggered')) - end) + -- All 3 buffers are visible. + assert_visible(1, true) + assert_visible(2, true) + assert_visible(3, true) - it('WinClosed events are not recursive in different window', function() - command('let g:triggered = 0') - local first_buffer = eval("bufnr('%')") - command('autocmd WinClosed :let g:triggered+=1') - command('new') - local second_buffer = eval("bufnr('%')") - command('autocmd WinClosed :bdelete ' .. first_buffer) - command('new') - neq(-1, funcs.bufwinnr(first_buffer)) - command('bdelete ' .. second_buffer ) - eq(0, eval('g:triggered')) + -- Trigger WinClosed, which also deletes buffer/window 2. + command('bdelete 1') - -- first event was triggered, second wasn't - eq(-1, funcs.bufwinnr(first_buffer)) - end) - - it('WinClosed events are not recursive in the same window', function() - command('let g:triggered = 0') - command('new') - local second_buffer = eval("bufnr('%')") - command('autocmd WinClosed :let g:triggered+=1 | bdelete ' .. second_buffer) - neq(-1, funcs.bufwinnr(second_buffer)) - eq(0, eval('g:triggered')) - command('bdelete ' .. second_buffer ) - eq(-1, funcs.bufwinnr(second_buffer)) + -- Buffers 1 and 2 were closed but WinClosed was triggered only once. eq(1, eval('g:triggered')) + assert_visible(1, false) + assert_visible(2, false) + assert_visible(3, true) end) - it('WinClosed events are not recursive in different tab', function() - command('let g:triggered = 0') + it('WinClosed from a different tabpage', function() + command('let g:evs = []') + command('edit tesfile1') + command('autocmd WinClosed :call add(g:evs, ["WinClosed", expand("")])') + local buf1 = eval("bufnr('%')") command('new') - local second_buffer = eval("bufnr('%')") - command('autocmd WinClosed :let g:triggered+=1 | bdelete ' .. second_buffer) - command('tabnew') - command('bdelete ' .. second_buffer ) - eq(1, eval('g:triggered')) + local buf2 = eval("bufnr('%')") + command('autocmd WinClosed :call add(g:evs, ["WinClosed", expand("")])' + -- Attempt recursion. + ..' | bdelete '..buf2) + command('tabedit testfile2') + command('tabedit testfile3') + command('bdelete '..buf2) + -- Non-recursive: only triggered once. + eq({ + {'WinClosed', '2'}, + }, eval('g:evs')) + command('bdelete '..buf1) + eq({ + {'WinClosed', '2'}, + {'WinClosed', '1'}, + }, eval('g:evs')) end) it('v:vim_did_enter is 1 after VimEnter', function() diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index e0012c6ced..de61ff9cc8 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -597,6 +597,19 @@ function module.assert_alive() assert(2 == module.eval('1+1'), 'crash? request failed') end +-- Asserts that buffer is loaded and visible in the current tabpage. +function module.assert_visible(bufnr, visible) + assert(type(visible) == 'boolean') + eq(visible, module.bufmeths.is_loaded(bufnr)) + if visible then + assert(-1 ~= module.funcs.bufwinnr(bufnr), + 'expected buffer to be visible in current tabpage: '..tostring(bufnr)) + else + assert(-1 == module.funcs.bufwinnr(bufnr), + 'expected buffer NOT visible in current tabpage: '..tostring(bufnr)) + end +end + local function do_rmdir(path) local mode, errmsg, errcode = lfs.attributes(path, 'mode') if mode == nil then -- cgit From b648b38bb1a447c1e757f61ddd248a686cd32807 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 18 Jan 2020 19:38:48 -0800 Subject: doc: autocmd.txt --- runtime/doc/autocmd.txt | 190 +++++++++++++++++++++++------------------------- 1 file changed, 91 insertions(+), 99 deletions(-) diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 608f8bbf3d..8006a45899 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -397,17 +397,18 @@ BufFilePost After changing the name of the current buffer BufFilePre Before changing the name of the current buffer with the ":file" or ":saveas" command. *BufHidden* -BufHidden Just before a buffer becomes hidden. That is, - when there are no longer windows that show - the buffer, but the buffer is not unloaded or - deleted. Not used for ":qa" or ":q" when - exiting Vim. +BufHidden Before a buffer becomes hidden: when there are + no longer windows that show the buffer, but + the buffer is not unloaded or deleted. + + Not used for ":qa" or ":q" when exiting Vim. NOTE: current buffer "%" may be different from the buffer being unloaded "". *BufLeave* BufLeave Before leaving to another buffer. Also when leaving or closing the current window and the new current window is not for the same buffer. + Not used for ":qa" or ":q" when exiting Vim. *BufNew* BufNew Just after creating a new buffer. Also used @@ -423,16 +424,17 @@ BufNewFile When starting to edit a file that doesn't *BufRead* *BufReadPost* BufRead or BufReadPost When starting to edit a new buffer, after reading the file into the buffer, before - executing the modelines. See |BufWinEnter| - for when you need to do something after - processing the modelines. - This does NOT work for ":r file". Not used - when the file doesn't exist. Also used after - successfully recovering a file. - Also triggered for the filetypedetect group - when executing ":filetype detect" and when - writing an unnamed buffer in a way that the - buffer gets a name. + processing modelines. See |BufWinEnter| to do + something after processing modelines. + Also triggered: + - when writing an unnamed buffer such that the + buffer gets a name + - after successfully recovering a file + - for the "filetypedetect" group when + executing ":filetype detect" + Not triggered: + - for ":r file" + - if the file doesn't exist *BufReadCmd* BufReadCmd Before starting to edit a new buffer. Should read the file into the buffer. |Cmd-event| @@ -441,34 +443,33 @@ BufReadPre When starting to edit a new buffer, before reading the file into the buffer. Not used if the file doesn't exist. *BufUnload* -BufUnload Before unloading a buffer. This is when the - text in the buffer is going to be freed. This - may be after a BufWritePost and before a - BufDelete. Also used for all buffers that are - loaded when Vim is going to exit. +BufUnload Before unloading a buffer, when the text in + the buffer is going to be freed. + After BufWritePost. + Before BufDelete. + Triggers for all loaded buffers when Vim is + going to exit. NOTE: Current buffer "%" may be different from the buffer being unloaded "". - Do not change to another buffer or window! + Do not switch buffers or windows! Not triggered when exiting and v:dying is 2 or more. *BufWinEnter* BufWinEnter After a buffer is displayed in a window. This - can be when the buffer is loaded (after - processing the modelines) or when a hidden - buffer is displayed in a window (and is no - longer hidden). - Does not happen for |:split| without - arguments, since you keep editing the same - buffer, or ":split" with a file that's already - open in a window, because it re-uses an - existing buffer. But it does happen for a - ":split" with the name of the current buffer, - since it reloads that buffer. + may be when the buffer is loaded (after + processing modelines) or when a hidden buffer + is displayed (and is no longer hidden). + + Not triggered for |:split| without arguments, + since the buffer does not change, or :split + with a file already open in a window. + Triggered for ":split" with the name of the + current buffer, since it reloads that buffer. *BufWinLeave* BufWinLeave Before a buffer is removed from a window. Not when it's still visible in another window. - Also triggered when exiting. It's triggered - before BufUnload or BufHidden. + Also triggered when exiting. + Before BufUnload, BufHidden. NOTE: Current buffer "%" may be different from the buffer being unloaded "". Not triggered when exiting and v:dying is 2 or @@ -516,7 +517,7 @@ CmdUndefined When a user command is used but it isn't defined. Useful for defining a command only when it's used. The pattern is matched against the command name. Both and - are set to the name of the command. + expand to the command name. NOTE: Autocompletion won't work until the command is defined. An alternative is to always define the user command and have it @@ -525,12 +526,12 @@ CmdUndefined When a user command is used but it isn't CmdlineChanged After a change was made to the text inside command line. Be careful not to mess up the command line, it may cause Vim to lock up. - is set to the |cmdline-char|. + expands to the |cmdline-char|. *CmdlineEnter* CmdlineEnter After entering the command-line (including non-interactive use of ":" in a mapping: use || instead to avoid this). - is set to the |cmdline-char|. + expands to the |cmdline-char|. Sets these |v:event| keys: cmdlevel cmdtype @@ -538,26 +539,26 @@ CmdlineEnter After entering the command-line (including CmdlineLeave Before leaving the command-line (including non-interactive use of ":" in a mapping: use || instead to avoid this). - is set to the |cmdline-char|. + expands to the |cmdline-char|. Sets these |v:event| keys: abort (mutable) cmdlevel cmdtype Note: `abort` can only be changed from false - to true. An autocmd cannot execute an already - aborted cmdline by changing it to false. + to true: cannot execute an already aborted + cmdline by changing it to false. *CmdwinEnter* CmdwinEnter After entering the command-line window. Useful for setting options specifically for this special type of window. - is set to a single character, + expands to a single character, indicating the type of command-line. |cmdwin-char| *CmdwinLeave* CmdwinLeave Before leaving the command-line window. Useful to clean up any global setting done with CmdwinEnter. - is set to a single character, + expands to a single character, indicating the type of command-line. |cmdwin-char| *ColorScheme* @@ -599,8 +600,7 @@ CompleteDone After Insert mode completion is done. Either completion. |ins-completion| |complete_info()| can be used, the info is cleared after triggering CompleteDone. - The |v:completed_item| variable contains the - completed item. + |v:completed_item| gives the completed item. *CursorHold* CursorHold When the user doesn't press a key for the time @@ -630,9 +630,9 @@ CursorHold When the user doesn't press a key for the time :let &ro = &ro *CursorHoldI* -CursorHoldI Just like CursorHold, but in Insert mode. - Not triggered when waiting for another key, - e.g. after CTRL-V, and not when in CTRL-X mode +CursorHoldI Like CursorHold, but in Insert mode. Not + triggered when waiting for another key, e.g. + after CTRL-V, and not in CTRL-X mode |insert_expand|. *CursorMoved* @@ -643,7 +643,7 @@ CursorMoved After the cursor was moved in Normal or Visual Not triggered when there is typeahead or when an operator is pending. For an example see |match-parens|. - Note: Cannot be skipped with `:noautocmd`. + Note: Cannot be skipped with |:noautocmd|. Careful: This is triggered very often, don't do anything that the user does not expect or that is slow. @@ -665,7 +665,7 @@ DirChanged After the |current-directory| was changed. *FileAppendCmd* FileAppendCmd Before appending to a file. Should do the appending to the file. Use the '[ and '] - marks for the range of lines.|Cmd-event| + marks for the range of lines. |Cmd-event| *FileAppendPost* FileAppendPost After appending to a file. *FileAppendPre* @@ -673,19 +673,18 @@ FileAppendPre Before appending to a file. Use the '[ and '] marks for the range of lines. *FileChangedRO* FileChangedRO Before making the first change to a read-only - file. Can be used to check-out the file from + file. Can be used to checkout the file from a source control system. Not triggered when the change was caused by an autocommand. - This event is triggered when making the first - change in a buffer or the first change after - 'readonly' was set, just before the change is - applied to the text. + Triggered when making the first change in + a buffer or the first change after 'readonly' + was set, just before the change is applied to + the text. WARNING: If the autocommand moves the cursor the effect of the change is undefined. *E788* - It is not allowed to change to another buffer - here. You can reload the buffer but not edit - another one. + Cannot switch buffers. You can reload the + buffer but not edit another one. *E881* If the number of lines changes saving for undo may fail and the change will be aborted. @@ -704,28 +703,21 @@ FileChangedShell When Vim notices that the modification time of Also when the file attributes of the file change or when the size of the file changes. |timestamp| - Mostly triggered after executing a shell - command, but also with a |:checktime| command - or when gvim regains input focus. - This autocommand is triggered for each changed - file. It is not used when 'autoread' is set - and the buffer was not changed. If a - FileChangedShell autocommand is present the - warning message and prompt is not given. - The |v:fcs_reason| variable is set to indicate - what happened and |v:fcs_choice| can be used - to tell Vim what to do next. - NOTE: When this autocommand is executed, the - current buffer "%" may be different from the - buffer that was changed, which is in "". - NOTE: The commands must not change the current - buffer, jump to another buffer or delete a - buffer. *E246* *E811* - NOTE: This event never nests, to avoid an - endless loop. This means that while executing - commands for the FileChangedShell event no - other FileChangedShell event will be - triggered. + Triggered for each changed file, after: + - executing a shell command + - |:checktime| + - |FocusGained| + Not used when 'autoread' is set and the buffer + was not changed. If a FileChangedShell + autocommand exists the warning message and + prompt is not given. + |v:fcs_reason| indicates what happened. Set + |v:fcs_choice| to control what happens next. + NOTE: Current buffer "%" may be different from + the buffer that was changed "". + *E246* *E811* + Cannot switch, jump to or delete buffers. + Non-recursive (event cannot trigger itself). *FileChangedShellPost* FileChangedShellPost After handling a file that was changed outside of Vim. Can be used to update the statusline. @@ -742,10 +734,10 @@ FileReadPre Before reading a file with a ":read" command. *FileType* FileType When the 'filetype' option has been set. The pattern is matched against the filetype. - can be used for the name of the file - where this option was set, and for - the new value of 'filetype'. Navigating to - another window or buffer is not allowed. + is the name of the file where this + option was set. is the new value of + 'filetype'. + Cannot switch windows or buffers. See |filetypes|. *FileWriteCmd* FileWriteCmd Before writing to a file, when not writing the @@ -1018,27 +1010,26 @@ SwapExists Detected an existing swap file when starting When set to an empty string the user will be asked, as if there was no SwapExists autocmd. *E812* - It is not allowed to change to another buffer, - change a buffer name or change directory - here. + Cannot change to another buffer, change + the buffer name or change directory. *Syntax* Syntax When the 'syntax' option has been set. The pattern is matched against the syntax name. - can be used for the name of the file - where this option was set, and for - the new value of 'syntax'. + expands to the name of the file where + this option was set. expands to the + new value of 'syntax'. See |:syn-on|. *TabEnter* TabEnter Just after entering a tab page. |tab-page| - After triggering the WinEnter and before - triggering the BufEnter event. + After WinEnter. + Before BufEnter. *TabLeave* TabLeave Just before leaving a tab page. |tab-page| - A WinLeave event will have been triggered - first. + After WinLeave. *TabNew* TabNew When creating a new tab page. |tab-page| - After WinEnter and before TabEnter. + After WinEnter. + Before TabEnter. *TabNewEntered* TabNewEntered After entering a new tab page. |tab-page| After BufEnter. @@ -1060,10 +1051,9 @@ TermClose When a |terminal| job ends. TermResponse After the response to t_RV is received from the terminal. The value of |v:termresponse| can be used to do things depending on the - terminal version. Note that this event may be - triggered halfway through another event - (especially if file I/O, a shell command, or - anything else that takes time is involved). + terminal version. May be triggered halfway + through another event (file I/O, a shell + command, or anything else that takes time). *TextChanged* TextChanged After a change was made to the text in the current buffer in Normal mode. That is after @@ -1136,6 +1126,7 @@ VimSuspend Before Nvim enters |suspend| state. *WinClosed* WinClosed After closing a window. expands to the |window-ID|. + After WinLeave. Non-recursive (event cannot trigger itself). See also |ExitPre|, |QuitPre|. *WinEnter* @@ -1155,10 +1146,11 @@ WinLeave Before leaving a window. If the window to be executes the BufLeave autocommands before the WinLeave autocommands (but not for ":new"). Not used for ":qa" or ":q" when exiting Vim. + After WinClosed. *WinNew* WinNew When a new window was created. Not done for the first window, when Vim has just started. - Before a WinEnter event. + Before WinEnter. ============================================================================== 6. Patterns *autocmd-pattern* *{pat}* -- cgit