2024-04-20 08:44:13 -07:00
|
|
|
local t = require('test.testutil')
|
|
|
|
local n = require('test.functional.testnvim')()
|
2019-05-08 11:30:30 -07:00
|
|
|
local Screen = require('test.functional.ui.screen')
|
2016-03-01 18:28:08 -07:00
|
|
|
|
2024-04-20 08:44:13 -07:00
|
|
|
local assert_visible = n.assert_visible
|
|
|
|
local assert_alive = n.assert_alive
|
2024-04-08 02:03:20 -07:00
|
|
|
local dedent = t.dedent
|
|
|
|
local eq = t.eq
|
|
|
|
local neq = t.neq
|
2024-04-20 08:44:13 -07:00
|
|
|
local eval = n.eval
|
|
|
|
local feed = n.feed
|
|
|
|
local clear = n.clear
|
2024-04-08 02:03:20 -07:00
|
|
|
local matches = t.matches
|
2024-04-20 08:44:13 -07:00
|
|
|
local api = n.api
|
2024-04-08 02:03:20 -07:00
|
|
|
local pcall_err = t.pcall_err
|
2024-04-20 08:44:13 -07:00
|
|
|
local fn = n.fn
|
|
|
|
local expect = n.expect
|
|
|
|
local command = n.command
|
|
|
|
local exc_exec = n.exc_exec
|
|
|
|
local exec_lua = n.exec_lua
|
2024-04-08 02:03:20 -07:00
|
|
|
local retry = t.retry
|
2024-04-20 08:44:13 -07:00
|
|
|
local source = n.source
|
2017-04-08 11:50:14 -07:00
|
|
|
|
2019-03-09 20:32:58 -07:00
|
|
|
describe('autocmd', function()
|
2016-03-01 18:28:08 -07:00
|
|
|
before_each(clear)
|
|
|
|
|
2020-01-13 01:19:20 -07:00
|
|
|
it(':tabnew, :split, :close events order, <afile>', function()
|
2016-03-01 18:28:08 -07:00
|
|
|
local expected = {
|
2020-01-13 01:19:20 -07:00
|
|
|
{ 'WinLeave', '' },
|
|
|
|
{ 'TabLeave', '' },
|
|
|
|
{ 'WinEnter', '' },
|
|
|
|
{ 'TabNew', 'testfile1' }, -- :tabnew
|
|
|
|
{ 'TabEnter', '' },
|
|
|
|
{ 'BufLeave', '' },
|
|
|
|
{ 'BufEnter', 'testfile1' }, -- :split
|
|
|
|
{ 'WinLeave', 'testfile1' },
|
|
|
|
{ 'WinEnter', 'testfile1' },
|
|
|
|
{ 'WinLeave', 'testfile1' },
|
|
|
|
{ 'WinClosed', '1002' }, -- :close, WinClosed <afile> = window-id
|
|
|
|
{ 'WinEnter', 'testfile1' },
|
|
|
|
{ 'WinLeave', 'testfile1' }, -- :bdelete
|
|
|
|
{ 'WinEnter', 'testfile1' },
|
|
|
|
{ 'BufLeave', 'testfile1' },
|
|
|
|
{ 'BufEnter', 'testfile2' },
|
|
|
|
{ 'WinClosed', '1000' },
|
2016-03-01 18:28:08 -07:00
|
|
|
}
|
2020-01-13 01:19:20 -07:00
|
|
|
command('let g:evs = []')
|
|
|
|
command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])')
|
|
|
|
command('autocmd BufLeave * :call add(g:evs, ["BufLeave", expand("<afile>")])')
|
|
|
|
command('autocmd TabEnter * :call add(g:evs, ["TabEnter", expand("<afile>")])')
|
|
|
|
command('autocmd TabLeave * :call add(g:evs, ["TabLeave", expand("<afile>")])')
|
|
|
|
command('autocmd TabNew * :call add(g:evs, ["TabNew", expand("<afile>")])')
|
|
|
|
command('autocmd WinEnter * :call add(g:evs, ["WinEnter", expand("<afile>")])')
|
|
|
|
command('autocmd WinLeave * :call add(g:evs, ["WinLeave", expand("<afile>")])')
|
|
|
|
command('autocmd WinClosed * :call add(g:evs, ["WinClosed", expand("<afile>")])')
|
|
|
|
command('tabnew testfile1')
|
|
|
|
command('split')
|
2018-09-29 11:40:53 -07:00
|
|
|
command('close')
|
2020-01-13 01:19:20 -07:00
|
|
|
command('new testfile2')
|
|
|
|
command('bdelete 1')
|
|
|
|
eq(expected, eval('g:evs'))
|
2020-01-14 06:34:05 -07:00
|
|
|
end)
|
|
|
|
|
2022-03-23 12:14:44 -07:00
|
|
|
it('first edit causes BufUnload on NoName', function()
|
|
|
|
local expected = {
|
|
|
|
{ 'BufUnload', '' },
|
|
|
|
{ 'BufDelete', '' },
|
|
|
|
{ 'BufWipeout', '' },
|
|
|
|
{ 'BufEnter', 'testfile1' },
|
|
|
|
}
|
|
|
|
command('let g:evs = []')
|
|
|
|
command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])')
|
|
|
|
command('autocmd BufDelete * :call add(g:evs, ["BufDelete", expand("<afile>")])')
|
|
|
|
command('autocmd BufLeave * :call add(g:evs, ["BufLeave", expand("<afile>")])')
|
|
|
|
command('autocmd BufUnload * :call add(g:evs, ["BufUnload", expand("<afile>")])')
|
|
|
|
command('autocmd BufWipeout * :call add(g:evs, ["BufWipeout", expand("<afile>")])')
|
|
|
|
command('edit testfile1')
|
|
|
|
eq(expected, eval('g:evs'))
|
|
|
|
end)
|
|
|
|
|
2020-01-13 01:19:20 -07:00
|
|
|
it('WinClosed is non-recursive', function()
|
2018-09-29 11:40:53 -07:00
|
|
|
command('let g:triggered = 0')
|
2020-01-13 01:19:20 -07:00
|
|
|
command('autocmd WinClosed * :let g:triggered+=1 | :bdelete 2')
|
|
|
|
command('new testfile2')
|
|
|
|
command('new testfile3')
|
2018-09-29 11:40:53 -07:00
|
|
|
|
2020-01-13 01:19:20 -07:00
|
|
|
-- All 3 buffers are visible.
|
|
|
|
assert_visible(1, true)
|
|
|
|
assert_visible(2, true)
|
|
|
|
assert_visible(3, true)
|
2018-09-29 11:40:53 -07:00
|
|
|
|
2020-01-13 01:19:20 -07:00
|
|
|
-- Trigger WinClosed, which also deletes buffer/window 2.
|
|
|
|
command('bdelete 1')
|
2018-09-29 11:40:53 -07:00
|
|
|
|
2020-01-13 01:19:20 -07:00
|
|
|
-- Buffers 1 and 2 were closed but WinClosed was triggered only once.
|
2018-09-29 11:40:53 -07:00
|
|
|
eq(1, eval('g:triggered'))
|
2020-01-13 01:19:20 -07:00
|
|
|
assert_visible(1, false)
|
|
|
|
assert_visible(2, false)
|
|
|
|
assert_visible(3, true)
|
2018-09-29 11:40:53 -07:00
|
|
|
end)
|
|
|
|
|
2020-01-13 01:19:20 -07:00
|
|
|
it('WinClosed from a different tabpage', function()
|
|
|
|
command('let g:evs = []')
|
|
|
|
command('edit tesfile1')
|
|
|
|
command('autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])')
|
|
|
|
local buf1 = eval("bufnr('%')")
|
2018-09-29 11:40:53 -07:00
|
|
|
command('new')
|
2020-01-13 01:19:20 -07:00
|
|
|
local buf2 = eval("bufnr('%')")
|
|
|
|
command(
|
|
|
|
'autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])'
|
|
|
|
-- 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'))
|
2018-09-29 11:40:53 -07:00
|
|
|
end)
|
|
|
|
|
2021-06-26 07:18:36 -07:00
|
|
|
it('WinClosed from root directory', function()
|
|
|
|
command('cd /')
|
|
|
|
command('let g:evs = []')
|
|
|
|
command('autocmd WinClosed * :call add(g:evs, ["WinClosed", expand("<afile>")])')
|
|
|
|
command('new')
|
|
|
|
command('close')
|
|
|
|
eq({
|
|
|
|
{ 'WinClosed', '1001' },
|
|
|
|
}, eval('g:evs'))
|
|
|
|
end)
|
|
|
|
|
2016-11-14 08:19:06 -07:00
|
|
|
it('v:vim_did_enter is 1 after VimEnter', function()
|
|
|
|
eq(1, eval('v:vim_did_enter'))
|
|
|
|
end)
|
2017-04-08 11:50:14 -07:00
|
|
|
|
|
|
|
describe('BufLeave autocommand', function()
|
|
|
|
it('can wipe out the buffer created by :edit which triggered autocmd', function()
|
2024-01-12 10:59:57 -07:00
|
|
|
api.nvim_set_option_value('hidden', true, {})
|
|
|
|
api.nvim_buf_set_lines(0, 0, 1, false, {
|
2017-04-08 11:50:14 -07:00
|
|
|
'start of test file xx',
|
|
|
|
'end of test file xx',
|
|
|
|
})
|
|
|
|
|
|
|
|
command('autocmd BufLeave * bwipeout yy')
|
|
|
|
eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', exc_exec('edit yy'))
|
|
|
|
|
|
|
|
expect([[
|
|
|
|
start of test file xx
|
|
|
|
end of test file xx]])
|
|
|
|
end)
|
|
|
|
end)
|
2019-03-09 20:32:58 -07:00
|
|
|
|
2019-03-13 14:13:25 -07:00
|
|
|
it('++once', function() -- :help autocmd-once
|
2019-03-09 20:32:58 -07:00
|
|
|
--
|
2019-03-13 14:13:25 -07:00
|
|
|
-- ":autocmd ... ++once" executes its handler once, then removes the handler.
|
2019-03-09 20:32:58 -07:00
|
|
|
--
|
|
|
|
local expected = {
|
|
|
|
'Many1',
|
|
|
|
'Once1',
|
|
|
|
'Once2',
|
|
|
|
'Many2',
|
|
|
|
'Once3',
|
|
|
|
'Many1',
|
|
|
|
'Many2',
|
|
|
|
'Many1',
|
|
|
|
'Many2',
|
|
|
|
}
|
|
|
|
command('let g:foo = []')
|
|
|
|
command('autocmd TabNew * :call add(g:foo, "Many1")')
|
2019-03-13 14:13:25 -07:00
|
|
|
command('autocmd TabNew * ++once :call add(g:foo, "Once1")')
|
|
|
|
command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
|
2019-03-09 20:32:58 -07:00
|
|
|
command('autocmd TabNew * :call add(g:foo, "Many2")')
|
2019-03-13 14:13:25 -07:00
|
|
|
command('autocmd TabNew * ++once :call add(g:foo, "Once3")')
|
2019-03-09 20:32:58 -07:00
|
|
|
eq(
|
|
|
|
dedent([[
|
|
|
|
|
|
|
|
--- Autocommands ---
|
|
|
|
TabNew
|
|
|
|
* :call add(g:foo, "Many1")
|
|
|
|
:call add(g:foo, "Once1")
|
|
|
|
:call add(g:foo, "Once2")
|
|
|
|
:call add(g:foo, "Many2")
|
|
|
|
:call add(g:foo, "Once3")]]),
|
2024-01-12 10:59:57 -07:00
|
|
|
fn.execute('autocmd Tabnew')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2019-03-09 20:32:58 -07:00
|
|
|
command('tabnew')
|
|
|
|
command('tabnew')
|
|
|
|
command('tabnew')
|
|
|
|
eq(expected, eval('g:foo'))
|
|
|
|
eq(
|
|
|
|
dedent([[
|
|
|
|
|
|
|
|
--- Autocommands ---
|
|
|
|
TabNew
|
|
|
|
* :call add(g:foo, "Many1")
|
|
|
|
:call add(g:foo, "Many2")]]),
|
2024-01-12 10:59:57 -07:00
|
|
|
fn.execute('autocmd Tabnew')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2019-03-09 20:32:58 -07:00
|
|
|
|
|
|
|
--
|
2019-03-13 14:13:25 -07:00
|
|
|
-- ":autocmd ... ++once" handlers can be deleted.
|
2019-03-09 20:32:58 -07:00
|
|
|
--
|
|
|
|
expected = {}
|
|
|
|
command('let g:foo = []')
|
2019-03-13 14:13:25 -07:00
|
|
|
command('autocmd TabNew * ++once :call add(g:foo, "Once1")')
|
2019-03-09 20:32:58 -07:00
|
|
|
command('autocmd! TabNew')
|
|
|
|
command('tabnew')
|
|
|
|
eq(expected, eval('g:foo'))
|
|
|
|
|
|
|
|
--
|
2019-03-13 14:13:25 -07:00
|
|
|
-- ":autocmd ... <buffer> ++once ++nested"
|
2019-03-09 20:32:58 -07:00
|
|
|
--
|
|
|
|
expected = {
|
|
|
|
'OptionSet-Once',
|
|
|
|
'CursorMoved-Once',
|
|
|
|
}
|
|
|
|
command('let g:foo = []')
|
2019-03-13 14:13:25 -07:00
|
|
|
command('autocmd OptionSet binary ++nested ++once :call add(g:foo, "OptionSet-Once")')
|
|
|
|
command(
|
|
|
|
'autocmd CursorMoved <buffer> ++once ++nested setlocal binary|:call add(g:foo, "CursorMoved-Once")'
|
|
|
|
)
|
2019-03-09 20:32:58 -07:00
|
|
|
command("put ='foo bar baz'")
|
|
|
|
feed('0llhlh')
|
|
|
|
eq(expected, eval('g:foo'))
|
2019-03-13 14:31:07 -07:00
|
|
|
|
|
|
|
--
|
|
|
|
-- :autocmd should not show empty section after ++once handlers expire.
|
|
|
|
--
|
|
|
|
expected = {
|
|
|
|
'Once1',
|
|
|
|
'Once2',
|
|
|
|
}
|
|
|
|
command('let g:foo = []')
|
|
|
|
command('autocmd! TabNew') -- Clear all TabNew handlers.
|
|
|
|
command('autocmd TabNew * ++once :call add(g:foo, "Once1")')
|
|
|
|
command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
|
|
|
|
command('tabnew')
|
|
|
|
eq(expected, eval('g:foo'))
|
|
|
|
eq(
|
|
|
|
dedent([[
|
|
|
|
|
|
|
|
--- Autocommands ---]]),
|
2024-01-12 10:59:57 -07:00
|
|
|
fn.execute('autocmd Tabnew')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2019-03-09 20:32:58 -07:00
|
|
|
end)
|
2019-05-08 11:30:30 -07:00
|
|
|
|
2019-05-21 15:10:35 -07:00
|
|
|
it('internal `aucmd_win` window', function()
|
|
|
|
-- Nvim uses a special internal window `aucmd_win` to execute certain
|
|
|
|
-- actions for an invisible buffer (:help E813).
|
|
|
|
-- Check redrawing and API accesses to this window.
|
2019-05-08 11:30:30 -07:00
|
|
|
|
|
|
|
local screen = Screen.new(50, 10)
|
|
|
|
|
|
|
|
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 |
|
2023-12-09 05:42:00 -07:00
|
|
|
{1:~ }|*8
|
2019-05-08 11:30:30 -07:00
|
|
|
|
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed(':enew | doautoall User<cr>')
|
|
|
|
screen:expect([[
|
2024-08-14 04:42:05 -07:00
|
|
|
{4:bb }|
|
|
|
|
{11:~ }|*4
|
2023-12-09 05:42:00 -07:00
|
|
|
{1:~ }|*4
|
2019-05-08 11:30:30 -07:00
|
|
|
^:enew | doautoall User |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed('<cr>')
|
|
|
|
screen:expect([[
|
|
|
|
^ |
|
2023-12-09 05:42:00 -07:00
|
|
|
{1:~ }|*8
|
2019-05-08 11:30:30 -07:00
|
|
|
13 |
|
|
|
|
]])
|
|
|
|
eq(7, eval('g:test'))
|
|
|
|
|
|
|
|
-- API calls are blocked when aucmd_win is not in scope
|
2020-01-14 01:21:10 -07:00
|
|
|
eq(
|
|
|
|
'Vim(call):E5555: API call: Invalid window id: 1001',
|
2019-09-03 13:51:45 -07:00
|
|
|
pcall_err(command, 'call nvim_set_current_win(g:winid)')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2019-05-08 11:30:30 -07:00
|
|
|
|
|
|
|
-- 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([[
|
2024-08-14 04:42:05 -07:00
|
|
|
{4:bb }|
|
|
|
|
{11:~ }|*4
|
2023-12-09 05:42:00 -07:00
|
|
|
{1:~ }|*4
|
2019-05-08 11:30:30 -07:00
|
|
|
^:doautoall User |
|
|
|
|
]])
|
|
|
|
|
|
|
|
feed('<cr>')
|
|
|
|
screen:expect([[
|
|
|
|
^ |
|
2023-12-09 05:42:00 -07:00
|
|
|
{1:~ }|*8
|
2019-05-08 11:30:30 -07:00
|
|
|
13 |
|
|
|
|
]])
|
|
|
|
-- win vars in aucmd_win should have been reset
|
|
|
|
eq(0, eval('g:had_value'))
|
|
|
|
eq(7, eval('g:test'))
|
|
|
|
|
2020-01-14 01:21:10 -07:00
|
|
|
eq(
|
|
|
|
'Vim(call):E5555: API call: Invalid window id: 1001',
|
2019-09-03 13:51:45 -07:00
|
|
|
pcall_err(command, 'call nvim_set_current_win(g:winid)')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2019-05-08 11:30:30 -07:00
|
|
|
end)
|
2019-08-04 18:33:45 -07:00
|
|
|
|
2021-12-31 02:32:04 -07:00
|
|
|
it('`aucmd_win` cannot be changed into a normal window #13699', function()
|
|
|
|
local screen = Screen.new(50, 10)
|
|
|
|
|
|
|
|
-- Create specific layout and ensure it's left unchanged.
|
2024-06-08 12:40:18 -07:00
|
|
|
-- Use vim._with on a hidden buffer so aucmd_win is used.
|
2021-12-31 02:32:04 -07:00
|
|
|
exec_lua [[
|
|
|
|
vim.cmd "wincmd s | wincmd _"
|
|
|
|
_G.buf = vim.api.nvim_create_buf(true, true)
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function() vim.cmd "wincmd J" end)
|
2021-12-31 02:32:04 -07:00
|
|
|
]]
|
|
|
|
screen:expect [[
|
|
|
|
^ |
|
2023-12-09 05:42:00 -07:00
|
|
|
{1:~ }|*5
|
2021-12-31 02:32:04 -07:00
|
|
|
{3:[No Name] }|
|
|
|
|
|
|
|
|
|
{2:[No Name] }|
|
|
|
|
|
|
|
|
|
]]
|
|
|
|
-- This used to crash after making aucmd_win a normal window via the above.
|
|
|
|
exec_lua [[
|
|
|
|
vim.cmd "tabnew | tabclose # | wincmd s | wincmd _"
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function() vim.cmd "wincmd K" end)
|
2021-12-31 02:32:04 -07:00
|
|
|
]]
|
|
|
|
assert_alive()
|
|
|
|
screen:expect_unchanged()
|
|
|
|
|
2024-04-06 16:10:32 -07:00
|
|
|
-- Also check with win_splitmove().
|
|
|
|
exec_lua [[
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function()
|
2024-04-06 16:10:32 -07:00
|
|
|
vim.fn.win_splitmove(vim.fn.winnr(), vim.fn.win_getid(1))
|
|
|
|
end)
|
|
|
|
]]
|
|
|
|
screen:expect_unchanged()
|
|
|
|
|
|
|
|
-- Also check with nvim_win_set_config().
|
|
|
|
matches(
|
2024-06-08 12:40:18 -07:00
|
|
|
'^Failed to move window %d+ into split$',
|
2024-04-06 16:10:32 -07:00
|
|
|
pcall_err(
|
|
|
|
exec_lua,
|
|
|
|
[[
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function()
|
2024-04-06 16:10:32 -07:00
|
|
|
vim.api.nvim_win_set_config(0, {
|
|
|
|
vertical = true,
|
|
|
|
win = vim.fn.win_getid(1)
|
|
|
|
})
|
|
|
|
end)
|
|
|
|
]]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
screen:expect_unchanged()
|
|
|
|
|
2021-12-31 02:32:04 -07:00
|
|
|
-- Ensure splitting still works from inside the aucmd_win.
|
2024-06-08 12:40:18 -07:00
|
|
|
exec_lua [[vim._with({buf = _G.buf}, function() vim.cmd "split" end)]]
|
2021-12-31 02:32:04 -07:00
|
|
|
screen:expect [[
|
|
|
|
^ |
|
|
|
|
{1:~ }|
|
|
|
|
{3:[No Name] }|
|
|
|
|
|
|
|
|
|
{1:~ }|
|
|
|
|
{2:[Scratch] }|
|
|
|
|
|
|
|
|
|
{1:~ }|
|
|
|
|
{2:[No Name] }|
|
|
|
|
|
|
|
|
|
]]
|
|
|
|
|
|
|
|
-- After all of our messing around, aucmd_win should still be floating.
|
|
|
|
-- Use :only to ensure _G.buf is hidden again (so the aucmd_win is used).
|
|
|
|
eq(
|
|
|
|
'editor',
|
|
|
|
exec_lua [[
|
2024-04-06 16:10:32 -07:00
|
|
|
vim.cmd "only"
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function()
|
2024-04-06 16:10:32 -07:00
|
|
|
_G.config = vim.api.nvim_win_get_config(0)
|
|
|
|
end)
|
|
|
|
return _G.config.relative
|
|
|
|
]]
|
2021-12-31 02:32:04 -07:00
|
|
|
)
|
|
|
|
end)
|
|
|
|
|
2022-03-21 06:19:09 -07:00
|
|
|
describe('closing last non-floating window in tab from `aucmd_win`', function()
|
|
|
|
before_each(function()
|
|
|
|
command('edit Xa.txt')
|
|
|
|
command('tabnew Xb.txt')
|
|
|
|
command('autocmd BufAdd Xa.txt 1close')
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('gives E814 when there are no other floating windows', function()
|
2023-01-15 15:38:50 -07:00
|
|
|
eq(
|
|
|
|
'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
|
2022-03-21 06:19:09 -07:00
|
|
|
pcall_err(command, 'doautoall BufAdd')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2022-03-21 06:19:09 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
it('gives E814 when there are other floating windows', function()
|
2024-01-12 10:59:57 -07:00
|
|
|
api.nvim_open_win(
|
2024-01-12 05:44:54 -07:00
|
|
|
0,
|
|
|
|
true,
|
|
|
|
{ width = 10, height = 10, relative = 'editor', row = 10, col = 10 }
|
|
|
|
)
|
2023-01-15 15:38:50 -07:00
|
|
|
eq(
|
|
|
|
'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
|
2022-03-21 06:19:09 -07:00
|
|
|
pcall_err(command, 'doautoall BufAdd')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2022-03-21 06:19:09 -07:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
2023-01-24 00:39:43 -07:00
|
|
|
it('closing `aucmd_win` using API gives E813', function()
|
|
|
|
exec_lua([[
|
|
|
|
vim.cmd('tabnew')
|
|
|
|
_G.buf = vim.api.nvim_create_buf(true, true)
|
|
|
|
]])
|
|
|
|
matches(
|
|
|
|
'Vim:E813: Cannot close autocmd window$',
|
|
|
|
pcall_err(
|
|
|
|
exec_lua,
|
|
|
|
[[
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function()
|
2024-04-06 16:10:32 -07:00
|
|
|
local win = vim.api.nvim_get_current_win()
|
|
|
|
vim.api.nvim_win_close(win, true)
|
|
|
|
end)
|
|
|
|
]]
|
2023-01-24 00:39:43 -07:00
|
|
|
)
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2023-01-24 00:39:43 -07:00
|
|
|
matches(
|
|
|
|
'Vim:E813: Cannot close autocmd window$',
|
|
|
|
pcall_err(
|
|
|
|
exec_lua,
|
|
|
|
[[
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function()
|
2024-04-06 16:10:32 -07:00
|
|
|
local win = vim.api.nvim_get_current_win()
|
|
|
|
vim.cmd('tabnext')
|
|
|
|
vim.api.nvim_win_close(win, true)
|
|
|
|
end)
|
|
|
|
]]
|
2023-01-24 00:39:43 -07:00
|
|
|
)
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2023-01-24 00:39:43 -07:00
|
|
|
matches(
|
|
|
|
'Vim:E813: Cannot close autocmd window$',
|
|
|
|
pcall_err(
|
|
|
|
exec_lua,
|
|
|
|
[[
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function()
|
2024-04-06 16:10:32 -07:00
|
|
|
local win = vim.api.nvim_get_current_win()
|
|
|
|
vim.api.nvim_win_hide(win)
|
|
|
|
end)
|
|
|
|
]]
|
2023-01-24 00:39:43 -07:00
|
|
|
)
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2023-01-24 00:39:43 -07:00
|
|
|
matches(
|
|
|
|
'Vim:E813: Cannot close autocmd window$',
|
|
|
|
pcall_err(
|
|
|
|
exec_lua,
|
|
|
|
[[
|
2024-06-08 12:40:18 -07:00
|
|
|
vim._with({buf = _G.buf}, function()
|
2024-04-06 16:10:32 -07:00
|
|
|
local win = vim.api.nvim_get_current_win()
|
|
|
|
vim.cmd('tabnext')
|
|
|
|
vim.api.nvim_win_hide(win)
|
|
|
|
end)
|
|
|
|
]]
|
2023-01-24 00:39:43 -07:00
|
|
|
)
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2023-01-24 00:39:43 -07:00
|
|
|
end)
|
|
|
|
|
2019-08-04 18:33:45 -07:00
|
|
|
it(':doautocmd does not warn "No matching autocommands" #10689', function()
|
|
|
|
local screen = Screen.new(32, 3)
|
|
|
|
|
|
|
|
feed(':doautocmd User Foo<cr>')
|
|
|
|
screen:expect {
|
|
|
|
grid = [[
|
|
|
|
^ |
|
|
|
|
{1:~ }|
|
|
|
|
:doautocmd User Foo |
|
|
|
|
]],
|
|
|
|
}
|
|
|
|
feed(':autocmd! SessionLoadPost<cr>')
|
|
|
|
feed(':doautocmd SessionLoadPost<cr>')
|
|
|
|
screen:expect {
|
|
|
|
grid = [[
|
|
|
|
^ |
|
|
|
|
{1:~ }|
|
|
|
|
:doautocmd SessionLoadPost |
|
|
|
|
]],
|
|
|
|
}
|
|
|
|
end)
|
2021-05-28 12:45:34 -07:00
|
|
|
|
2022-04-10 20:32:15 -07:00
|
|
|
describe('v:event is readonly #18063', function()
|
|
|
|
it('during ChanOpen event', function()
|
|
|
|
command('autocmd ChanOpen * let v:event.info.id = 0')
|
2024-01-12 10:59:57 -07:00
|
|
|
fn.jobstart({ 'cat' })
|
2022-04-10 20:32:15 -07:00
|
|
|
retry(nil, nil, function()
|
2024-01-12 10:59:57 -07:00
|
|
|
eq('E46: Cannot change read-only variable "v:event.info"', api.nvim_get_vvar('errmsg'))
|
2022-04-10 20:32:15 -07:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('during ChanOpen event', function()
|
|
|
|
command('autocmd ChanInfo * let v:event.info.id = 0')
|
2024-01-12 10:59:57 -07:00
|
|
|
api.nvim_set_client_info('foo', {}, 'remote', {}, {})
|
2022-04-10 20:32:15 -07:00
|
|
|
retry(nil, nil, function()
|
2024-01-12 10:59:57 -07:00
|
|
|
eq('E46: Cannot change read-only variable "v:event.info"', api.nvim_get_vvar('errmsg'))
|
2022-04-10 20:32:15 -07:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('during RecordingLeave event', function()
|
|
|
|
command([[autocmd RecordingLeave * let v:event.regname = '']])
|
2023-01-15 15:38:50 -07:00
|
|
|
eq(
|
|
|
|
'RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"',
|
2022-04-10 20:32:15 -07:00
|
|
|
pcall_err(command, 'normal! qqq')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2022-04-10 20:32:15 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
it('during TermClose event', function()
|
|
|
|
command('autocmd TermClose * let v:event.status = 0')
|
|
|
|
command('terminal')
|
2023-01-15 15:38:50 -07:00
|
|
|
eq(
|
|
|
|
'TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"',
|
2022-04-10 20:32:15 -07:00
|
|
|
pcall_err(command, 'bdelete!')
|
2024-01-02 18:09:18 -07:00
|
|
|
)
|
2022-04-10 20:32:15 -07:00
|
|
|
end)
|
|
|
|
end)
|
|
|
|
|
2021-05-28 12:45:34 -07:00
|
|
|
describe('old_tests', function()
|
|
|
|
it('vimscript: WinNew ++once', function()
|
|
|
|
source [[
|
|
|
|
" Without ++once WinNew triggers twice
|
|
|
|
let g:did_split = 0
|
|
|
|
augroup Testing
|
|
|
|
au!
|
|
|
|
au WinNew * let g:did_split += 1
|
|
|
|
augroup END
|
|
|
|
split
|
|
|
|
split
|
|
|
|
call assert_equal(2, g:did_split)
|
|
|
|
call assert_true(exists('#WinNew'))
|
|
|
|
close
|
|
|
|
close
|
|
|
|
|
|
|
|
" With ++once WinNew triggers once
|
|
|
|
let g:did_split = 0
|
|
|
|
augroup Testing
|
|
|
|
au!
|
|
|
|
au WinNew * ++once let g:did_split += 1
|
|
|
|
augroup END
|
|
|
|
split
|
|
|
|
split
|
|
|
|
call assert_equal(1, g:did_split)
|
|
|
|
call assert_false(exists('#WinNew'))
|
|
|
|
close
|
|
|
|
close
|
|
|
|
|
|
|
|
call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
|
|
|
|
]]
|
|
|
|
|
2024-01-12 10:59:57 -07:00
|
|
|
api.nvim_set_var('did_split', 0)
|
2021-05-28 12:45:34 -07:00
|
|
|
|
|
|
|
source [[
|
|
|
|
augroup Testing
|
|
|
|
au!
|
|
|
|
au WinNew * let g:did_split += 1
|
|
|
|
augroup END
|
|
|
|
|
|
|
|
split
|
|
|
|
split
|
|
|
|
]]
|
|
|
|
|
2024-01-12 10:59:57 -07:00
|
|
|
eq(2, api.nvim_get_var('did_split'))
|
|
|
|
eq(1, fn.exists('#WinNew'))
|
2021-05-28 12:45:34 -07:00
|
|
|
|
|
|
|
-- Now with once
|
2024-01-12 10:59:57 -07:00
|
|
|
api.nvim_set_var('did_split', 0)
|
2021-05-28 12:45:34 -07:00
|
|
|
|
|
|
|
source [[
|
|
|
|
augroup Testing
|
|
|
|
au!
|
|
|
|
au WinNew * ++once let g:did_split += 1
|
|
|
|
augroup END
|
|
|
|
|
|
|
|
split
|
|
|
|
split
|
|
|
|
]]
|
|
|
|
|
2024-01-12 10:59:57 -07:00
|
|
|
eq(1, api.nvim_get_var('did_split'))
|
|
|
|
eq(0, fn.exists('#WinNew'))
|
2021-05-28 12:45:34 -07:00
|
|
|
|
|
|
|
-- call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
|
|
|
|
local ok, msg = pcall(
|
|
|
|
source,
|
|
|
|
[[
|
|
|
|
au WinNew * ++once ++once echo bad
|
|
|
|
]]
|
|
|
|
)
|
|
|
|
|
|
|
|
eq(false, ok)
|
|
|
|
eq(true, not not string.find(msg, 'E983:'))
|
|
|
|
end)
|
|
|
|
|
|
|
|
it('should have autocmds in filetypedetect group', function()
|
|
|
|
source [[filetype on]]
|
2024-01-12 10:59:57 -07:00
|
|
|
neq({}, api.nvim_get_autocmds { group = 'filetypedetect' })
|
2021-05-28 12:45:34 -07:00
|
|
|
end)
|
|
|
|
|
|
|
|
it('should allow comma-separated patterns', function()
|
|
|
|
source [[
|
|
|
|
augroup TestingPatterns
|
|
|
|
au!
|
|
|
|
autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello'
|
|
|
|
autocmd BufReadCmd *.shada,*.shada.tmp.[a-z] echo 'hello'
|
|
|
|
augroup END
|
|
|
|
]]
|
|
|
|
|
2024-01-12 10:59:57 -07:00
|
|
|
eq(4, #api.nvim_get_autocmds { event = 'BufReadCmd', group = 'TestingPatterns' })
|
2021-05-28 12:45:34 -07:00
|
|
|
end)
|
|
|
|
end)
|
2023-04-27 10:25:08 -07:00
|
|
|
|
|
|
|
it('no use-after-free when adding autocommands from a callback', function()
|
|
|
|
exec_lua [[
|
|
|
|
vim.cmd "autocmd! TabNew"
|
|
|
|
vim.g.count = 0
|
|
|
|
vim.api.nvim_create_autocmd('TabNew', {
|
|
|
|
callback = function()
|
|
|
|
vim.g.count = vim.g.count + 1
|
|
|
|
for _ = 1, 100 do
|
|
|
|
vim.cmd "autocmd TabNew * let g:count += 1"
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
vim.cmd "tabnew"
|
|
|
|
]]
|
|
|
|
eq(1, eval('g:count')) -- Added autocommands should not be executed
|
|
|
|
end)
|
2023-04-27 13:03:17 -07:00
|
|
|
|
|
|
|
it('no crash when clearing a group inside a callback #23355', function()
|
|
|
|
exec_lua [[
|
|
|
|
vim.cmd "autocmd! TabNew"
|
|
|
|
local group = vim.api.nvim_create_augroup('Test', {})
|
|
|
|
local id
|
|
|
|
id = vim.api.nvim_create_autocmd('TabNew', {
|
|
|
|
group = group,
|
|
|
|
callback = function()
|
|
|
|
vim.api.nvim_del_autocmd(id)
|
|
|
|
vim.api.nvim_create_augroup('Test', { clear = true })
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
vim.cmd "tabnew"
|
|
|
|
]]
|
|
|
|
end)
|
2016-03-01 18:28:08 -07:00
|
|
|
end)
|