neovim/test/old/testdir/test_autocmd.vim

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

3631 lines
106 KiB
VimL
Raw Normal View History

" Tests for autocommands
source shared.vim
source check.vim
source term_util.vim
source screendump.vim
source load.vim
func s:cleanup_buffers() abort
for bnr in range(1, bufnr('$'))
if bufloaded(bnr) && bufnr('%') != bnr
execute 'bd! ' . bnr
endif
endfor
endfunc
func Test_vim_did_enter()
call assert_false(v:vim_did_enter)
" This script will never reach the main loop, can't check if v:vim_did_enter
" becomes one.
endfunc
" Test for the CursorHold autocmd
func Test_CursorHold_autocmd()
CheckRunVimInTerminal
call writefile(['one', 'two', 'three'], 'Xfile')
let before =<< trim END
set updatetime=10
au CursorHold * call writefile([line('.')], 'Xoutput', 'a')
END
call writefile(before, 'Xinit')
let buf = RunVimInTerminal('-S Xinit Xfile', {})
call term_sendkeys(buf, "G")
call term_wait(buf, 20)
call term_sendkeys(buf, "gg")
call term_wait(buf)
call WaitForAssert({-> assert_equal(['1'], readfile('Xoutput')[-1:-1])})
call term_sendkeys(buf, "j")
call term_wait(buf)
call WaitForAssert({-> assert_equal(['1', '2'], readfile('Xoutput')[-2:-1])})
call term_sendkeys(buf, "j")
call term_wait(buf)
call WaitForAssert({-> assert_equal(['1', '2', '3'], readfile('Xoutput')[-3:-1])})
call StopVimInTerminal(buf)
call delete('Xinit')
call delete('Xoutput')
call delete('Xfile')
endfunc
if has('timers')
func ExitInsertMode(id)
call feedkeys("\<Esc>")
endfunc
func Test_cursorhold_insert()
" Need to move the cursor.
call feedkeys("ggG", "xt")
let g:triggered = 0
au CursorHoldI * let g:triggered += 1
set updatetime=20
call timer_start(LoadAdjust(200), 'ExitInsertMode')
call feedkeys('a', 'x!')
call assert_equal(1, g:triggered)
unlet g:triggered
au! CursorHoldI
set updatetime&
endfunc
func Test_cursorhold_insert_with_timer_interrupt()
CheckFeature job
" Need to move the cursor.
call feedkeys("ggG", "xt")
" Confirm the timer invoked in exit_cb of the job doesn't disturb
" CursorHoldI event.
let g:triggered = 0
au CursorHoldI * let g:triggered += 1
set updatetime=500
call job_start(has('win32') ? 'cmd /c echo:' : 'echo',
\ {'exit_cb': {-> timer_start(1000, 'ExitInsertMode')}})
call feedkeys('a', 'x!')
call assert_equal(1, g:triggered)
unlet g:triggered
au! CursorHoldI
set updatetime&
endfunc
func Test_cursorhold_insert_ctrl_x()
let g:triggered = 0
au CursorHoldI * let g:triggered += 1
set updatetime=20
call timer_start(LoadAdjust(100), 'ExitInsertMode')
" CursorHoldI does not trigger after CTRL-X
call feedkeys("a\<C-X>", 'x!')
call assert_equal(0, g:triggered)
unlet g:triggered
au! CursorHoldI
set updatetime&
endfunc
func Test_OptionSet_modeline()
CheckFunction test_override
call test_override('starting', 1)
au! OptionSet
augroup set_tabstop
au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler called'", "")})
augroup END
call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline')
set modeline
let v:errmsg = ''
call assert_fails('split XoptionsetModeline', 'E12:')
call assert_equal(7, &ts)
call assert_equal('', v:errmsg)
augroup set_tabstop
au!
augroup END
bwipe!
set ts&
call delete('XoptionsetModeline')
call test_override('starting', 0)
endfunc
endif "has('timers')
func Test_bufunload()
augroup test_bufunload_group
autocmd!
autocmd BufUnload * call add(s:li, "bufunload")
autocmd BufDelete * call add(s:li, "bufdelete")
autocmd BufWipeout * call add(s:li, "bufwipeout")
augroup END
let s:li = []
new
setlocal bufhidden=
bunload
call assert_equal(["bufunload", "bufdelete"], s:li)
let s:li = []
new
setlocal bufhidden=delete
bunload
call assert_equal(["bufunload", "bufdelete"], s:li)
let s:li = []
new
setlocal bufhidden=unload
bwipeout
call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li)
au! test_bufunload_group
augroup! test_bufunload_group
endfunc
" SEGV occurs in older versions. (At least 7.4.2005 or older)
func Test_autocmd_bufunload_with_tabnext()
tabedit
tabfirst
augroup test_autocmd_bufunload_with_tabnext_group
autocmd!
autocmd BufUnload <buffer> tabnext
augroup END
quit
call assert_equal(2, tabpagenr('$'))
autocmd! test_autocmd_bufunload_with_tabnext_group
augroup! test_autocmd_bufunload_with_tabnext_group
tablast
quit
endfunc
func Test_argdelete_in_next()
au BufNew,BufEnter,BufLeave,BufWinEnter * argdel
call assert_fails('next a b', 'E1156:')
au! BufNew,BufEnter,BufLeave,BufWinEnter *
endfunc
func Test_autocmd_bufwinleave_with_tabfirst()
tabedit
augroup sample
autocmd!
autocmd BufWinLeave <buffer> tabfirst
augroup END
call setline(1, ['a', 'b', 'c'])
edit! a.txt
tabclose
endfunc
" SEGV occurs in older versions. (At least 7.4.2321 or older)
func Test_autocmd_bufunload_avoiding_SEGV_01()
split aa.txt
let lastbuf = bufnr('$')
augroup test_autocmd_bufunload
autocmd!
exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
augroup END
call assert_fails('edit bb.txt', 'E937:')
autocmd! test_autocmd_bufunload
augroup! test_autocmd_bufunload
bwipe! aa.txt
bwipe! bb.txt
endfunc
" SEGV occurs in older versions. (At least 7.4.2321 or older)
func Test_autocmd_bufunload_avoiding_SEGV_02()
setlocal buftype=nowrite
let lastbuf = bufnr('$')
augroup test_autocmd_bufunload
autocmd!
exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
augroup END
normal! i1
call assert_fails('edit a.txt', 'E517:')
autocmd! test_autocmd_bufunload
augroup! test_autocmd_bufunload
bwipe! a.txt
endfunc
func Test_autocmd_dummy_wipeout()
" prepare files
call writefile([''], 'Xdummywipetest1.txt')
call writefile([''], 'Xdummywipetest2.txt')
augroup test_bufunload_group
autocmd!
autocmd BufUnload * call add(s:li, "bufunload")
autocmd BufDelete * call add(s:li, "bufdelete")
autocmd BufWipeout * call add(s:li, "bufwipeout")
augroup END
let s:li = []
split Xdummywipetest1.txt
silent! vimgrep /notmatched/ Xdummywipetest*
call assert_equal(["bufunload", "bufwipeout"], s:li)
bwipeout
call delete('Xdummywipetest1.txt')
call delete('Xdummywipetest2.txt')
au! test_bufunload_group
augroup! test_bufunload_group
endfunc
func Test_win_tab_autocmd()
let g:record = []
augroup testing
au WinNew * call add(g:record, 'WinNew')
au WinClosed * call add(g:record, 'WinClosed')
au WinEnter * call add(g:record, 'WinEnter')
au WinLeave * call add(g:record, 'WinLeave')
au TabNew * call add(g:record, 'TabNew')
au TabClosed * call add(g:record, 'TabClosed')
au TabEnter * call add(g:record, 'TabEnter')
au TabLeave * call add(g:record, 'TabLeave')
augroup END
split
tabnew
close
close
call assert_equal([
\ 'WinLeave', 'WinNew', 'WinEnter',
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
\ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter',
\ 'WinLeave', 'WinClosed', 'WinEnter'
\ ], g:record)
let g:record = []
tabnew somefile
tabnext
bwipe somefile
call assert_equal([
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
\ 'WinClosed', 'TabClosed'
\ ], g:record)
augroup testing
au!
augroup END
unlet g:record
endfunc
func Test_WinResized()
CheckRunVimInTerminal
let lines =<< trim END
set scrolloff=0
call setline(1, ['111', '222'])
vnew
call setline(1, ['aaa', 'bbb'])
new
call setline(1, ['foo', 'bar'])
let g:resized = 0
au WinResized * let g:resized += 1
func WriteResizedEvent()
call writefile([json_encode(v:event)], 'XresizeEvent')
endfunc
au WinResized * call WriteResizedEvent()
END
call writefile(lines, 'Xtest_winresized', 'D')
let buf = RunVimInTerminal('-S Xtest_winresized', {'rows': 10})
" redraw now to avoid a redraw after the :echo command
call term_sendkeys(buf, ":redraw!\<CR>")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:resized\<CR>")
call WaitForAssert({-> assert_match('^0$', term_getline(buf, 10))}, 1000)
" increase window height, two windows will be reported
call term_sendkeys(buf, "\<C-W>+")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:resized\<CR>")
call WaitForAssert({-> assert_match('^1$', term_getline(buf, 10))}, 1000)
let event = readfile('XresizeEvent')[0]->json_decode()
call assert_equal({
\ 'windows': [1002, 1001],
\ }, event)
" increase window width, three windows will be reported
call term_sendkeys(buf, "\<C-W>>")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:resized\<CR>")
call WaitForAssert({-> assert_match('^2$', term_getline(buf, 10))}, 1000)
let event = readfile('XresizeEvent')[0]->json_decode()
call assert_equal({
\ 'windows': [1002, 1001, 1000],
\ }, event)
call delete('XresizeEvent')
call StopVimInTerminal(buf)
endfunc
func Test_WinScrolled()
CheckRunVimInTerminal
let lines =<< trim END
set nowrap scrolloff=0
for ii in range(1, 18)
call setline(ii, repeat(nr2char(96 + ii), ii * 2))
endfor
let win_id = win_getid()
let g:matched = v:false
func WriteScrollEvent()
call writefile([json_encode(v:event)], 'XscrollEvent')
endfunc
execute 'au WinScrolled' win_id 'let g:matched = v:true'
let g:scrolled = 0
au WinScrolled * let g:scrolled += 1
au WinScrolled * let g:amatch = str2nr(expand('<amatch>'))
au WinScrolled * let g:afile = str2nr(expand('<afile>'))
au WinScrolled * call WriteScrollEvent()
END
call writefile(lines, 'Xtest_winscrolled', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled', {'rows': 6})
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000)
" Scroll left/right in Normal mode.
call term_sendkeys(buf, "zlzh:echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 1, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': -1, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Scroll up/down in Normal mode.
call term_sendkeys(buf, "\<c-e>\<c-y>:echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^4 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': -1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Scroll up/down in Insert mode.
call term_sendkeys(buf, "Mi\<c-x>\<c-e>\<Esc>i\<c-x>\<c-y>\<Esc>")
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^6 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': -1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Scroll the window horizontally to focus the last letter of the third line
" containing only six characters. Moving to the previous and shorter lines
" should trigger another autocommand as Vim has to make them visible.
call term_sendkeys(buf, "5zl2k")
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^8 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 5, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': -5, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Ensure the command was triggered for the specified window ID.
call term_sendkeys(buf, ":echo g:matched\<CR>")
call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000)
" Ensure the expansion of <amatch> and <afile> matches the window ID.
call term_sendkeys(buf, ":echo g:amatch == win_id && g:afile == win_id\<CR>")
call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000)
call delete('XscrollEvent')
call StopVimInTerminal(buf)
endfunc
func Test_WinScrolled_mouse()
CheckRunVimInTerminal
let lines =<< trim END
set nowrap scrolloff=0
set mouse=a term=xterm ttymouse=sgr mousetime=200 clipboard=
call setline(1, ['foo']->repeat(32))
split
let g:scrolled = 0
au WinScrolled * let g:scrolled += 1
END
call writefile(lines, 'Xtest_winscrolled_mouse', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled_mouse', {'rows': 10})
" With the upper split focused, send a scroll-down event to the unfocused one.
call test_setmouse(7, 1)
call term_sendkeys(buf, "\<ScrollWheelDown>")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^1', term_getline(buf, 10))}, 1000)
" Again, but this time while we're in insert mode.
call term_sendkeys(buf, "i\<ScrollWheelDown>\<Esc>")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^2', term_getline(buf, 10))}, 1000)
call StopVimInTerminal(buf)
endfunc
func Test_WinScrolled_close_curwin()
CheckRunVimInTerminal
let lines =<< trim END
set nowrap scrolloff=0
call setline(1, ['aaa', 'bbb'])
vsplit
au WinScrolled * close
au VimLeave * call writefile(['123456'], 'Xtestout')
END
call writefile(lines, 'Xtest_winscrolled_close_curwin', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled_close_curwin', {'rows': 6})
" This was using freed memory
call term_sendkeys(buf, "\<C-E>")
call TermWait(buf)
call StopVimInTerminal(buf)
" check the startup script finished to the end
call assert_equal(['123456'], readfile('Xtestout'))
call delete('Xtestout')
endfunc
func Test_WinScrolled_once_only()
CheckRunVimInTerminal
let lines =<< trim END
set cmdheight=2
call setline(1, ['aaa', 'bbb'])
let trigger_count = 0
func ShowInfo(id)
echo g:trigger_count g:winid winlayout()
endfunc
vsplit
split
" use a timer to show the info after a redraw
au WinScrolled * let trigger_count += 1 | let winid = expand('<amatch>') | call timer_start(100, 'ShowInfo')
wincmd j
wincmd l
END
call writefile(lines, 'Xtest_winscrolled_once', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled_once', #{rows: 10, cols: 60, statusoff: 2})
call term_sendkeys(buf, "\<C-E>")
call VerifyScreenDump(buf, 'Test_winscrolled_once_only_1', {})
call StopVimInTerminal(buf)
endfunc
" Check that WinScrolled is not triggered immediately when defined and there
" are split windows.
func Test_WinScrolled_not_when_defined()
CheckRunVimInTerminal
let lines =<< trim END
call setline(1, ['aaa', 'bbb'])
echo 'nothing happened'
func ShowTriggered(id)
echo 'triggered'
endfunc
END
call writefile(lines, 'Xtest_winscrolled_not', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled_not', #{rows: 10, cols: 60, statusoff: 2})
call term_sendkeys(buf, ":split\<CR>")
call TermWait(buf)
" use a timer to show the message after redrawing
call term_sendkeys(buf, ":au WinScrolled * call timer_start(100, 'ShowTriggered')\<CR>")
call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_1', {})
call term_sendkeys(buf, "\<C-E>")
call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_2', {})
call StopVimInTerminal(buf)
endfunc
func Test_WinScrolled_long_wrapped()
CheckRunVimInTerminal
let lines =<< trim END
set scrolloff=0
let height = winheight(0)
let width = winwidth(0)
let g:scrolled = 0
au WinScrolled * let g:scrolled += 1
call setline(1, repeat('foo', height * width))
call cursor(1, height * width)
END
call writefile(lines, 'Xtest_winscrolled_long_wrapped', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled_long_wrapped', {'rows': 6})
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000)
call term_sendkeys(buf, 'gj')
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^1 ', term_getline(buf, 6))}, 1000)
call term_sendkeys(buf, '0')
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000)
call term_sendkeys(buf, '$')
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^3 ', term_getline(buf, 6))}, 1000)
call StopVimInTerminal(buf)
endfunc
func Test_WinScrolled_diff()
CheckRunVimInTerminal
let lines =<< trim END
set diffopt+=foldcolumn:0
call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
vnew
call setline(1, ['d', 'e', 'f', 'g', 'h', 'i'])
windo diffthis
func WriteScrollEvent()
call writefile([json_encode(v:event)], 'XscrollEvent')
endfunc
au WinScrolled * call WriteScrollEvent()
END
call writefile(lines, 'Xtest_winscrolled_diff', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled_diff', {'rows': 8})
call term_sendkeys(buf, "\<C-E>")
call WaitForAssert({-> assert_match('^d', term_getline(buf, 3))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1001': {'leftcol': 0, 'topline': 0, 'topfill': -1, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
call term_sendkeys(buf, "2\<C-E>")
call WaitForAssert({-> assert_match('^f', term_getline(buf, 3))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 2, 'topfill': 2, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': 2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1001': {'leftcol': 0, 'topline': 0, 'topfill': -2, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
call term_sendkeys(buf, "\<C-E>")
call WaitForAssert({-> assert_match('^g', term_getline(buf, 3))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1001': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
call term_sendkeys(buf, "2\<C-Y>")
call WaitForAssert({-> assert_match('^e', term_getline(buf, 3))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 3, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': -2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1001': {'leftcol': 0, 'topline': -1, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
call StopVimInTerminal(buf)
call delete('XscrollEvent')
endfunc
func Test_WinClosed()
" Test that the pattern is matched against the closed window's ID, and both
" <amatch> and <afile> are set to it.
new
let winid = win_getid()
let g:matched = v:false
augroup test-WinClosed
autocmd!
execute 'autocmd WinClosed' winid 'let g:matched = v:true'
autocmd WinClosed * let g:amatch = str2nr(expand('<amatch>'))
autocmd WinClosed * let g:afile = str2nr(expand('<afile>'))
augroup END
close
call assert_true(g:matched)
call assert_equal(winid, g:amatch)
call assert_equal(winid, g:afile)
" Test that WinClosed is non-recursive.
new
new
call assert_equal(3, winnr('$'))
let g:triggered = 0
augroup test-WinClosed
autocmd!
autocmd WinClosed * let g:triggered += 1
autocmd WinClosed * 2 wincmd c
augroup END
close
call assert_equal(1, winnr('$'))
call assert_equal(1, g:triggered)
autocmd! test-WinClosed
augroup! test-WinClosed
unlet g:matched
unlet g:amatch
unlet g:afile
unlet g:triggered
endfunc
func Test_WinClosed_throws()
vnew
let bnr = bufnr()
call assert_equal(1, bufloaded(bnr))
augroup test-WinClosed
autocmd WinClosed * throw 'foo'
augroup END
try
close
catch /.*/
endtry
call assert_equal(0, bufloaded(bnr))
autocmd! test-WinClosed
augroup! test-WinClosed
endfunc
func Test_WinClosed_throws_with_tabs()
tabnew
let bnr = bufnr()
call assert_equal(1, bufloaded(bnr))
augroup test-WinClosed
autocmd WinClosed * throw 'foo'
augroup END
try
close
catch /.*/
endtry
call assert_equal(0, bufloaded(bnr))
autocmd! test-WinClosed
augroup! test-WinClosed
endfunc
" This used to trigger WinClosed twice for the same window, and the window's
" buffer was NULL in the second autocommand.
func Test_WinClosed_switch_tab()
edit Xa
split Xb
split Xc
tab split
new
augroup test-WinClosed
autocmd WinClosed * tabprev | bwipe!
augroup END
close
" Check that the tabline has been fully removed
call assert_equal([1, 1], win_screenpos(0))
autocmd! test-WinClosed
augroup! test-WinClosed
%bwipe!
endfunc
func s:AddAnAutocmd()
augroup vimBarTest
au BufReadCmd * echo 'hello'
augroup END
call assert_equal(3, len(split(execute('au vimBarTest'), "\n")))
endfunc
func Test_early_bar()
" test that a bar is recognized before the {event}
call s:AddAnAutocmd()
augroup vimBarTest | au! | let done = 77 | augroup END
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
call assert_equal(77, done)
call s:AddAnAutocmd()
augroup vimBarTest| au!| let done = 88 | augroup END
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
call assert_equal(88, done)
" test that a bar is recognized after the {event}
call s:AddAnAutocmd()
augroup vimBarTest| au!BufReadCmd| let done = 99 | augroup END
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
call assert_equal(99, done)
" test that a bar is recognized after the {group}
call s:AddAnAutocmd()
au! vimBarTest|echo 'hello'
call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
endfunc
func RemoveGroup()
autocmd! StartOK
augroup! StartOK
endfunc
func Test_augroup_warning()
augroup TheWarning
au VimEnter * echo 'entering'
augroup END
call assert_match("TheWarning.*VimEnter", execute('au VimEnter'))
redir => res
augroup! TheWarning
redir END
call assert_match("W19:", res)
call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
" check "Another" does not take the pace of the deleted entry
augroup Another
augroup END
call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
augroup! Another
" no warning for postpone aucmd delete
augroup StartOK
au VimEnter * call RemoveGroup()
augroup END
call assert_match("StartOK.*VimEnter", execute('au VimEnter'))
redir => res
doautocmd VimEnter
redir END
call assert_notmatch("W19:", res)
au! VimEnter
call assert_fails('augroup!', 'E471:')
endfunc
func Test_BufReadCmdHelp()
" This used to cause access to free memory
au BufReadCmd * e +h
help
au! BufReadCmd
endfunc
func Test_BufReadCmdHelpJump()
" This used to cause access to free memory
au BufReadCmd * e +h{
2018-08-14 15:19:56 -07:00
" } to fix highlighting
call assert_fails('help', 'E434:')
au! BufReadCmd
endfunc
" BufReadCmd is triggered for a "nofile" buffer. Check all values.
func Test_BufReadCmdNofile()
for val in ['nofile',
\ 'nowrite',
\ 'acwrite',
\ 'quickfix',
\ 'help',
"\ 'terminal',
\ 'prompt',
"\ 'popup',
\ ]
new somefile
exe 'set buftype=' .. val
au BufReadCmd somefile call setline(1, 'triggered')
edit
call assert_equal('triggered', getline(1))
au! BufReadCmd
bwipe!
endfor
endfunc
func Test_augroup_deleted()
" This caused a crash before E936 was introduced
augroup x
call assert_fails('augroup! x', 'E936:')
au VimEnter * echo
augroup end
augroup! x
call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
au! VimEnter
endfunc
" Tests for autocommands on :close command.
" This used to be in test13.
func Test_three_windows()
" Clean up buffers, because in some cases this function fails.
call s:cleanup_buffers()
" Write three files and open them, each in a window.
" Then go to next window, with autocommand that deletes the previous one.
" Do this twice, writing the file.
e! Xtestje1
call setline(1, 'testje1')
w
sp Xtestje2
call setline(1, 'testje2')
w
sp Xtestje3
call setline(1, 'testje3')
w
wincmd w
au WinLeave Xtestje2 bwipe
wincmd w
call assert_equal('Xtestje1', expand('%'))
au WinLeave Xtestje1 bwipe Xtestje3
close
call assert_equal('Xtestje1', expand('%'))
" Test deleting the buffer on a Unload event. If this goes wrong there
" will be the ATTENTION prompt.
e Xtestje1
au!
au! BufUnload Xtestje1 bwipe
call assert_fails('e Xtestje3', 'E937:')
call assert_equal('Xtestje3', expand('%'))
e Xtestje2
sp Xtestje1
call assert_fails('e', 'E937:')
call assert_equal('Xtestje1', expand('%'))
" Test changing buffers in a BufWipeout autocommand. If this goes wrong
" there are ml_line errors and/or a Crash.
au!
only
e Xanother
e Xtestje1
bwipe Xtestje2
bwipe Xtestje3
au BufWipeout Xtestje1 buf Xtestje1
bwipe
call assert_equal('Xanother', expand('%'))
only
help
wincmd w
1quit
call assert_equal('Xanother', expand('%'))
au!
enew
call delete('Xtestje1')
call delete('Xtestje2')
call delete('Xtestje3')
endfunc
func Test_BufEnter()
au! BufEnter
au Bufenter * let val = val . '+'
let g:val = ''
split NewFile
call assert_equal('+', g:val)
bwipe!
call assert_equal('++', g:val)
" Also get BufEnter when editing a directory
call mkdir('Xdir')
split Xdir
call assert_equal('+++', g:val)
" On MS-Windows we can't edit the directory, make sure we wipe the right
" buffer.
bwipe! Xdir
call delete('Xdir', 'd')
au! BufEnter
" Editing a "nofile" buffer doesn't read the file but does trigger BufEnter
" for historic reasons. Also test other 'buftype' values.
for val in ['nofile',
\ 'nowrite',
\ 'acwrite',
\ 'quickfix',
\ 'help',
"\ 'terminal',
\ 'prompt',
"\ 'popup',
\ ]
new somefile
exe 'set buftype=' .. val
au BufEnter somefile call setline(1, 'some text')
edit
call assert_equal('some text', getline(1))
bwipe!
au! BufEnter
endfor
endfunc
" Closing a window might cause an endless loop
" E814 for older Vims
func Test_autocmd_bufwipe_in_SessLoadPost()
edit Xtest
tabnew
file Xsomething
set noswapfile
mksession!
let content =<< trim [CODE]
set nocp noswapfile
let v:swapchoice = "e"
augroup test_autocmd_sessionload
autocmd!
autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!"
augroup END
func WriteErrors()
call writefile([execute("messages")], "Xerrors")
endfunc
au VimLeave * call WriteErrors()
[CODE]
call writefile(content, 'Xvimrc')
call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq')
let errors = join(readfile('Xerrors'))
call assert_match('E814', errors)
set swapfile
for file in ['Session.vim', 'Xvimrc', 'Xerrors']
call delete(file)
endfor
endfunc
" Using :blast and :ball for many events caused a crash, because b_nwindows was
" not incremented correctly.
func Test_autocmd_blast_badd()
let content =<< trim [CODE]
au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* blast
edit foo1
au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* ball
edit foo2
call writefile(['OK'], 'Xerrors')
qall
[CODE]
call writefile(content, 'XblastBall')
call system(GetVimCommand() .. ' --clean -S XblastBall')
call assert_match('OK', readfile('Xerrors')->join())
call delete('XblastBall')
call delete('Xerrors')
endfunc
" SEGV occurs in older versions.
func Test_autocmd_bufwipe_in_SessLoadPost2()
tabnew
set noswapfile
mksession!
let content =<< trim [CODE]
set nocp noswapfile
function! DeleteInactiveBufs()
tabfirst
let tabblist = []
for i in range(1, tabpagenr(''$''))
call extend(tabblist, tabpagebuflist(i))
endfor
for b in range(1, bufnr(''$''))
if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')
exec ''bwipeout '' . b
endif
endfor
echomsg "SessionLoadPost DONE"
endfunction
au SessionLoadPost * call DeleteInactiveBufs()
func WriteErrors()
call writefile([execute("messages")], "Xerrors")
endfunc
au VimLeave * call WriteErrors()
[CODE]
call writefile(content, 'Xvimrc')
call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq')
let errors = join(readfile('Xerrors'))
" This probably only ever matches on unix.
call assert_notmatch('Caught deadly signal SEGV', errors)
call assert_match('SessionLoadPost DONE', errors)
set swapfile
for file in ['Session.vim', 'Xvimrc', 'Xerrors']
call delete(file)
endfor
endfunc
func Test_empty_doau()
doau \|
endfunc
func s:AutoCommandOptionSet(match)
let template = "Option: <%s>, OldVal: <%s>, OldValLocal: <%s>, OldValGlobal: <%s>, NewVal: <%s>, Scope: <%s>, Command: <%s>\n"
let item = remove(g:options, 0)
let expected = printf(template, item[0], item[1], item[2], item[3], item[4], item[5], item[6])
let actual = printf(template, a:match, v:option_old, v:option_oldlocal, v:option_oldglobal, v:option_new, v:option_type, v:option_command)
let g:opt = [expected, actual]
"call assert_equal(expected, actual)
endfunc
func Test_OptionSet()
CheckFunction test_override
CheckOption autochdir
call test_override('starting', 1)
set nocp
au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>"))
" 1: Setting number option"
let g:options = [['number', 0, 0, 0, 1, 'global', 'set']]
set nu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 2: Setting local number option"
let g:options = [['number', 1, 1, '', 0, 'local', 'setlocal']]
setlocal nonu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 3: Setting global number option"
let g:options = [['number', 1, '', 1, 0, 'global', 'setglobal']]
setglobal nonu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 4: Setting local autoindent option"
let g:options = [['autoindent', 0, 0, '', 1, 'local', 'setlocal']]
setlocal ai
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 5: Setting global autoindent option"
let g:options = [['autoindent', 0, '', 0, 1, 'global', 'setglobal']]
setglobal ai
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 6: Setting global autoindent option"
let g:options = [['autoindent', 1, 1, 1, 0, 'global', 'set']]
set ai!
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 6a: Setting global autoindent option"
let g:options = [['autoindent', 1, 1, 0, 0, 'global', 'set']]
noa setlocal ai
noa setglobal noai
set ai!
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" Should not print anything, use :noa
" 7: don't trigger OptionSet"
let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
noa set nonu
call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 8: Setting several global list and number option"
let g:options = [['list', 0, 0, 0, 1, 'global', 'set'], ['number', 0, 0, 0, 1, 'global', 'set']]
set list nu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 9: don't trigger OptionSet"
let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
noa set nolist nonu
call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 10: Setting global acd"
let g:options = [['autochdir', 0, 0, '', 1, 'local', 'setlocal']]
setlocal acd
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 11: Setting global autoread (also sets local value)"
let g:options = [['autoread', 0, 0, 0, 1, 'global', 'set']]
set ar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 12: Setting local autoread"
let g:options = [['autoread', 1, 1, '', 1, 'local', 'setlocal']]
setlocal ar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 13: Setting global autoread"
let g:options = [['autoread', 1, '', 1, 0, 'global', 'setglobal']]
setglobal invar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 14: Setting option backspace through :let"
let g:options = [['backspace', '', '', '', 'eol,indent,start', 'global', 'set']]
let &bs = "eol,indent,start"
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 15: Setting option backspace through setbufvar()"
let g:options = [['backup', 0, 0, '', 1, 'local', 'setlocal']]
" try twice, first time, shouldn't trigger because option name is invalid,
" second time, it should trigger
let bnum = bufnr('%')
call assert_fails("call setbufvar(bnum, '&l:bk', 1)", 'E355:')
" should trigger, use correct option name
call setbufvar(bnum, '&backup', 1)
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 16: Setting number option using setwinvar"
let g:options = [['number', 0, 0, '', 1, 'local', 'setlocal']]
call setwinvar(0, '&number', 1)
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 17: Setting key option, shouldn't trigger"
let g:options = [['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']]
setlocal key=blah
setlocal key=
call assert_equal([['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 18a: Setting string global option"
let oldval = &backupext
let g:options = [['backupext', oldval, oldval, oldval, 'foo', 'global', 'set']]
set backupext=foo
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 18b: Resetting string global option"
let g:options = [['backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
set backupext&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 18c: Setting global string global option"
let g:options = [['backupext', oldval, '', oldval, 'bar', 'global', 'setglobal']]
setglobal backupext=bar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 18d: Setting local string global option"
" As this is a global option this sets the global value even though
" :setlocal is used!
noa set backupext& " Reset global and local value (without triggering autocmd)
let g:options = [['backupext', oldval, oldval, '', 'baz', 'local', 'setlocal']]
setlocal backupext=baz
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 18e: Setting again string global option"
noa setglobal backupext=ext_global " Reset global and local value (without triggering autocmd)
noa setlocal backupext=ext_local " Sets the global(!) value!
let g:options = [['backupext', 'ext_local', 'ext_local', 'ext_local', 'fuu', 'global', 'set']]
set backupext=fuu
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19a: Setting string global-local (to buffer) option"
let oldval = &tags
let g:options = [['tags', oldval, oldval, oldval, 'tagpath', 'global', 'set']]
set tags=tagpath
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19b: Resetting string global-local (to buffer) option"
let g:options = [['tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set']]
set tags&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19c: Setting global string global-local (to buffer) option "
let g:options = [['tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal']]
setglobal tags=tagpath1
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19d: Setting local string global-local (to buffer) option"
let g:options = [['tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal']]
setlocal tags=tagpath2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19e: Setting again string global-local (to buffer) option"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa setglobal tags=tag_global " Reset global and local value (without triggering autocmd)
noa setlocal tags=tag_local
let g:options = [['tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set']]
set tags=tagpath
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 19f: Setting string global-local (to buffer) option to an empty string"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa set tags=tag_global " Reset global and local value (without triggering autocmd)
noa setlocal tags= " empty string
let g:options = [['tags', 'tag_global', '', 'tag_global', 'tagpath', 'global', 'set']]
set tags=tagpath
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 20a: Setting string local (to buffer) option"
let oldval = &spelllang
let g:options = [['spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set']]
set spelllang=elvish,klingon
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 20b: Resetting string local (to buffer) option"
let g:options = [['spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set']]
set spelllang&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 20c: Setting global string local (to buffer) option"
let g:options = [['spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal']]
setglobal spelllang=elvish
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 20d: Setting local string local (to buffer) option"
noa set spelllang& " Reset global and local value (without triggering autocmd)
let g:options = [['spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal']]
setlocal spelllang=klingon
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 20e: Setting again string local (to buffer) option"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa setglobal spelllang=spellglobal " Reset global and local value (without triggering autocmd)
noa setlocal spelllang=spelllocal
let g:options = [['spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set']]
set spelllang=foo
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21a: Setting string global-local (to window) option"
let oldval = &statusline
let g:options = [['statusline', oldval, oldval, oldval, 'foo', 'global', 'set']]
set statusline=foo
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21b: Resetting string global-local (to window) option"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
let g:options = [['statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
set statusline&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21c: Setting global string global-local (to window) option"
let g:options = [['statusline', oldval, '', oldval, 'bar', 'global', 'setglobal']]
setglobal statusline=bar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21d: Setting local string global-local (to window) option"
noa set statusline& " Reset global and local value (without triggering autocmd)
let g:options = [['statusline', oldval, oldval, '', 'baz', 'local', 'setlocal']]
setlocal statusline=baz
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 21e: Setting again string global-local (to window) option"
" Note: v:option_old is the old global value for global-local string options
" but the old local value for all other kinds of options.
noa setglobal statusline=bar " Reset global and local value (without triggering autocmd)
noa setlocal statusline=baz
let g:options = [['statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set']]
set statusline=foo
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 22a: Setting string local (to window) option"
let oldval = &foldignore
let g:options = [['foldignore', oldval, oldval, oldval, 'fo', 'global', 'set']]
set foldignore=fo
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 22b: Resetting string local (to window) option"
let g:options = [['foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set']]
set foldignore&
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 22c: Setting global string local (to window) option"
let g:options = [['foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal']]
setglobal foldignore=bar
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 22d: Setting local string local (to window) option"
noa set foldignore& " Reset global and local value (without triggering autocmd)
let g:options = [['foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal']]
setlocal foldignore=baz
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 22e: Setting again string local (to window) option"
noa setglobal foldignore=glob " Reset global and local value (without triggering autocmd)
noa setlocal foldignore=loc
let g:options = [['foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set']]
set foldignore=fo
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 23a: Setting global number global option"
noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
noa setlocal cmdheight=1 " Sets the global(!) value!
let g:options = [['cmdheight', '1', '', '1', '2', 'global', 'setglobal']]
setglobal cmdheight=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 23b: Setting local number global option"
noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
noa setlocal cmdheight=1 " Sets the global(!) value!
let g:options = [['cmdheight', '1', '1', '', '2', 'local', 'setlocal']]
setlocal cmdheight=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 23c: Setting again number global option"
noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
noa setlocal cmdheight=1 " Sets the global(!) value!
let g:options = [['cmdheight', '1', '1', '1', '2', 'global', 'set']]
set cmdheight=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 23d: Setting again number global option"
noa set cmdheight=8 " Reset global and local value (without triggering autocmd)
let g:options = [['cmdheight', '8', '8', '8', '2', 'global', 'set']]
set cmdheight=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 24a: Setting global number global-local (to buffer) option"
noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
noa setlocal undolevels=1
let g:options = [['undolevels', '8', '', '8', '2', 'global', 'setglobal']]
setglobal undolevels=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 24b: Setting local number global-local (to buffer) option"
noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
noa setlocal undolevels=1
let g:options = [['undolevels', '1', '1', '', '2', 'local', 'setlocal']]
setlocal undolevels=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 24c: Setting again number global-local (to buffer) option"
noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
noa setlocal undolevels=1
let g:options = [['undolevels', '1', '1', '8', '2', 'global', 'set']]
set undolevels=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 24d: Setting again global number global-local (to buffer) option"
noa set undolevels=8 " Reset global and local value (without triggering autocmd)
let g:options = [['undolevels', '8', '8', '8', '2', 'global', 'set']]
set undolevels=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 25a: Setting global number local (to buffer) option"
noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
noa setlocal wrapmargin=1
let g:options = [['wrapmargin', '8', '', '8', '2', 'global', 'setglobal']]
setglobal wrapmargin=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 25b: Setting local number local (to buffer) option"
noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
noa setlocal wrapmargin=1
let g:options = [['wrapmargin', '1', '1', '', '2', 'local', 'setlocal']]
setlocal wrapmargin=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 25c: Setting again number local (to buffer) option"
noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
noa setlocal wrapmargin=1
let g:options = [['wrapmargin', '1', '1', '8', '2', 'global', 'set']]
set wrapmargin=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 25d: Setting again global number local (to buffer) option"
noa set wrapmargin=8 " Reset global and local value (without triggering autocmd)
let g:options = [['wrapmargin', '8', '8', '8', '2', 'global', 'set']]
set wrapmargin=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 26: Setting number global-local (to window) option.
" Such option does currently not exist.
" 27a: Setting global number local (to window) option"
noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
noa setlocal foldcolumn=1
let g:options = [['foldcolumn', '8', '', '8', '2', 'global', 'setglobal']]
setglobal foldcolumn=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 27b: Setting local number local (to window) option"
noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
noa setlocal foldcolumn=1
let g:options = [['foldcolumn', '1', '1', '', '2', 'local', 'setlocal']]
setlocal foldcolumn=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 27c: Setting again number local (to window) option"
noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
noa setlocal foldcolumn=1
let g:options = [['foldcolumn', '1', '1', '8', '2', 'global', 'set']]
set foldcolumn=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 27d: Setting again global number local (to window) option"
noa set foldcolumn=8 " Reset global and local value (without triggering autocmd)
let g:options = [['foldcolumn', '8', '8', '8', '2', 'global', 'set']]
set foldcolumn=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 28a: Setting global boolean global option"
noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
noa setlocal wrapscan " Sets the global(!) value!
let g:options = [['wrapscan', '1', '', '1', '0', 'global', 'setglobal']]
setglobal nowrapscan
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 28b: Setting local boolean global option"
noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
noa setlocal wrapscan " Sets the global(!) value!
let g:options = [['wrapscan', '1', '1', '', '0', 'local', 'setlocal']]
setlocal nowrapscan
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 28c: Setting again boolean global option"
noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
noa setlocal wrapscan " Sets the global(!) value!
let g:options = [['wrapscan', '1', '1', '1', '0', 'global', 'set']]
set nowrapscan
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 28d: Setting again global boolean global option"
noa set nowrapscan " Reset global and local value (without triggering autocmd)
let g:options = [['wrapscan', '0', '0', '0', '1', 'global', 'set']]
set wrapscan
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 29a: Setting global boolean global-local (to buffer) option"
noa setglobal noautoread " Reset global and local value (without triggering autocmd)
noa setlocal autoread
let g:options = [['autoread', '0', '', '0', '1', 'global', 'setglobal']]
setglobal autoread
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 29b: Setting local boolean global-local (to buffer) option"
noa setglobal noautoread " Reset global and local value (without triggering autocmd)
noa setlocal autoread
let g:options = [['autoread', '1', '1', '', '0', 'local', 'setlocal']]
setlocal noautoread
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 29c: Setting again boolean global-local (to buffer) option"
noa setglobal noautoread " Reset global and local value (without triggering autocmd)
noa setlocal autoread
let g:options = [['autoread', '1', '1', '0', '1', 'global', 'set']]
set autoread
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 29d: Setting again global boolean global-local (to buffer) option"
noa set noautoread " Reset global and local value (without triggering autocmd)
let g:options = [['autoread', '0', '0', '0', '1', 'global', 'set']]
set autoread
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 30a: Setting global boolean local (to buffer) option"
noa setglobal nocindent " Reset global and local value (without triggering autocmd)
noa setlocal cindent
let g:options = [['cindent', '0', '', '0', '1', 'global', 'setglobal']]
setglobal cindent
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 30b: Setting local boolean local (to buffer) option"
noa setglobal nocindent " Reset global and local value (without triggering autocmd)
noa setlocal cindent
let g:options = [['cindent', '1', '1', '', '0', 'local', 'setlocal']]
setlocal nocindent
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 30c: Setting again boolean local (to buffer) option"
noa setglobal nocindent " Reset global and local value (without triggering autocmd)
noa setlocal cindent
let g:options = [['cindent', '1', '1', '0', '1', 'global', 'set']]
set cindent
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 30d: Setting again global boolean local (to buffer) option"
noa set nocindent " Reset global and local value (without triggering autocmd)
let g:options = [['cindent', '0', '0', '0', '1', 'global', 'set']]
set cindent
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 31: Setting boolean global-local (to window) option
" Currently no such option exists.
" 32a: Setting global boolean local (to window) option"
noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
noa setlocal cursorcolumn
let g:options = [['cursorcolumn', '0', '', '0', '1', 'global', 'setglobal']]
setglobal cursorcolumn
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 32b: Setting local boolean local (to window) option"
noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
noa setlocal cursorcolumn
let g:options = [['cursorcolumn', '1', '1', '', '0', 'local', 'setlocal']]
setlocal nocursorcolumn
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 32c: Setting again boolean local (to window) option"
noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
noa setlocal cursorcolumn
let g:options = [['cursorcolumn', '1', '1', '0', '1', 'global', 'set']]
set cursorcolumn
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 32d: Setting again global boolean local (to window) option"
noa set nocursorcolumn " Reset global and local value (without triggering autocmd)
let g:options = [['cursorcolumn', '0', '0', '0', '1', 'global', 'set']]
set cursorcolumn
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" 33: Test autocommands when an option value is converted internally.
noa set backspace=1 " Reset global and local value (without triggering autocmd)
let g:options = [['backspace', 'indent,eol', 'indent,eol', 'indent,eol', '2', 'global', 'set']]
set backspace=2
call assert_equal([], g:options)
call assert_equal(g:opt[0], g:opt[1])
" Cleanup
au! OptionSet
" set tags&
for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp', 'backupext', 'tags', 'spelllang', 'statusline', 'foldignore', 'cmdheight', 'undolevels', 'wrapmargin', 'foldcolumn', 'wrapscan', 'autoread', 'cindent', 'cursorcolumn']
exe printf(":set %s&vim", opt)
endfor
call test_override('starting', 0)
delfunc! AutoCommandOptionSet
endfunc
func Test_OptionSet_diffmode()
CheckFunction test_override
call test_override('starting', 1)
" 18: Changing an option when entering diff mode
new
au OptionSet diff :let &l:cul = v:option_new
call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
call assert_equal(0, &l:cul)
diffthis
call assert_equal(1, &l:cul)
vnew
call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
call assert_equal(0, &l:cul)
diffthis
call assert_equal(1, &l:cul)
diffoff
call assert_equal(0, &l:cul)
call assert_equal(1, getwinvar(2, '&l:cul'))
bw!
call assert_equal(1, &l:cul)
diffoff!
call assert_equal(0, &l:cul)
call assert_equal(0, getwinvar(1, '&l:cul'))
bw!
" Cleanup
au! OptionSet
call test_override('starting', 0)
endfunc
func Test_OptionSet_diffmode_close()
CheckFunction test_override
call test_override('starting', 1)
" 19: Try to close the current window when entering diff mode
" should not segfault
new
au OptionSet diff close
call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
call assert_fails(':diffthis', 'E788')
call assert_equal(1, &diff)
vnew
call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
call assert_fails(':diffthis', 'E788')
call assert_equal(1, &diff)
set diffopt-=closeoff
bw!
call assert_fails(':diffoff!', 'E788')
bw!
" Cleanup
au! OptionSet
call test_override('starting', 0)
"delfunc! AutoCommandOptionSet
endfunc
" Test for Bufleave autocommand that deletes the buffer we are about to edit.
func Test_BufleaveWithDelete()
new | edit Xfile1
augroup test_bufleavewithdelete
autocmd!
autocmd BufLeave Xfile1 bwipe Xfile2
augroup END
call assert_fails('edit Xfile2', 'E143:')
call assert_equal('Xfile1', bufname('%'))
autocmd! test_bufleavewithdelete BufLeave Xfile1
augroup! test_bufleavewithdelete
new
bwipe! Xfile1
endfunc
" Test for autocommand that changes the buffer list, when doing ":ball".
func Test_Acmd_BufAll()
enew!
%bwipe!
call writefile(['Test file Xxx1'], 'Xxx1')
call writefile(['Test file Xxx2'], 'Xxx2')
call writefile(['Test file Xxx3'], 'Xxx3')
" Add three files to the buffer list
split Xxx1
close
split Xxx2
close
split Xxx3
close
" Wipe the buffer when the buffer is opened
au BufReadPost Xxx2 bwipe
call append(0, 'Test file Xxx4')
ball
call assert_equal(2, winnr('$'))
call assert_equal('Xxx1', bufname(winbufnr(winnr('$'))))
wincmd t
au! BufReadPost
%bwipe!
call delete('Xxx1')
call delete('Xxx2')
call delete('Xxx3')
enew! | only
endfunc
" Test for autocommand that changes current buffer on BufEnter event.
" Check if modelines are interpreted for the correct buffer.
func Test_Acmd_BufEnter()
%bwipe!
call writefile(['start of test file Xxx1',
\ "\<Tab>this is a test",
\ 'end of test file Xxx1'], 'Xxx1')
call writefile(['start of test file Xxx2',
\ 'vim: set noai :',
\ "\<Tab>this is a test",
\ 'end of test file Xxx2'], 'Xxx2')
au BufEnter Xxx2 brew
set ai modeline modelines=3
edit Xxx1
" edit Xxx2, autocmd will do :brew
edit Xxx2
exe "normal G?this is a\<CR>"
" Append text with autoindent to this file
normal othis should be auto-indented
call assert_equal("\<Tab>this should be auto-indented", getline('.'))
call assert_equal(3, line('.'))
" Remove autocmd and edit Xxx2 again
au! BufEnter Xxx2
buf! Xxx2
exe "normal G?this is a\<CR>"
" append text without autoindent to Xxx
normal othis should be in column 1
call assert_equal("this should be in column 1", getline('.'))
call assert_equal(4, line('.'))
%bwipe!
call delete('Xxx1')
call delete('Xxx2')
set ai&vim modeline&vim modelines&vim
endfunc
" Test for issue #57
" do not move cursor on <c-o> when autoindent is set
func Test_ai_CTRL_O()
enew!
set ai
let save_fo = &fo
set fo+=r
exe "normal o# abcdef\<Esc>2hi\<CR>\<C-O>d0\<Esc>"
exe "normal o# abcdef\<Esc>2hi\<C-O>d0\<Esc>"
call assert_equal(['# abc', 'def', 'def'], getline(2, 4))
set ai&vim
let &fo = save_fo
enew!
endfunc
" Test for autocommand that deletes the current buffer on BufLeave event.
" Also test deleting the last buffer, should give a new, empty buffer.
func Test_BufLeave_Wipe()
%bwipe!
let content = ['start of test file Xxx',
\ 'this is a test',
\ 'end of test file Xxx']
call writefile(content, 'Xxx1')
call writefile(content, 'Xxx2')
au BufLeave Xxx2 bwipe
edit Xxx1
split Xxx2
" delete buffer Xxx2, we should be back to Xxx1
bwipe
call assert_equal('Xxx1', bufname('%'))
call assert_equal(1, winnr('$'))
" Create an alternate buffer
%write! test.out
call assert_equal('test.out', bufname('#'))
" delete alternate buffer
bwipe test.out
call assert_equal('Xxx1', bufname('%'))
call assert_equal('', bufname('#'))
au BufLeave Xxx1 bwipe
" delete current buffer, get an empty one
bwipe!
call assert_equal(1, line('$'))
call assert_equal('', bufname('%'))
let g:bufinfo = getbufinfo()
call assert_equal(1, len(g:bufinfo))
call delete('Xxx1')
call delete('Xxx2')
call delete('test.out')
%bwipe
au! BufLeave
" check that bufinfo doesn't contain a pointer to freed memory
call test_garbagecollect_now()
endfunc
func Test_QuitPre()
edit Xfoo
let winid = win_getid(winnr())
split Xbar
au! QuitPre * let g:afile = expand('<afile>')
" Close the other window, <afile> should be correct.
exe win_id2win(winid) . 'q'
call assert_equal('Xfoo', g:afile)
unlet g:afile
bwipe Xfoo
bwipe Xbar
endfunc
func Test_Cmdline()
au! CmdlineChanged : let g:text = getcmdline()
let g:text = 0
call feedkeys(":echom 'hello'\<CR>", 'xt')
call assert_equal("echom 'hello'", g:text)
au! CmdlineChanged
au! CmdlineChanged : let g:entered = expand('<afile>')
let g:entered = 0
call feedkeys(":echom 'hello'\<CR>", 'xt')
call assert_equal(':', g:entered)
au! CmdlineChanged
autocmd CmdlineChanged : let g:log += [getcmdline()]
let g:log = []
cnoremap <F1> <Cmd>call setcmdline('ls')<CR>
call feedkeys(":\<F1>", 'xt')
call assert_equal(['ls'], g:log)
cunmap <F1>
let g:log = []
call feedkeys(":sign \<Tab>\<Tab>\<C-N>\<C-P>\<S-Tab>\<S-Tab>\<Esc>", 'xt')
call assert_equal([
\ 's',
\ 'si',
\ 'sig',
\ 'sign',
\ 'sign ',
\ 'sign define',
\ 'sign jump',
\ 'sign list',
\ 'sign jump',
\ 'sign define',
\ 'sign ',
\ ], g:log)
let g:log = []
set wildmenu wildoptions+=pum
call feedkeys(":sign \<S-Tab>\<PageUp>\<kPageUp>\<kPageDown>\<PageDown>\<Esc>", 'xt')
call assert_equal([
\ 's',
\ 'si',
\ 'sig',
\ 'sign',
\ 'sign ',
\ 'sign unplace',
\ 'sign jump',
\ 'sign define',
\ 'sign undefine',
\ 'sign unplace',
\ ], g:log)
set wildmenu& wildoptions&
let g:log = []
let @r = 'abc'
call feedkeys(":0\<C-R>r1\<C-R>\<C-O>r2\<C-R>\<C-R>r3\<Esc>", 'xt')
call assert_equal([
\ '0',
\ '0a',
\ '0ab',
\ '0abc',
\ '0abc1',
\ '0abc1abc',
\ '0abc1abc2',
\ '0abc1abc2abc',
\ '0abc1abc2abc3',
\ ], g:log)
unlet g:log
au! CmdlineChanged
au! CmdlineEnter : let g:entered = expand('<afile>')
au! CmdlineLeave : let g:left = expand('<afile>')
let g:entered = 0
let g:left = 0
call feedkeys(":echo 'hello'\<CR>", 'xt')
call assert_equal(':', g:entered)
call assert_equal(':', g:left)
au! CmdlineEnter
au! CmdlineLeave
let save_shellslash = &shellslash
set noshellslash
au! CmdlineEnter / let g:entered = expand('<afile>')
au! CmdlineLeave / let g:left = expand('<afile>')
let g:entered = 0
let g:left = 0
new
call setline(1, 'hello')
call feedkeys("/hello\<CR>", 'xt')
call assert_equal('/', g:entered)
call assert_equal('/', g:left)
bwipe!
au! CmdlineEnter
au! CmdlineLeave
let &shellslash = save_shellslash
endfunc
" Test for BufWritePre autocommand that deletes or unloads the buffer.
func Test_BufWritePre()
%bwipe
au BufWritePre Xxx1 bunload
au BufWritePre Xxx2 bwipe
call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1')
call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2')
edit Xtest
e! Xxx2
bdel Xtest
e Xxx1
" write it, will unload it and give an error msg
call assert_fails('w', 'E203')
call assert_equal('Xxx2', bufname('%'))
edit Xtest
e! Xxx2
bwipe Xtest
" write it, will delete the buffer and give an error msg
call assert_fails('w', 'E203')
call assert_equal('Xxx1', bufname('%'))
au! BufWritePre
call delete('Xxx1')
call delete('Xxx2')
endfunc
" Test for BufUnload autocommand that unloads all the other buffers
func Test_bufunload_all()
call writefile(['Test file Xxx1'], 'Xxx1')"
call writefile(['Test file Xxx2'], 'Xxx2')"
let content =<< trim [CODE]
func UnloadAllBufs()
let i = 1
while i <= bufnr('$')
if i != bufnr('%') && bufloaded(i)
exe i . 'bunload'
endif
let i += 1
endwhile
endfunc
au BufUnload * call UnloadAllBufs()
au VimLeave * call writefile(['Test Finished'], 'Xout')
set nohidden
edit Xxx1
split Xxx2
q
[CODE]
call writefile(content, 'Xtest')
call delete('Xout')
call system(GetVimCommandClean() .. ' -N --headless -S Xtest')
call assert_true(filereadable('Xout'))
call delete('Xxx1')
call delete('Xxx2')
call delete('Xtest')
call delete('Xout')
endfunc
" Some tests for buffer-local autocommands
func Test_buflocal_autocmd()
let g:bname = ''
edit xx
au BufLeave <buffer> let g:bname = expand("%")
" here, autocommand for xx should trigger.
" but autocommand shall not apply to buffer named <buffer>.
edit somefile
call assert_equal('xx', g:bname)
let g:bname = ''
" here, autocommand shall be auto-deleted
bwipe xx
" autocmd should not trigger
edit xx
call assert_equal('', g:bname)
" autocmd should not trigger
edit somefile
call assert_equal('', g:bname)
enew
unlet g:bname
endfunc
" Test for "*Cmd" autocommands
func Test_Cmd_Autocmds()
call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx')
enew!
au BufReadCmd XtestA 0r Xxx|$del
edit XtestA " will read text of Xxd instead
call assert_equal('start of Xxx', getline(1))
au BufWriteCmd XtestA call append(line("$"), "write")
write " will append a line to the file
call assert_equal('write', getline('$'))
call assert_fails('read XtestA', 'E484') " should not read anything
call assert_equal('write', getline(4))
" now we have:
" 1 start of Xxx
" 2 abc2
" 3 end of Xxx
" 4 write
au FileReadCmd XtestB '[r Xxx
2r XtestB " will read Xxx below line 2 instead
call assert_equal('start of Xxx', getline(3))
" now we have:
" 1 start of Xxx
" 2 abc2
" 3 start of Xxx
" 4 abc2
" 5 end of Xxx
" 6 end of Xxx
" 7 write
au FileWriteCmd XtestC '[,']copy $
normal 4GA1
4,5w XtestC " will copy lines 4 and 5 to the end
call assert_equal("\tabc21", getline(8))
call assert_fails('r XtestC', 'E484') " should not read anything
call assert_equal("end of Xxx", getline(9))
" now we have:
" 1 start of Xxx
" 2 abc2
" 3 start of Xxx
" 4 abc21
" 5 end of Xxx
" 6 end of Xxx
" 7 write
" 8 abc21
" 9 end of Xxx
let g:lines = []
au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']")))
w >>XtestD " will add lines to 'lines'
call assert_equal(9, len(g:lines))
call assert_fails('$r XtestD', 'E484') " should not read anything
call assert_equal(9, line('$'))
call assert_equal('end of Xxx', getline('$'))
au BufReadCmd XtestE 0r Xxx|$del
sp XtestE " split window with test.out
call assert_equal('end of Xxx', getline(3))
let g:lines = []
exe "normal 2Goasdf\<Esc>\<C-W>\<C-W>"
au BufWriteCmd XtestE call extend(g:lines, getline(0, '$'))
wall " will write other window to 'lines'
call assert_equal(4, len(g:lines), g:lines)
call assert_equal("asdf", g:lines[2])
au! BufReadCmd
au! BufWriteCmd
au! FileReadCmd
au! FileWriteCmd
au! FileAppendCmd
%bwipe!
call delete('Xxx')
enew!
endfunc
func s:ReadFile()
setl noswapfile nomodified
let filename = resolve(expand("<afile>:p"))
execute 'read' fnameescape(filename)
1d_
exe 'file' fnameescape(filename)
setl buftype=acwrite
endfunc
func s:WriteFile()
let filename = resolve(expand("<afile>:p"))
setl buftype=
noautocmd execute 'write' fnameescape(filename)
setl buftype=acwrite
setl nomodified
endfunc
func Test_BufReadCmd()
autocmd BufReadCmd *.test call s:ReadFile()
autocmd BufWriteCmd *.test call s:WriteFile()
call writefile(['one', 'two', 'three'], 'Xcmd.test')
edit Xcmd.test
call assert_match('Xcmd.test" line 1 of 3', execute('file'))
normal! Gofour
write
call assert_equal(['one', 'two', 'three', 'four'], readfile('Xcmd.test'))
bwipe!
call delete('Xcmd.test')
au! BufReadCmd
au! BufWriteCmd
endfunc
func Test_BufWriteCmd()
autocmd BufWriteCmd Xbufwritecmd let g:written = 1
new
file Xbufwritecmd
set buftype=acwrite
call mkdir('Xbufwritecmd')
write
" BufWriteCmd should be triggered even if a directory has the same name
call assert_equal(1, g:written)
call delete('Xbufwritecmd', 'd')
unlet g:written
au! BufWriteCmd
bwipe!
endfunc
func SetChangeMarks(start, end)
exe a:start .. 'mark ['
exe a:end .. 'mark ]'
endfunc
" Verify the effects of autocmds on '[ and ']
func Test_change_mark_in_autocmds()
edit! Xtest
call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u\<Esc>", 'xtn')
call SetChangeMarks(2, 3)
write
call assert_equal([1, 4], [line("'["), line("']")])
call SetChangeMarks(2, 3)
au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")])
write
au! BufWritePre
if has('unix')
write XtestFilter
write >> XtestFilter
call SetChangeMarks(2, 3)
" Marks are set to the entire range of the write
au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
" '[ is adjusted to just before the line that will receive the filtered
" data
au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")])
" The filtered data is read into the buffer, and the source lines are
" still present, so the range is after the source lines
au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")])
%!cat XtestFilter
" After the filtered data is read, the original lines are deleted
call assert_equal([1, 8], [line("'["), line("']")])
au! FilterWritePre,FilterReadPre,FilterReadPost
undo
call SetChangeMarks(1, 4)
au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")])
au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")])
au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")])
2,3!cat XtestFilter
call assert_equal([2, 9], [line("'["), line("']")])
au! FilterWritePre,FilterReadPre,FilterReadPost
undo
call delete('XtestFilter')
endif
call SetChangeMarks(1, 4)
au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")])
2,3write Xtest2
au! FileWritePre
call SetChangeMarks(2, 3)
au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")])
write >> Xtest2
au! FileAppendPre
call SetChangeMarks(1, 4)
au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")])
2,3write >> Xtest2
au! FileAppendPre
call SetChangeMarks(1, 1)
au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")])
au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")])
3read Xtest2
au! FileReadPre,FileReadPost
undo
call SetChangeMarks(4, 4)
" When the line is 0, it's adjusted to 1
au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")])
0read Xtest2
au! FileReadPre,FileReadPost
undo
call SetChangeMarks(4, 4)
" When the line is 0, it's adjusted to 1
au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")])
1read Xtest2
au! FileReadPre,FileReadPost
undo
bwipe!
call delete('Xtest')
call delete('Xtest2')
endfunc
func Test_Filter_noshelltemp()
CheckExecutable cat
enew!
call setline(1, ['a', 'b', 'c', 'd'])
let shelltemp = &shelltemp
set shelltemp
let g:filter_au = 0
au FilterWritePre * let g:filter_au += 1
au FilterReadPre * let g:filter_au += 1
au FilterReadPost * let g:filter_au += 1
%!cat
call assert_equal(3, g:filter_au)
if has('filterpipe')
set noshelltemp
let g:filter_au = 0
au FilterWritePre * let g:filter_au += 1
au FilterReadPre * let g:filter_au += 1
au FilterReadPost * let g:filter_au += 1
%!cat
call assert_equal(0, g:filter_au)
endif
au! FilterWritePre,FilterReadPre,FilterReadPost
let &shelltemp = shelltemp
bwipe!
endfunc
func Test_TextYankPost()
enew!
call setline(1, ['foo'])
let g:event = []
au TextYankPost * let g:event = copy(v:event)
call assert_equal({}, v:event)
call assert_fails('let v:event = {}', 'E46:')
call assert_fails('let v:event.mykey = 0', 'E742:')
norm "ayiw
call assert_equal(
\{'regcontents': ['foo'], 'inclusive': v:true, 'regname': 'a', 'operator': 'y', 'visual': v:false, 'regtype': 'v'},
\g:event)
norm y_
call assert_equal(
\{'regcontents': ['foo'], 'inclusive': v:false, 'regname': '', 'operator': 'y', 'visual': v:false, 'regtype': 'V'},
\g:event)
norm Vy
call assert_equal(
\{'regcontents': ['foo'], 'inclusive': v:true, 'regname': '', 'operator': 'y', 'visual': v:true, 'regtype': 'V'},
\g:event)
call feedkeys("\<C-V>y", 'x')
call assert_equal(
\{'regcontents': ['f'], 'inclusive': v:true, 'regname': '', 'operator': 'y', 'visual': v:true, 'regtype': "\x161"},
\g:event)
norm "xciwbar
call assert_equal(
\{'regcontents': ['foo'], 'inclusive': v:true, 'regname': 'x', 'operator': 'c', 'visual': v:false, 'regtype': 'v'},
\g:event)
norm "bdiw
call assert_equal(
\{'regcontents': ['bar'], 'inclusive': v:true, 'regname': 'b', 'operator': 'd', 'visual': v:false, 'regtype': 'v'},
\g:event)
call assert_equal({}, v:event)
au! TextYankPost
unlet g:event
bwipe!
endfunc
func Test_autocommand_all_events()
call assert_fails('au * * bwipe', 'E1155:')
call assert_fails('au * x bwipe', 'E1155:')
call assert_fails('au! * x bwipe', 'E1155:')
endfunc
func Test_autocmd_user()
au User MyEvent let s:res = [expand("<afile>"), expand("<amatch>")]
doautocmd User MyEvent
call assert_equal(['MyEvent', 'MyEvent'], s:res)
au! User
unlet s:res
endfunc
function s:Before_test_dirchanged()
augroup test_dirchanged
autocmd!
augroup END
let s:li = []
let s:dir_this = getcwd()
let s:dir_foo = s:dir_this . '/Xfoo'
call mkdir(s:dir_foo)
let s:dir_bar = s:dir_this . '/Xbar'
call mkdir(s:dir_bar)
endfunc
function s:After_test_dirchanged()
call chdir(s:dir_this)
call delete(s:dir_foo, 'd')
call delete(s:dir_bar, 'd')
augroup test_dirchanged
autocmd!
augroup END
endfunc
function Test_dirchanged_global()
call s:Before_test_dirchanged()
autocmd test_dirchanged DirChangedPre global call add(s:li, expand("<amatch>") .. " pre cd " .. v:event.directory)
autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
call chdir(s:dir_foo)
let expected = ["global pre cd " .. s:dir_foo, "cd:", s:dir_foo]
call assert_equal(expected, s:li)
call chdir(s:dir_foo)
call assert_equal(expected, s:li)
exe 'lcd ' .. fnameescape(s:dir_bar)
call assert_equal(expected, s:li)
exe 'cd ' .. s:dir_foo
exe 'cd ' .. s:dir_bar
autocmd! test_dirchanged DirChanged global let g:result = expand("<afile>")
cd -
call assert_equal(s:dir_foo, substitute(g:result, '\\', '/', 'g'))
call s:After_test_dirchanged()
endfunc
function Test_dirchanged_local()
call s:Before_test_dirchanged()
autocmd test_dirchanged DirChanged window call add(s:li, "lcd:")
autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>"))
call chdir(s:dir_foo)
call assert_equal([], s:li)
exe 'lcd ' .. fnameescape(s:dir_bar)
call assert_equal(["lcd:", s:dir_bar], s:li)
exe 'lcd ' .. fnameescape(s:dir_bar)
call assert_equal(["lcd:", s:dir_bar], s:li)
call s:After_test_dirchanged()
endfunc
function Test_dirchanged_auto()
CheckFunction test_autochdir
CheckOption autochdir
call s:Before_test_dirchanged()
call test_autochdir()
autocmd test_dirchanged DirChangedPre auto call add(s:li, "pre cd " .. v:event.directory)
autocmd test_dirchanged DirChanged auto call add(s:li, "auto:")
autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
set acd
cd ..
call assert_equal([], s:li)
exe 'edit ' . s:dir_foo . '/Xfile'
call assert_equal(s:dir_foo, getcwd())
let expected = ["pre cd " .. s:dir_foo, "auto:", s:dir_foo]
call assert_equal(expected, s:li)
set noacd
bwipe!
call s:After_test_dirchanged()
endfunc
" Test TextChangedI and TextChangedP
func Test_ChangedP()
throw 'Skipped: use test/functional/editor/completion_spec.lua'
new
call setline(1, ['foo', 'bar', 'foobar'])
call test_override("char_avail", 1)
set complete=. completeopt=menuone
func! TextChangedAutocmd(char)
let g:autocmd .= a:char
endfunc
au! TextChanged <buffer> :call TextChangedAutocmd('N')
au! TextChangedI <buffer> :call TextChangedAutocmd('I')
au! TextChangedP <buffer> :call TextChangedAutocmd('P')
call cursor(3, 1)
let g:autocmd = ''
call feedkeys("o\<esc>", 'tnix')
call assert_equal('I', g:autocmd)
let g:autocmd = ''
call feedkeys("Sf", 'tnix')
call assert_equal('II', g:autocmd)
let g:autocmd = ''
call feedkeys("Sf\<C-N>", 'tnix')
call assert_equal('IIP', g:autocmd)
let g:autocmd = ''
call feedkeys("Sf\<C-N>\<C-N>", 'tnix')
call assert_equal('IIPP', g:autocmd)
let g:autocmd = ''
call feedkeys("Sf\<C-N>\<C-N>\<C-N>", 'tnix')
call assert_equal('IIPPP', g:autocmd)
let g:autocmd = ''
call feedkeys("Sf\<C-N>\<C-N>\<C-N>\<C-N>", 'tnix')
call assert_equal('IIPPPP', g:autocmd)
call assert_equal(['foo', 'bar', 'foobar', 'foo'], getline(1, '$'))
" TODO: how should it handle completeopt=noinsert,noselect?
" CleanUp
call test_override("char_avail", 0)
au! TextChanged
au! TextChangedI
au! TextChangedP
delfu TextChangedAutocmd
unlet! g:autocmd
set complete&vim completeopt&vim
bw!
endfunc
let g:setline_handled = v:false
func SetLineOne()
if !g:setline_handled
call setline(1, "(x)")
let g:setline_handled = v:true
endif
endfunc
func Test_TextChangedI_with_setline()
CheckFunction test_override
new
call test_override('char_avail', 1)
autocmd TextChangedI <buffer> call SetLineOne()
call feedkeys("i(\<CR>\<Esc>", 'tx')
call assert_equal('(', getline(1))
call assert_equal('x)', getline(2))
undo
call assert_equal('', getline(1))
call assert_equal('', getline(2))
call test_override('starting', 0)
bwipe!
endfunc
func Test_Changed_FirstTime()
CheckFeature terminal
CheckNotGui
" Starting a terminal to run Vim is always considered flaky.
let g:test_is_flaky = 1
" Prepare file for TextChanged event.
call writefile([''], 'Xchanged.txt')
let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
call assert_equal('running', term_getstatus(buf))
" Wait for the ruler (in the status line) to be shown.
call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))})
" It's only adding autocmd, so that no event occurs.
call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>")
call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
call assert_equal([''], readfile('Xchanged.txt'))
" clean up
call delete('Xchanged.txt')
bwipe!
endfunc
func Test_autocmd_nested()
let g:did_nested = 0
augroup Testing
au WinNew * edit somefile
au BufNew * let g:did_nested = 1
augroup END
split
call assert_equal(0, g:did_nested)
close
bwipe! somefile
" old nested argument still works
augroup Testing
au!
au WinNew * nested edit somefile
au BufNew * let g:did_nested = 1
augroup END
split
call assert_equal(1, g:did_nested)
close
bwipe! somefile
" New ++nested argument works
augroup Testing
au!
au WinNew * ++nested edit somefile
au BufNew * let g:did_nested = 1
augroup END
split
call assert_equal(1, g:did_nested)
close
bwipe! somefile
augroup Testing
au!
augroup END
call assert_fails('au WinNew * ++nested ++nested echo bad', 'E983:')
call assert_fails('au WinNew * nested nested echo bad', 'E983:')
endfunc
func Test_autocmd_nested_cursor_invalid()
set laststatus=0
copen
cclose
call setline(1, ['foo', 'bar', 'baz'])
3
augroup nested_inv
autocmd User foo ++nested copen
autocmd BufAdd * let &laststatus = 2 - &laststatus
augroup END
doautocmd User foo
augroup nested_inv
au!
augroup END
set laststatus&
cclose
bwipe!
endfunc
func Test_autocmd_nested_keeps_cursor_pos()
enew
call setline(1, 'foo')
autocmd User foo ++nested normal! $a
autocmd InsertLeave * :
doautocmd User foo
call assert_equal([0, 1, 3, 0], getpos('.'))
bwipe!
endfunc
func Test_autocmd_nested_switch_window()
" run this in a separate Vim so that SafeState works
CheckRunVimInTerminal
let lines =<< trim END
vim9script
['()']->writefile('Xautofile')
autocmd VimEnter * ++nested edit Xautofile | split
autocmd BufReadPost * autocmd SafeState * ++once foldclosed('.')
autocmd WinEnter * matchadd('ErrorMsg', 'pat')
END
call writefile(lines, 'Xautoscript')
let buf = RunVimInTerminal('-S Xautoscript', {'rows': 10})
call VerifyScreenDump(buf, 'Test_autocmd_nested_switch', {})
call StopVimInTerminal(buf)
call delete('Xautofile')
call delete('Xautoscript')
endfunc
func Test_autocmd_once()
" Without ++once WinNew triggers twice
let g:did_split = 0
augroup Testing
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:')
endfunc
func Test_autocmd_bufreadpre()
new
let b:bufreadpre = 1
call append(0, range(100))
w! XAutocmdBufReadPre.txt
autocmd BufReadPre <buffer> :let b:bufreadpre += 1
norm! 50gg
sp
norm! 100gg
wincmd p
let g:wsv1 = winsaveview()
wincmd p
let g:wsv2 = winsaveview()
" triggers BufReadPre, should not move the cursor in either window
" The topline may change one line in a large window.
edit
call assert_inrange(g:wsv2.topline - 1, g:wsv2.topline + 1, winsaveview().topline)
call assert_equal(g:wsv2.lnum, winsaveview().lnum)
call assert_equal(2, b:bufreadpre)
wincmd p
call assert_equal(g:wsv1.topline, winsaveview().topline)
call assert_equal(g:wsv1.lnum, winsaveview().lnum)
call assert_equal(2, b:bufreadpre)
" Now set the cursor position in an BufReadPre autocommand
" (even though the position will be invalid, this should make Vim reset the
" cursor position in the other window.
wincmd p
1 " set cpo+=g
" won't do anything, but try to set the cursor on an invalid lnum
autocmd BufReadPre <buffer> :norm! 70gg
" triggers BufReadPre, should not move the cursor in either window
e
call assert_equal(1, winsaveview().topline)
call assert_equal(1, winsaveview().lnum)
call assert_equal(3, b:bufreadpre)
wincmd p
call assert_equal(g:wsv1.topline, winsaveview().topline)
call assert_equal(g:wsv1.lnum, winsaveview().lnum)
call assert_equal(3, b:bufreadpre)
close
close
call delete('XAutocmdBufReadPre.txt')
set cpo-=g
endfunc
" FileChangedShell tested in test_filechanged.vim
" Tests for the following autocommands:
" - FileWritePre writing a compressed file
" - FileReadPost reading a compressed file
" - BufNewFile reading a file template
" - BufReadPre decompressing the file to be read
" - FilterReadPre substituting characters in the temp file
" - FilterReadPost substituting characters after filtering
" - FileReadPre set options for decompression
" - FileReadPost decompress the file
func Test_ReadWrite_Autocmds()
" Run this test only on Unix-like systems and if gzip is available
if !has('unix') || !executable("gzip")
return
endif
" Make $GZIP empty, "-v" would cause trouble.
let $GZIP = ""
" Use a FileChangedShell autocommand to avoid a prompt for 'Xtestfile.gz'
" being modified outside of Vim (noticed on Solaris).
au FileChangedShell * echo 'caught FileChangedShell'
" Test for the FileReadPost, FileWritePre and FileWritePost autocmds
augroup Test1
au!
au FileWritePre *.gz '[,']!gzip
au FileWritePost *.gz undo
au FileReadPost *.gz '[,']!gzip -d
augroup END
new
set bin
call append(0, [
\ 'line 2 Abcdefghijklmnopqrstuvwxyz',
\ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 4 Abcdefghijklmnopqrstuvwxyz',
\ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 6 Abcdefghijklmnopqrstuvwxyz',
\ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 8 Abcdefghijklmnopqrstuvwxyz',
\ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 10 Abcdefghijklmnopqrstuvwxyz'
\ ])
1,9write! Xtestfile.gz
enew! | close
new
" Read and decompress the testfile
0read Xtestfile.gz
call assert_equal([
\ 'line 2 Abcdefghijklmnopqrstuvwxyz',
\ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 4 Abcdefghijklmnopqrstuvwxyz',
\ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 6 Abcdefghijklmnopqrstuvwxyz',
\ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 8 Abcdefghijklmnopqrstuvwxyz',
\ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 10 Abcdefghijklmnopqrstuvwxyz'
\ ], getline(1, 9))
enew! | close
augroup Test1
au!
augroup END
" Test for the FileAppendPre and FileAppendPost autocmds
augroup Test2
au!
au BufNewFile *.c read Xtest.c
au FileAppendPre *.out '[,']s/new/NEW/
au FileAppendPost *.out !cat Xtest.c >> test.out
augroup END
call writefile(['/*', ' * Here is a new .c file', ' */'], 'Xtest.c')
new foo.c " should load Xtest.c
call assert_equal(['/*', ' * Here is a new .c file', ' */'], getline(2, 4))
w! >> test.out " append it to the output file
let contents = readfile('test.out')
call assert_equal(' * Here is a NEW .c file', contents[2])
call assert_equal(' * Here is a new .c file', contents[5])
call delete('test.out')
enew! | close
augroup Test2
au!
augroup END
" Test for the BufReadPre and BufReadPost autocmds
augroup Test3
au!
" setup autocommands to decompress before reading and re-compress
" afterwards
au BufReadPre *.gz exe '!gzip -d ' . shellescape(expand("<afile>"))
au BufReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
au BufReadPost *.gz call rename(expand("<afile>"), expand("<afile>:r"))
au BufReadPost *.gz exe '!gzip ' . shellescape(expand("<afile>:r"))
augroup END
e! Xtestfile.gz " Edit compressed file
call assert_equal([
\ 'line 2 Abcdefghijklmnopqrstuvwxyz',
\ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 4 Abcdefghijklmnopqrstuvwxyz',
\ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 6 Abcdefghijklmnopqrstuvwxyz',
\ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 8 Abcdefghijklmnopqrstuvwxyz',
\ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 10 Abcdefghijklmnopqrstuvwxyz'
\ ], getline(1, 9))
w! >> test.out " Append it to the output file
augroup Test3
au!
augroup END
" Test for the FilterReadPre and FilterReadPost autocmds.
set shelltemp " need temp files here
augroup Test4
au!
au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t")
au FilterReadPre *.out exe 'silent !sed s/e/E/ ' . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))
au FilterReadPre *.out exe 'silent !rm ' . shellescape(expand("<afile>")) . '.t'
au FilterReadPost *.out '[,']s/x/X/g
augroup END
e! test.out " Edit the output file
1,$!cat
call assert_equal([
\ 'linE 2 AbcdefghijklmnopqrstuvwXyz',
\ 'linE 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
\ 'linE 4 AbcdefghijklmnopqrstuvwXyz',
\ 'linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
\ 'linE 6 AbcdefghijklmnopqrstuvwXyz',
\ 'linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
\ 'linE 8 AbcdefghijklmnopqrstuvwXyz',
\ 'linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
\ 'linE 10 AbcdefghijklmnopqrstuvwXyz'
\ ], getline(1, 9))
call assert_equal([
\ 'line 2 Abcdefghijklmnopqrstuvwxyz',
\ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 4 Abcdefghijklmnopqrstuvwxyz',
\ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 6 Abcdefghijklmnopqrstuvwxyz',
\ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 8 Abcdefghijklmnopqrstuvwxyz',
\ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 10 Abcdefghijklmnopqrstuvwxyz'
\ ], readfile('test.out'))
augroup Test4
au!
augroup END
set shelltemp&vim
" Test for the FileReadPre and FileReadPost autocmds.
augroup Test5
au!
au FileReadPre *.gz exe 'silent !gzip -d ' . shellescape(expand("<afile>"))
au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
au FileReadPost *.gz '[,']s/l/L/
augroup END
new
0r Xtestfile.gz " Read compressed file
call assert_equal([
\ 'Line 2 Abcdefghijklmnopqrstuvwxyz',
\ 'Line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'Line 4 Abcdefghijklmnopqrstuvwxyz',
\ 'Line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'Line 6 Abcdefghijklmnopqrstuvwxyz',
\ 'Line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'Line 8 Abcdefghijklmnopqrstuvwxyz',
\ 'Line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'Line 10 Abcdefghijklmnopqrstuvwxyz'
\ ], getline(1, 9))
call assert_equal([
\ 'line 2 Abcdefghijklmnopqrstuvwxyz',
\ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 4 Abcdefghijklmnopqrstuvwxyz',
\ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 6 Abcdefghijklmnopqrstuvwxyz',
\ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 8 Abcdefghijklmnopqrstuvwxyz',
\ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
\ 'line 10 Abcdefghijklmnopqrstuvwxyz'
\ ], readfile('Xtestfile.gz'))
augroup Test5
au!
augroup END
au! FileChangedShell
call delete('Xtestfile.gz')
call delete('Xtest.c')
call delete('test.out')
endfunc
func Test_throw_in_BufWritePre()
new
call setline(1, ['one', 'two', 'three'])
call assert_false(filereadable('Xthefile'))
augroup throwing
au BufWritePre X* throw 'do not write'
augroup END
try
w Xthefile
catch
let caught = 1
endtry
call assert_equal(1, caught)
call assert_false(filereadable('Xthefile'))
bwipe!
au! throwing
endfunc
func Test_autocmd_in_try_block()
call mkdir('Xdir')
au BufEnter * let g:fname = expand('%')
try
edit Xdir/
endtry
call assert_match('Xdir', g:fname)
unlet g:fname
au! BufEnter
call delete('Xdir', 'rf')
endfunc
func Test_autocmd_CmdWinEnter()
CheckRunVimInTerminal
" There is not cmdwin switch, so
" test for cmdline_hist
" (both are available with small builds)
CheckFeature cmdline_hist
let lines =<< trim END
let b:dummy_var = 'This is a dummy'
autocmd CmdWinEnter * quit
let winnr = winnr('$')
END
let filename = 'XCmdWinEnter'
call writefile(lines, filename)
let buf = RunVimInTerminal('-S '.filename, #{rows: 6})
call term_sendkeys(buf, "q:")
call term_wait(buf)
call term_sendkeys(buf, ":echo b:dummy_var\<cr>")
call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000)
call term_sendkeys(buf, ":echo &buftype\<cr>")
call WaitForAssert({-> assert_notmatch('^nofile', term_getline(buf, 6))}, 1000)
call term_sendkeys(buf, ":echo winnr\<cr>")
call WaitForAssert({-> assert_match('^1', term_getline(buf, 6))}, 1000)
" clean up
call StopVimInTerminal(buf)
call delete(filename)
endfunc
func Test_autocmd_was_using_freed_memory()
pedit xx
n x
augroup winenter
au WinEnter * if winnr('$') > 2 | quit | endif
augroup END
" Nvim needs large 'winwidth' and 'nowinfixwidth' to crash
set winwidth=99999 nowinfixwidth
split
augroup winenter
au! WinEnter
augroup END
set winwidth& winfixwidth&
bwipe xx
bwipe x
pclose
endfunc
func Test_BufWrite_lockmarks()
edit! Xtest
call setline(1, ['a', 'b', 'c', 'd'])
" :lockmarks preserves the marks
call SetChangeMarks(2, 3)
lockmarks write
call assert_equal([2, 3], [line("'["), line("']")])
" *WritePre autocmds get the correct line range, but lockmarks preserves the
" original values for the user
augroup lockmarks
au!
au BufWritePre,FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
au FileWritePre * call assert_equal([3, 4], [line("'["), line("']")])
augroup END
lockmarks write
call assert_equal([2, 3], [line("'["), line("']")])
if executable('cat')
lockmarks %!cat
call assert_equal([2, 3], [line("'["), line("']")])
endif
lockmarks 3,4write Xtest2
call assert_equal([2, 3], [line("'["), line("']")])
au! lockmarks
augroup! lockmarks
call delete('Xtest')
call delete('Xtest2')
endfunc
func Test_FileType_spell()
if !isdirectory('/tmp')
throw "Skipped: requires /tmp directory"
endif
" this was crashing with an invalid free()
setglobal spellfile=/tmp/en.utf-8.add
augroup crash
autocmd!
autocmd BufNewFile,BufReadPost crashfile setf somefiletype
autocmd BufNewFile,BufReadPost crashfile set ft=anotherfiletype
autocmd FileType anotherfiletype setlocal spell
augroup END
func! NoCrash() abort
edit /tmp/crashfile
endfunc
call NoCrash()
au! crash
setglobal spellfile=
endfunc
" this was wiping out the current buffer and using freed memory
func Test_SpellFileMissing_bwipe()
next 0
au SpellFileMissing 0 bwipe
call assert_fails('set spell spelllang=0', 'E937:')
au! SpellFileMissing
set nospell spelllang=en
bwipe
endfunc
" Test closing a window or editing another buffer from a FileChangedRO handler
" in a readonly buffer
func Test_FileChangedRO_winclose()
augroup FileChangedROTest
au!
autocmd FileChangedRO * quit
augroup END
new
set readonly
call assert_fails('normal i', 'E788:')
close
augroup! FileChangedROTest
augroup FileChangedROTest
au!
autocmd FileChangedRO * edit Xfile
augroup END
new
set readonly
call assert_fails('normal i', 'E788:')
close
augroup! FileChangedROTest
endfunc
func LogACmd()
call add(g:logged, line('$'))
endfunc
func Test_TermChanged()
throw 'skipped: Nvim does not support TermChanged event'
CheckNotGui
enew!
tabnew
call setline(1, ['a', 'b', 'c', 'd'])
$
au TermChanged * call LogACmd()
let g:logged = []
let term_save = &term
set term=xterm
call assert_equal([1, 4], g:logged)
au! TermChanged
let &term = term_save
bwipe!
endfunc
" Test for FileReadCmd autocmd
func Test_autocmd_FileReadCmd()
func ReadFileCmd()
call append(line('$'), "v:cmdarg = " .. v:cmdarg)
endfunc
augroup FileReadCmdTest
au!
au FileReadCmd Xtest call ReadFileCmd()
augroup END
new
read ++bin Xtest
read ++nobin Xtest
read ++edit Xtest
read ++bad=keep Xtest
read ++bad=drop Xtest
read ++bad=- Xtest
read ++ff=unix Xtest
read ++ff=dos Xtest
read ++ff=mac Xtest
read ++enc=utf-8 Xtest
call assert_equal(['',
\ 'v:cmdarg = ++bin',
\ 'v:cmdarg = ++nobin',
\ 'v:cmdarg = ++edit',
\ 'v:cmdarg = ++bad=keep',
\ 'v:cmdarg = ++bad=drop',
\ 'v:cmdarg = ++bad=-',
\ 'v:cmdarg = ++ff=unix',
\ 'v:cmdarg = ++ff=dos',
\ 'v:cmdarg = ++ff=mac',
\ 'v:cmdarg = ++enc=utf-8'], getline(1, '$'))
close!
augroup FileReadCmdTest
au!
augroup END
delfunc ReadFileCmd
endfunc
" Test for passing invalid arguments to autocmd
func Test_autocmd_invalid_args()
" Additional character after * for event
call assert_fails('autocmd *a Xfile set ff=unix', 'E215:')
augroup Test
augroup END
" Invalid autocmd event
call assert_fails('autocmd Bufabc Xfile set ft=vim', 'E216:')
" Invalid autocmd event in a autocmd group
call assert_fails('autocmd Test Bufabc Xfile set ft=vim', 'E216:')
augroup! Test
" Execute all autocmds
call assert_fails('doautocmd * BufEnter', 'E217:')
call assert_fails('augroup! x1a2b3', 'E367:')
call assert_fails('autocmd BufNew <buffer=999> pwd', 'E680:')
call assert_fails('autocmd BufNew \) set ff=unix', 'E55:')
endfunc
" Test for deep nesting of autocmds
func Test_autocmd_deep_nesting()
autocmd BufEnter Xfile doautocmd BufEnter Xfile
call assert_fails('doautocmd BufEnter Xfile', 'E218:')
autocmd! BufEnter Xfile
endfunc
" Tests for SigUSR1 autocmd event, which is only available on posix systems.
func Test_autocmd_sigusr1()
CheckUnix
let g:sigusr1_passed = 0
au Signal SIGUSR1 let g:sigusr1_passed = 1
call system('kill -s usr1 ' . getpid())
call WaitForAssert({-> assert_true(g:sigusr1_passed)})
au! Signal
unlet g:sigusr1_passed
endfunc
" Test for BufReadPre autocmd deleting the file
func Test_BufReadPre_delfile()
augroup TestAuCmd
au!
autocmd BufReadPre Xfile call delete('Xfile')
augroup END
call writefile([], 'Xfile')
call assert_fails('new Xfile', 'E200:')
call assert_equal('Xfile', @%)
call assert_equal(1, &readonly)
call delete('Xfile')
augroup TestAuCmd
au!
augroup END
close!
endfunc
" Test for BufReadPre autocmd changing the current buffer
func Test_BufReadPre_changebuf()
augroup TestAuCmd
au!
autocmd BufReadPre Xfile edit Xsomeotherfile
augroup END
call writefile([], 'Xfile')
call assert_fails('new Xfile', 'E201:')
call assert_equal('Xsomeotherfile', @%)
call assert_equal(1, &readonly)
call delete('Xfile')
augroup TestAuCmd
au!
augroup END
close!
endfunc
" Test for BufWipeouti autocmd changing the current buffer when reading a file
" in an empty buffer with 'f' flag in 'cpo'
func Test_BufDelete_changebuf()
new
augroup TestAuCmd
au!
autocmd BufWipeout * let bufnr = bufadd('somefile') | exe "b " .. bufnr
augroup END
let save_cpo = &cpo
set cpo+=f
call assert_fails('r Xfile', ['E812:', 'E484:'])
call assert_equal('somefile', @%)
let &cpo = save_cpo
augroup TestAuCmd
au!
augroup END
close!
endfunc
" Test for the temporary internal window used to execute autocmds
func Test_autocmd_window()
%bw!
edit one.txt
tabnew two.txt
vnew three.txt
tabnew four.txt
tabprevious
let g:blist = []
augroup aucmd_win_test1
au!
au BufEnter * call add(g:blist, [expand('<afile>'),
\ win_gettype(bufwinnr(expand('<afile>')))])
augroup END
doautoall BufEnter
call assert_equal([
\ ['one.txt', 'autocmd'],
\ ['two.txt', ''],
\ ['four.txt', 'autocmd'],
\ ['three.txt', ''],
\ ], g:blist)
augroup aucmd_win_test1
au!
augroup END
augroup! aucmd_win_test1
%bw!
endfunc
" Test for trying to close the temporary window used for executing an autocmd
func Test_close_autocmd_window()
%bw!
edit one.txt
tabnew two.txt
augroup aucmd_win_test2
au!
" Nvim makes aucmd_win the last window
" au BufEnter * if expand('<afile>') == 'one.txt' | 1close | endif
au BufEnter * if expand('<afile>') == 'one.txt' | close | endif
augroup END
call assert_fails('doautoall BufEnter', 'E813:')
augroup aucmd_win_test2
au!
augroup END
augroup! aucmd_win_test2
%bw!
endfunc
" Test for trying to close the tab that has the temporary window for exeucing
" an autocmd.
func Test_close_autocmd_tab()
edit one.txt
tabnew two.txt
augroup aucmd_win_test
au!
au BufEnter * if expand('<afile>') == 'one.txt' | tabfirst | tabonly | endif
augroup END
call assert_fails('doautoall BufEnter', 'E813:')
tabonly
augroup aucmd_win_test
au!
augroup END
augroup! aucmd_win_test
%bwipe!
endfunc
func Test_Visual_doautoall_redraw()
call setline(1, ['a', 'b'])
new
wincmd p
call feedkeys("G\<C-V>", 'txn')
autocmd User Explode ++once redraw
doautoall User Explode
%bwipe!
endfunc
" This was using freed memory.
func Test_BufNew_arglocal()
arglocal
au BufNew * arglocal
call assert_fails('drop xx', 'E1156:')
au! BufNew
endfunc
func Test_autocmd_closes_window()
au BufNew,BufWinLeave * e %e
file yyy
au BufNew,BufWinLeave * ball
n xxx
%bwipe
au! BufNew
au! BufWinLeave
endfunc
func Test_autocmd_quit_psearch()
sn aa bb
augroup aucmd_win_test
au!
au BufEnter,BufLeave,BufNew,WinEnter,WinLeave,WinNew * if winnr('$') > 1 | q | endif
augroup END
ps /
augroup aucmd_win_test
au!
augroup END
new
pclose
endfunc
" Fuzzer found some strange combination that caused a crash.
func Test_autocmd_normal_mess()
" For unknown reason this hangs on MS-Windows
CheckNotMSWindows
augroup aucmd_normal_test
au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc
augroup END
" Nvim has removed :open
" call assert_fails('o4', 'E1159')
call assert_fails('e4', 'E1159')
silent! H
call assert_fails('e xx', 'E1159')
normal G
augroup aucmd_normal_test
au!
augroup END
endfunc
func Test_autocmd_closing_cmdwin()
" For unknown reason this hangs on MS-Windows
CheckNotMSWindows
au BufWinLeave * nested q
call assert_fails("norm 7q?\n", 'E855:')
au! BufWinLeave
new
only
endfunc
func Test_autocmd_vimgrep()
augroup aucmd_vimgrep
au QuickfixCmdPre,BufNew,BufReadCmd * sb
" Nvim makes aucmd_win the last window
" au QuickfixCmdPre,BufNew,BufReadCmd * q9
au QuickfixCmdPre,BufNew,BufReadCmd * exe 'q' .. (winnr('$') - (win_gettype(winnr('$')) == 'autocmd'))
augroup END
call assert_fails('lv ?a? foo', 'E926:')
augroup aucmd_vimgrep
au!
augroup END
endfunc
func Test_bufwipeout_changes_window()
" This should not crash, but we don't have any expectations about what
" happens, changing window in BufWipeout has unpredictable results.
tabedit
let g:window_id = win_getid()
topleft new
setlocal bufhidden=wipe
autocmd BufWipeout <buffer> call win_gotoid(g:window_id)
tabprevious
+tabclose
unlet g:window_id
au! BufWipeout
%bwipe!
endfunc
func Test_v_event_readonly()
autocmd CompleteChanged * let v:event.width = 0
call assert_fails("normal! i\<C-X>\<C-V>", 'E46:')
au! CompleteChanged
autocmd DirChangedPre * let v:event.directory = ''
call assert_fails('cd .', 'E46:')
au! DirChangedPre
autocmd ModeChanged * let v:event.new_mode = ''
call assert_fails('normal! cc', 'E46:')
au! ModeChanged
autocmd TextYankPost * let v:event.operator = ''
call assert_fails('normal! yy', 'E46:')
au! TextYankPost
endfunc
" Test for ModeChanged pattern
func Test_mode_changes()
let g:index = 0
let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'i', 'ix', 'i', 'ic', 'i', 'n', 'no', 'n', 'V', 'v', 's', 'n']
func! TestMode()
call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode"))
call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode"))
call assert_equal(mode(1), get(v:event, "new_mode"))
let g:index += 1
endfunc
au ModeChanged * :call TestMode()
let g:n_to_any = 0
au ModeChanged n:* let g:n_to_any += 1
call feedkeys("i\<esc>vVca\<CR>\<C-X>\<C-L>\<esc>ggdG", 'tnix')
let g:V_to_v = 0
au ModeChanged V:v let g:V_to_v += 1
call feedkeys("Vv\<C-G>\<esc>", 'tnix')
call assert_equal(len(filter(g:mode_seq[1:], {idx, val -> val == 'n'})), g:n_to_any)
call assert_equal(1, g:V_to_v)
call assert_equal(len(g:mode_seq) - 1, g:index)
let g:n_to_i = 0
au ModeChanged n:i let g:n_to_i += 1
let g:n_to_niI = 0
au ModeChanged i:niI let g:n_to_niI += 1
let g:niI_to_i = 0
au ModeChanged niI:i let g:niI_to_i += 1
let g:nany_to_i = 0
au ModeChanged n*:i let g:nany_to_i += 1
let g:i_to_n = 0
au ModeChanged i:n let g:i_to_n += 1
let g:nori_to_any = 0
au ModeChanged [ni]:* let g:nori_to_any += 1
let g:i_to_any = 0
au ModeChanged i:* let g:i_to_any += 1
let g:index = 0
let g:mode_seq = ['n', 'i', 'niI', 'i', 'n']
call feedkeys("a\<C-O>l\<esc>", 'tnix')
call assert_equal(len(g:mode_seq) - 1, g:index)
call assert_equal(1, g:n_to_i)
call assert_equal(1, g:n_to_niI)
call assert_equal(1, g:niI_to_i)
call assert_equal(2, g:nany_to_i)
call assert_equal(1, g:i_to_n)
call assert_equal(2, g:i_to_any)
call assert_equal(3, g:nori_to_any)
if has('terminal')
let g:mode_seq += ['c', 'n', 't', 'nt', 'c', 'nt', 'n']
call feedkeys(":term\<CR>\<C-W>N:bd!\<CR>", 'tnix')
call assert_equal(len(g:mode_seq) - 1, g:index)
call assert_equal(1, g:n_to_i)
call assert_equal(1, g:n_to_niI)
call assert_equal(1, g:niI_to_i)
call assert_equal(2, g:nany_to_i)
call assert_equal(1, g:i_to_n)
call assert_equal(2, g:i_to_any)
call assert_equal(5, g:nori_to_any)
endif
let g:n_to_c = 0
au ModeChanged n:c let g:n_to_c += 1
let g:c_to_n = 0
au ModeChanged c:n let g:c_to_n += 1
let g:mode_seq += ['c', 'n', 'c', 'n']
call feedkeys("q:\<C-C>\<Esc>", 'tnix')
call assert_equal(len(g:mode_seq) - 1, g:index)
call assert_equal(2, g:n_to_c)
call assert_equal(2, g:c_to_n)
unlet g:n_to_c
unlet g:c_to_n
let g:n_to_v = 0
au ModeChanged n:v let g:n_to_v += 1
let g:v_to_n = 0
au ModeChanged v:n let g:v_to_n += 1
let g:mode_seq += ['v', 'n']
call feedkeys("v\<C-C>", 'tnix')
call assert_equal(len(g:mode_seq) - 1, g:index)
call assert_equal(1, g:n_to_v)
call assert_equal(1, g:v_to_n)
unlet g:n_to_v
unlet g:v_to_n
au! ModeChanged
delfunc TestMode
unlet! g:mode_seq
unlet! g:index
unlet! g:n_to_any
unlet! g:V_to_v
unlet! g:n_to_i
unlet! g:n_to_niI
unlet! g:niI_to_i
unlet! g:nany_to_i
unlet! g:i_to_n
unlet! g:nori_to_any
unlet! g:i_to_any
endfunc
func Test_recursive_ModeChanged()
au! ModeChanged * norm 0u
sil! norm 
au! ModeChanged
endfunc
func Test_ModeChanged_starts_visual()
" This was triggering ModeChanged before setting VIsual, causing a crash.
au! ModeChanged * norm 0u
sil! norm 
au! ModeChanged
endfunc
func Test_noname_autocmd()
augroup test_noname_autocmd_group
autocmd!
autocmd BufEnter * call add(s:li, ["BufEnter", expand("<afile>")])
autocmd BufDelete * call add(s:li, ["BufDelete", expand("<afile>")])
autocmd BufLeave * call add(s:li, ["BufLeave", expand("<afile>")])
autocmd BufUnload * call add(s:li, ["BufUnload", expand("<afile>")])
autocmd BufWipeout * call add(s:li, ["BufWipeout", expand("<afile>")])
augroup END
let s:li = []
edit foo
call assert_equal([['BufUnload', ''], ['BufDelete', ''], ['BufWipeout', ''], ['BufEnter', 'foo']], s:li)
au! test_noname_autocmd_group
augroup! test_noname_autocmd_group
endfunc
func Test_autocmd_split_dummy()
" Autocommand trying to split a window containing a dummy buffer.
auto BufReadPre * exe "sbuf " .. expand("<abuf>")
" Avoid the "W11" prompt
au FileChangedShell * let v:fcs_choice = 'reload'
func Xautocmd_changelist()
cal writefile(['Xtestfile2:4:4'], 'Xerr')
edit Xerr
lex 'Xtestfile2:4:4'
endfunc
call Xautocmd_changelist()
" Should get E86, but it doesn't always happen (timing?)
silent! call Xautocmd_changelist()
au! BufReadPre
au! FileChangedShell
delfunc Xautocmd_changelist
bwipe! Xerr
call delete('Xerr')
endfunc
" This was crashing because there was only one window to execute autocommands
" in.
func Test_autocmd_nested_setbufvar()
CheckFeature python3
set hidden
edit Xaaa
edit Xbbb
call setline(1, 'bar')
enew
au BufWriteCmd Xbbb ++nested call setbufvar('Xaaa', '&ft', 'foo') | bw! Xaaa
au FileType foo call py3eval('vim.current.buffer.options["cindent"]')
wall
au! BufWriteCmd
au! FileType foo
set nohidden
call delete('Xaaa')
call delete('Xbbb')
%bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab