xref: /vim-8.2.3635/src/testdir/test_autocmd.vim (revision abcbb0e9)
1" Tests for autocommands
2
3source shared.vim
4source check.vim
5source term_util.vim
6
7func s:cleanup_buffers() abort
8  for bnr in range(1, bufnr('$'))
9    if bufloaded(bnr) && bufnr('%') != bnr
10      execute 'bd! ' . bnr
11    endif
12  endfor
13endfunc
14
15func Test_vim_did_enter()
16  call assert_false(v:vim_did_enter)
17
18  " This script will never reach the main loop, can't check if v:vim_did_enter
19  " becomes one.
20endfunc
21
22" Test for the CursorHold autocmd
23func Test_CursorHold_autocmd()
24  CheckRunVimInTerminal
25  call writefile(['one', 'two', 'three'], 'Xfile')
26  let before =<< trim END
27    set updatetime=10
28    au CursorHold * call writefile([line('.')], 'Xoutput', 'a')
29  END
30  call writefile(before, 'Xinit')
31  let buf = RunVimInTerminal('-S Xinit Xfile', {})
32  call term_sendkeys(buf, "G")
33  call term_wait(buf, 50)
34  call term_sendkeys(buf, "gg")
35  call term_wait(buf)
36  call WaitForAssert({-> assert_equal(['1'], readfile('Xoutput')[-1:-1])})
37  call term_sendkeys(buf, "j")
38  call term_wait(buf)
39  call WaitForAssert({-> assert_equal(['1', '2'], readfile('Xoutput')[-2:-1])})
40  call term_sendkeys(buf, "j")
41  call term_wait(buf)
42  call WaitForAssert({-> assert_equal(['1', '2', '3'], readfile('Xoutput')[-3:-1])})
43  call StopVimInTerminal(buf)
44
45  call delete('Xinit')
46  call delete('Xoutput')
47  call delete('Xfile')
48endfunc
49
50if has('timers')
51
52  func ExitInsertMode(id)
53    call feedkeys("\<Esc>")
54  endfunc
55
56  func Test_cursorhold_insert()
57    " Need to move the cursor.
58    call feedkeys("ggG", "xt")
59
60    let g:triggered = 0
61    au CursorHoldI * let g:triggered += 1
62    set updatetime=20
63    call timer_start(100, 'ExitInsertMode')
64    call feedkeys('a', 'x!')
65    call assert_equal(1, g:triggered)
66    unlet g:triggered
67    au! CursorHoldI
68    set updatetime&
69  endfunc
70
71  func Test_cursorhold_insert_with_timer_interrupt()
72    CheckFeature job
73    " Need to move the cursor.
74    call feedkeys("ggG", "xt")
75
76    " Confirm the timer invoked in exit_cb of the job doesn't disturb
77    " CursorHoldI event.
78    let g:triggered = 0
79    au CursorHoldI * let g:triggered += 1
80    set updatetime=100
81    call job_start(has('win32') ? 'cmd /c echo:' : 'echo',
82          \ {'exit_cb': {-> timer_start(200, 'ExitInsertMode')}})
83    call feedkeys('a', 'x!')
84    call assert_equal(1, g:triggered)
85    unlet g:triggered
86    au! CursorHoldI
87    set updatetime&
88  endfunc
89
90  func Test_cursorhold_insert_ctrl_x()
91    let g:triggered = 0
92    au CursorHoldI * let g:triggered += 1
93    set updatetime=20
94    call timer_start(100, 'ExitInsertMode')
95    " CursorHoldI does not trigger after CTRL-X
96    call feedkeys("a\<C-X>", 'x!')
97    call assert_equal(0, g:triggered)
98    unlet g:triggered
99    au! CursorHoldI
100    set updatetime&
101  endfunc
102
103  func Test_OptionSet_modeline()
104    call test_override('starting', 1)
105    au! OptionSet
106    augroup set_tabstop
107      au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler called'", "")})
108    augroup END
109    call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline')
110    set modeline
111    let v:errmsg = ''
112    call assert_fails('split XoptionsetModeline', 'E12:')
113    call assert_equal(7, &ts)
114    call assert_equal('', v:errmsg)
115
116    augroup set_tabstop
117      au!
118    augroup END
119    bwipe!
120    set ts&
121    call delete('XoptionsetModeline')
122    call test_override('starting', 0)
123  endfunc
124
125endif "has('timers')
126
127func Test_bufunload()
128  augroup test_bufunload_group
129    autocmd!
130    autocmd BufUnload * call add(s:li, "bufunload")
131    autocmd BufDelete * call add(s:li, "bufdelete")
132    autocmd BufWipeout * call add(s:li, "bufwipeout")
133  augroup END
134
135  let s:li = []
136  new
137  setlocal bufhidden=
138  bunload
139  call assert_equal(["bufunload", "bufdelete"], s:li)
140
141  let s:li = []
142  new
143  setlocal bufhidden=delete
144  bunload
145  call assert_equal(["bufunload", "bufdelete"], s:li)
146
147  let s:li = []
148  new
149  setlocal bufhidden=unload
150  bwipeout
151  call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li)
152
153  au! test_bufunload_group
154  augroup! test_bufunload_group
155endfunc
156
157" SEGV occurs in older versions.  (At least 7.4.2005 or older)
158func Test_autocmd_bufunload_with_tabnext()
159  tabedit
160  tabfirst
161
162  augroup test_autocmd_bufunload_with_tabnext_group
163    autocmd!
164    autocmd BufUnload <buffer> tabnext
165  augroup END
166
167  quit
168  call assert_equal(2, tabpagenr('$'))
169
170  autocmd! test_autocmd_bufunload_with_tabnext_group
171  augroup! test_autocmd_bufunload_with_tabnext_group
172  tablast
173  quit
174endfunc
175
176func Test_autocmd_bufwinleave_with_tabfirst()
177  tabedit
178  augroup sample
179    autocmd!
180    autocmd BufWinLeave <buffer> tabfirst
181  augroup END
182  call setline(1, ['a', 'b', 'c'])
183  edit! a.txt
184  tabclose
185endfunc
186
187" SEGV occurs in older versions.  (At least 7.4.2321 or older)
188func Test_autocmd_bufunload_avoiding_SEGV_01()
189  split aa.txt
190  let lastbuf = bufnr('$')
191
192  augroup test_autocmd_bufunload
193    autocmd!
194    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
195  augroup END
196
197  call assert_fails('edit bb.txt', 'E937:')
198
199  autocmd! test_autocmd_bufunload
200  augroup! test_autocmd_bufunload
201  bwipe! aa.txt
202  bwipe! bb.txt
203endfunc
204
205" SEGV occurs in older versions.  (At least 7.4.2321 or older)
206func Test_autocmd_bufunload_avoiding_SEGV_02()
207  setlocal buftype=nowrite
208  let lastbuf = bufnr('$')
209
210  augroup test_autocmd_bufunload
211    autocmd!
212    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
213  augroup END
214
215  normal! i1
216  call assert_fails('edit a.txt', 'E517:')
217  call feedkeys("\<CR>")
218
219  autocmd! test_autocmd_bufunload
220  augroup! test_autocmd_bufunload
221  bwipe! a.txt
222endfunc
223
224func Test_autocmd_dummy_wipeout()
225  " prepare files
226  call writefile([''], 'Xdummywipetest1.txt')
227  call writefile([''], 'Xdummywipetest2.txt')
228  augroup test_bufunload_group
229    autocmd!
230    autocmd BufUnload * call add(s:li, "bufunload")
231    autocmd BufDelete * call add(s:li, "bufdelete")
232    autocmd BufWipeout * call add(s:li, "bufwipeout")
233  augroup END
234
235  let s:li = []
236  split Xdummywipetest1.txt
237  silent! vimgrep /notmatched/ Xdummywipetest*
238  call assert_equal(["bufunload", "bufwipeout"], s:li)
239
240  bwipeout
241  call delete('Xdummywipetest1.txt')
242  call delete('Xdummywipetest2.txt')
243  au! test_bufunload_group
244  augroup! test_bufunload_group
245endfunc
246
247func Test_win_tab_autocmd()
248  let g:record = []
249
250  augroup testing
251    au WinNew * call add(g:record, 'WinNew')
252    au WinEnter * call add(g:record, 'WinEnter')
253    au WinLeave * call add(g:record, 'WinLeave')
254    au TabNew * call add(g:record, 'TabNew')
255    au TabClosed * call add(g:record, 'TabClosed')
256    au TabEnter * call add(g:record, 'TabEnter')
257    au TabLeave * call add(g:record, 'TabLeave')
258  augroup END
259
260  split
261  tabnew
262  close
263  close
264
265  call assert_equal([
266	\ 'WinLeave', 'WinNew', 'WinEnter',
267	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
268	\ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter',
269	\ 'WinLeave', 'WinEnter'
270	\ ], g:record)
271
272  let g:record = []
273  tabnew somefile
274  tabnext
275  bwipe somefile
276
277  call assert_equal([
278	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
279	\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
280	\ 'TabClosed'
281	\ ], g:record)
282
283  augroup testing
284    au!
285  augroup END
286  unlet g:record
287endfunc
288
289func s:AddAnAutocmd()
290  augroup vimBarTest
291    au BufReadCmd * echo 'hello'
292  augroup END
293  call assert_equal(3, len(split(execute('au vimBarTest'), "\n")))
294endfunc
295
296func Test_early_bar()
297  " test that a bar is recognized before the {event}
298  call s:AddAnAutocmd()
299  augroup vimBarTest | au! | augroup END
300  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
301
302  call s:AddAnAutocmd()
303  augroup vimBarTest| au!| augroup END
304  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
305
306  " test that a bar is recognized after the {event}
307  call s:AddAnAutocmd()
308  augroup vimBarTest| au!BufReadCmd| augroup END
309  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
310
311  " test that a bar is recognized after the {group}
312  call s:AddAnAutocmd()
313  au! vimBarTest|echo 'hello'
314  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
315endfunc
316
317func RemoveGroup()
318  autocmd! StartOK
319  augroup! StartOK
320endfunc
321
322func Test_augroup_warning()
323  augroup TheWarning
324    au VimEnter * echo 'entering'
325  augroup END
326  call assert_match("TheWarning.*VimEnter", execute('au VimEnter'))
327  redir => res
328  augroup! TheWarning
329  redir END
330  call assert_match("W19:", res)
331  call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
332
333  " check "Another" does not take the pace of the deleted entry
334  augroup Another
335  augroup END
336  call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
337  augroup! Another
338
339  " no warning for postpone aucmd delete
340  augroup StartOK
341    au VimEnter * call RemoveGroup()
342  augroup END
343  call assert_match("StartOK.*VimEnter", execute('au VimEnter'))
344  redir => res
345  doautocmd VimEnter
346  redir END
347  call assert_notmatch("W19:", res)
348  au! VimEnter
349
350  call assert_fails('augroup!', 'E471:')
351endfunc
352
353func Test_BufReadCmdHelp()
354  " This used to cause access to free memory
355  au BufReadCmd * e +h
356  help
357
358  au! BufReadCmd
359endfunc
360
361func Test_BufReadCmdHelpJump()
362  " This used to cause access to free memory
363  au BufReadCmd * e +h{
364  " } to fix highlighting
365  call assert_fails('help', 'E434:')
366
367  au! BufReadCmd
368endfunc
369
370func Test_augroup_deleted()
371  " This caused a crash before E936 was introduced
372  augroup x
373    call assert_fails('augroup! x', 'E936:')
374    au VimEnter * echo
375  augroup end
376  augroup! x
377  call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
378  au! VimEnter
379endfunc
380
381" Tests for autocommands on :close command.
382" This used to be in test13.
383func Test_three_windows()
384  " Clean up buffers, because in some cases this function fails.
385  call s:cleanup_buffers()
386
387  " Write three files and open them, each in a window.
388  " Then go to next window, with autocommand that deletes the previous one.
389  " Do this twice, writing the file.
390  e! Xtestje1
391  call setline(1, 'testje1')
392  w
393  sp Xtestje2
394  call setline(1, 'testje2')
395  w
396  sp Xtestje3
397  call setline(1, 'testje3')
398  w
399  wincmd w
400  au WinLeave Xtestje2 bwipe
401  wincmd w
402  call assert_equal('Xtestje1', expand('%'))
403
404  au WinLeave Xtestje1 bwipe Xtestje3
405  close
406  call assert_equal('Xtestje1', expand('%'))
407
408  " Test deleting the buffer on a Unload event.  If this goes wrong there
409  " will be the ATTENTION prompt.
410  e Xtestje1
411  au!
412  au! BufUnload Xtestje1 bwipe
413  call assert_fails('e Xtestje3', 'E937:')
414  call assert_equal('Xtestje3', expand('%'))
415
416  e Xtestje2
417  sp Xtestje1
418  call assert_fails('e', 'E937:')
419  call assert_equal('Xtestje1', expand('%'))
420
421  " Test changing buffers in a BufWipeout autocommand.  If this goes wrong
422  " there are ml_line errors and/or a Crash.
423  au!
424  only
425  e Xanother
426  e Xtestje1
427  bwipe Xtestje2
428  bwipe Xtestje3
429  au BufWipeout Xtestje1 buf Xtestje1
430  bwipe
431  call assert_equal('Xanother', expand('%'))
432
433  only
434  help
435  wincmd w
436  1quit
437  call assert_equal('Xanother', expand('%'))
438
439  au!
440  enew
441  call delete('Xtestje1')
442  call delete('Xtestje2')
443  call delete('Xtestje3')
444endfunc
445
446func Test_BufEnter()
447  au! BufEnter
448  au Bufenter * let val = val . '+'
449  let g:val = ''
450  split NewFile
451  call assert_equal('+', g:val)
452  bwipe!
453  call assert_equal('++', g:val)
454
455  " Also get BufEnter when editing a directory
456  call mkdir('Xdir')
457  split Xdir
458  call assert_equal('+++', g:val)
459
460  " On MS-Windows we can't edit the directory, make sure we wipe the right
461  " buffer.
462  bwipe! Xdir
463
464  call delete('Xdir', 'd')
465  au! BufEnter
466endfunc
467
468" Closing a window might cause an endless loop
469" E814 for older Vims
470func Test_autocmd_bufwipe_in_SessLoadPost()
471  edit Xtest
472  tabnew
473  file Xsomething
474  set noswapfile
475  mksession!
476
477  let content =<< trim [CODE]
478    call test_override('ui_delay', 10)
479    set nocp noswapfile
480    let v:swapchoice = "e"
481    augroup test_autocmd_sessionload
482    autocmd!
483    autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!"
484    augroup END
485
486    func WriteErrors()
487      call writefile([execute("messages")], "Xerrors")
488    endfunc
489    au VimLeave * call WriteErrors()
490  [CODE]
491
492  call writefile(content, 'Xvimrc')
493  call system(GetVimCommand('Xvimrc') .. ' --not-a-term --noplugins -S Session.vim -c cq')
494  let errors = join(readfile('Xerrors'))
495  call assert_match('E814:', errors)
496
497  set swapfile
498  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
499    call delete(file)
500  endfor
501endfunc
502
503" SEGV occurs in older versions.
504func Test_autocmd_bufwipe_in_SessLoadPost2()
505  tabnew
506  set noswapfile
507  mksession!
508
509  let content =<< trim [CODE]
510    set nocp noswapfile
511    function! DeleteInactiveBufs()
512      tabfirst
513      let tabblist = []
514      for i in range(1, tabpagenr(''$''))
515        call extend(tabblist, tabpagebuflist(i))
516      endfor
517      for b in range(1, bufnr(''$''))
518        if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')
519          exec ''bwipeout '' . b
520        endif
521      endfor
522      echomsg "SessionLoadPost DONE"
523    endfunction
524    au SessionLoadPost * call DeleteInactiveBufs()
525
526    func WriteErrors()
527      call writefile([execute("messages")], "Xerrors")
528    endfunc
529    au VimLeave * call WriteErrors()
530  [CODE]
531
532  call writefile(content, 'Xvimrc')
533  call system(GetVimCommand('Xvimrc') .. ' --not-a-term --noplugins -S Session.vim -c cq')
534  let errors = join(readfile('Xerrors'))
535  " This probably only ever matches on unix.
536  call assert_notmatch('Caught deadly signal SEGV', errors)
537  call assert_match('SessionLoadPost DONE', errors)
538
539  set swapfile
540  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
541    call delete(file)
542  endfor
543endfunc
544
545func Test_empty_doau()
546  doau \|
547endfunc
548
549func s:AutoCommandOptionSet(match)
550  let template = "Option: <%s>, OldVal: <%s>, OldValLocal: <%s>, OldValGlobal: <%s>, NewVal: <%s>, Scope: <%s>, Command: <%s>\n"
551  let item     = remove(g:options, 0)
552  let expected = printf(template, item[0], item[1], item[2], item[3], item[4], item[5], item[6])
553  let actual   = printf(template, a:match, v:option_old, v:option_oldlocal, v:option_oldglobal, v:option_new, v:option_type, v:option_command)
554  let g:opt    = [expected, actual]
555  "call assert_equal(expected, actual)
556endfunc
557
558func Test_OptionSet()
559  CheckOption autochdir
560
561  badd test_autocmd.vim
562
563  call test_override('starting', 1)
564  set nocp
565  au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>"))
566
567  " 1: Setting number option"
568  let g:options = [['number', 0, 0, 0, 1, 'global', 'set']]
569  set nu
570  call assert_equal([], g:options)
571  call assert_equal(g:opt[0], g:opt[1])
572
573  " 2: Setting local number option"
574  let g:options = [['number', 1, 1, '', 0, 'local', 'setlocal']]
575  setlocal nonu
576  call assert_equal([], g:options)
577  call assert_equal(g:opt[0], g:opt[1])
578
579  " 3: Setting global number option"
580  let g:options = [['number', 1, '', 1, 0, 'global', 'setglobal']]
581  setglobal nonu
582  call assert_equal([], g:options)
583  call assert_equal(g:opt[0], g:opt[1])
584
585  " 4: Setting local autoindent option"
586  let g:options = [['autoindent', 0, 0, '', 1, 'local', 'setlocal']]
587  setlocal ai
588  call assert_equal([], g:options)
589  call assert_equal(g:opt[0], g:opt[1])
590
591  " 5: Setting global autoindent option"
592  let g:options = [['autoindent', 0, '', 0, 1, 'global', 'setglobal']]
593  setglobal ai
594  call assert_equal([], g:options)
595  call assert_equal(g:opt[0], g:opt[1])
596
597  " 6: Setting global autoindent option"
598  let g:options = [['autoindent', 1, 1, 1, 0, 'global', 'set']]
599  set ai!
600  call assert_equal([], g:options)
601  call assert_equal(g:opt[0], g:opt[1])
602
603  " 6a: Setting global autoindent option"
604  let g:options = [['autoindent', 1, 1, 0, 0, 'global', 'set']]
605  noa setlocal ai
606  noa setglobal noai
607  set ai!
608  call assert_equal([], g:options)
609  call assert_equal(g:opt[0], g:opt[1])
610
611  " Should not print anything, use :noa
612  " 7: don't trigger OptionSet"
613  let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
614  noa set nonu
615  call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
616  call assert_equal(g:opt[0], g:opt[1])
617
618  " 8: Setting several global list and number option"
619  let g:options = [['list', 0, 0, 0, 1, 'global', 'set'], ['number', 0, 0, 0, 1, 'global', 'set']]
620  set list nu
621  call assert_equal([], g:options)
622  call assert_equal(g:opt[0], g:opt[1])
623
624  " 9: don't trigger OptionSet"
625  let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
626  noa set nolist nonu
627  call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
628  call assert_equal(g:opt[0], g:opt[1])
629
630  " 10: Setting global acd"
631  let g:options = [['autochdir', 0, 0, '', 1, 'local', 'setlocal']]
632  setlocal acd
633  call assert_equal([], g:options)
634  call assert_equal(g:opt[0], g:opt[1])
635
636  " 11: Setting global autoread (also sets local value)"
637  let g:options = [['autoread', 0, 0, 0, 1, 'global', 'set']]
638  set ar
639  call assert_equal([], g:options)
640  call assert_equal(g:opt[0], g:opt[1])
641
642  " 12: Setting local autoread"
643  let g:options = [['autoread', 1, 1, '', 1, 'local', 'setlocal']]
644  setlocal ar
645  call assert_equal([], g:options)
646  call assert_equal(g:opt[0], g:opt[1])
647
648  " 13: Setting global autoread"
649  let g:options = [['autoread', 1, '', 1, 0, 'global', 'setglobal']]
650  setglobal invar
651  call assert_equal([], g:options)
652  call assert_equal(g:opt[0], g:opt[1])
653
654  " 14: Setting option backspace through :let"
655  let g:options = [['backspace', '', '', '', 'eol,indent,start', 'global', 'set']]
656  let &bs = "eol,indent,start"
657  call assert_equal([], g:options)
658  call assert_equal(g:opt[0], g:opt[1])
659
660  " 15: Setting option backspace through setbufvar()"
661  let g:options = [['backup', 0, 0, '', 1, 'local', 'setlocal']]
662  " try twice, first time, shouldn't trigger because option name is invalid,
663  " second time, it should trigger
664  let bnum = bufnr('%')
665  call assert_fails("call setbufvar(bnum, '&l:bk', 1)", 'E355:')
666  " should trigger, use correct option name
667  call setbufvar(bnum, '&backup', 1)
668  call assert_equal([], g:options)
669  call assert_equal(g:opt[0], g:opt[1])
670
671  " 16: Setting number option using setwinvar"
672  let g:options = [['number', 0, 0, '', 1, 'local', 'setlocal']]
673  call setwinvar(0, '&number', 1)
674  call assert_equal([], g:options)
675  call assert_equal(g:opt[0], g:opt[1])
676
677  " 17: Setting key option, shouldn't trigger"
678  let g:options = [['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']]
679  setlocal key=blah
680  setlocal key=
681  call assert_equal([['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']], g:options)
682  call assert_equal(g:opt[0], g:opt[1])
683
684
685  " 18a: Setting string global option"
686  let oldval = &backupext
687  let g:options = [['backupext', oldval, oldval, oldval, 'foo', 'global', 'set']]
688  set backupext=foo
689  call assert_equal([], g:options)
690  call assert_equal(g:opt[0], g:opt[1])
691
692  " 18b: Resetting string global option"
693  let g:options = [['backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
694  set backupext&
695  call assert_equal([], g:options)
696  call assert_equal(g:opt[0], g:opt[1])
697
698  " 18c: Setting global string global option"
699  let g:options = [['backupext', oldval, '', oldval, 'bar', 'global', 'setglobal']]
700  setglobal backupext=bar
701  call assert_equal([], g:options)
702  call assert_equal(g:opt[0], g:opt[1])
703
704  " 18d: Setting local string global option"
705  " As this is a global option this sets the global value even though
706  " :setlocal is used!
707  noa set backupext& " Reset global and local value (without triggering autocmd)
708  let g:options = [['backupext', oldval, oldval, '', 'baz', 'local', 'setlocal']]
709  setlocal backupext=baz
710  call assert_equal([], g:options)
711  call assert_equal(g:opt[0], g:opt[1])
712
713  " 18e: Setting again string global option"
714  noa setglobal backupext=ext_global " Reset global and local value (without triggering autocmd)
715  noa setlocal backupext=ext_local " Sets the global(!) value!
716  let g:options = [['backupext', 'ext_local', 'ext_local', 'ext_local', 'fuu', 'global', 'set']]
717  set backupext=fuu
718  call assert_equal([], g:options)
719  call assert_equal(g:opt[0], g:opt[1])
720
721
722  " 19a: Setting string local-global (to buffer) option"
723  let oldval = &tags
724  let g:options = [['tags', oldval, oldval, oldval, 'tagpath', 'global', 'set']]
725  set tags=tagpath
726  call assert_equal([], g:options)
727  call assert_equal(g:opt[0], g:opt[1])
728
729  " 19b: Resetting string local-global (to buffer) option"
730  let g:options = [['tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set']]
731  set tags&
732  call assert_equal([], g:options)
733  call assert_equal(g:opt[0], g:opt[1])
734
735  " 19c: Setting global string local-global (to buffer) option "
736  let g:options = [['tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal']]
737  setglobal tags=tagpath1
738  call assert_equal([], g:options)
739  call assert_equal(g:opt[0], g:opt[1])
740
741  " 19d: Setting local string local-global (to buffer) option"
742  let g:options = [['tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal']]
743  setlocal tags=tagpath2
744  call assert_equal([], g:options)
745  call assert_equal(g:opt[0], g:opt[1])
746
747  " 19e: Setting again string local-global (to buffer) option"
748  " Note: v:option_old is the old global value for local-global string options
749  " but the old local value for all other kinds of options.
750  noa setglobal tags=tag_global " Reset global and local value (without triggering autocmd)
751  noa setlocal tags=tag_local
752  let g:options = [['tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set']]
753  set tags=tagpath
754  call assert_equal([], g:options)
755  call assert_equal(g:opt[0], g:opt[1])
756
757  " 19f: Setting string local-global (to buffer) option to an empty string"
758  " Note: v:option_old is the old global value for local-global string options
759  " but the old local value for all other kinds of options.
760  noa set tags=tag_global " Reset global and local value (without triggering autocmd)
761  noa setlocal tags= " empty string
762  let g:options = [['tags', 'tag_global', '', 'tag_global', 'tagpath', 'global', 'set']]
763  set tags=tagpath
764  call assert_equal([], g:options)
765  call assert_equal(g:opt[0], g:opt[1])
766
767
768  " 20a: Setting string local (to buffer) option"
769  let oldval = &spelllang
770  let g:options = [['spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set']]
771  set spelllang=elvish,klingon
772  call assert_equal([], g:options)
773  call assert_equal(g:opt[0], g:opt[1])
774
775  " 20b: Resetting string local (to buffer) option"
776  let g:options = [['spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set']]
777  set spelllang&
778  call assert_equal([], g:options)
779  call assert_equal(g:opt[0], g:opt[1])
780
781  " 20c: Setting global string local (to buffer) option"
782  let g:options = [['spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal']]
783  setglobal spelllang=elvish
784  call assert_equal([], g:options)
785  call assert_equal(g:opt[0], g:opt[1])
786
787  " 20d: Setting local string local (to buffer) option"
788  noa set spelllang& " Reset global and local value (without triggering autocmd)
789  let g:options = [['spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal']]
790  setlocal spelllang=klingon
791  call assert_equal([], g:options)
792  call assert_equal(g:opt[0], g:opt[1])
793
794  " 20e: Setting again string local (to buffer) option"
795  " Note: v:option_old is the old global value for local-global string options
796  " but the old local value for all other kinds of options.
797  noa setglobal spelllang=spellglobal " Reset global and local value (without triggering autocmd)
798  noa setlocal spelllang=spelllocal
799  let g:options = [['spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set']]
800  set spelllang=foo
801  call assert_equal([], g:options)
802  call assert_equal(g:opt[0], g:opt[1])
803
804
805  " 21a: Setting string local-global (to window) option"
806  let oldval = &statusline
807  let g:options = [['statusline', oldval, oldval, oldval, 'foo', 'global', 'set']]
808  set statusline=foo
809  call assert_equal([], g:options)
810  call assert_equal(g:opt[0], g:opt[1])
811
812  " 21b: Resetting string local-global (to window) option"
813  " Note: v:option_old is the old global value for local-global string options
814  " but the old local value for all other kinds of options.
815  let g:options = [['statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
816  set statusline&
817  call assert_equal([], g:options)
818  call assert_equal(g:opt[0], g:opt[1])
819
820  " 21c: Setting global string local-global (to window) option"
821  let g:options = [['statusline', oldval, '', oldval, 'bar', 'global', 'setglobal']]
822  setglobal statusline=bar
823  call assert_equal([], g:options)
824  call assert_equal(g:opt[0], g:opt[1])
825
826  " 21d: Setting local string local-global (to window) option"
827  noa set statusline& " Reset global and local value (without triggering autocmd)
828  let g:options = [['statusline', oldval, oldval, '', 'baz', 'local', 'setlocal']]
829  setlocal statusline=baz
830  call assert_equal([], g:options)
831  call assert_equal(g:opt[0], g:opt[1])
832
833  " 21e: Setting again string local-global (to window) option"
834  " Note: v:option_old is the old global value for local-global string options
835  " but the old local value for all other kinds of options.
836  noa setglobal statusline=bar " Reset global and local value (without triggering autocmd)
837  noa setlocal statusline=baz
838  let g:options = [['statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set']]
839  set statusline=foo
840  call assert_equal([], g:options)
841  call assert_equal(g:opt[0], g:opt[1])
842
843
844  " 22a: Setting string local (to window) option"
845  let oldval = &foldignore
846  let g:options = [['foldignore', oldval, oldval, oldval, 'fo', 'global', 'set']]
847  set foldignore=fo
848  call assert_equal([], g:options)
849  call assert_equal(g:opt[0], g:opt[1])
850
851  " 22b: Resetting string local (to window) option"
852  let g:options = [['foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set']]
853  set foldignore&
854  call assert_equal([], g:options)
855  call assert_equal(g:opt[0], g:opt[1])
856
857  " 22c: Setting global string local (to window) option"
858  let g:options = [['foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal']]
859  setglobal foldignore=bar
860  call assert_equal([], g:options)
861  call assert_equal(g:opt[0], g:opt[1])
862
863  " 22d: Setting local string local (to window) option"
864  noa set foldignore& " Reset global and local value (without triggering autocmd)
865  let g:options = [['foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal']]
866  setlocal foldignore=baz
867  call assert_equal([], g:options)
868  call assert_equal(g:opt[0], g:opt[1])
869
870  " 22e: Setting again string local (to window) option"
871  noa setglobal foldignore=glob " Reset global and local value (without triggering autocmd)
872  noa setlocal foldignore=loc
873  let g:options = [['foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set']]
874  set foldignore=fo
875  call assert_equal([], g:options)
876  call assert_equal(g:opt[0], g:opt[1])
877
878
879  " 23a: Setting global number local option"
880  noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
881  noa setlocal cmdheight=1 " Sets the global(!) value!
882  let g:options = [['cmdheight', '1', '', '1', '2', 'global', 'setglobal']]
883  setglobal cmdheight=2
884  call assert_equal([], g:options)
885  call assert_equal(g:opt[0], g:opt[1])
886
887  " 23b: Setting local number global option"
888  noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
889  noa setlocal cmdheight=1 " Sets the global(!) value!
890  let g:options = [['cmdheight', '1', '1', '', '2', 'local', 'setlocal']]
891  setlocal cmdheight=2
892  call assert_equal([], g:options)
893  call assert_equal(g:opt[0], g:opt[1])
894
895  " 23c: Setting again number global option"
896  noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
897  noa setlocal cmdheight=1 " Sets the global(!) value!
898  let g:options = [['cmdheight', '1', '1', '1', '2', 'global', 'set']]
899  set cmdheight=2
900  call assert_equal([], g:options)
901  call assert_equal(g:opt[0], g:opt[1])
902
903  " 23d: Setting again number global option"
904  noa set cmdheight=8 " Reset global and local value (without triggering autocmd)
905  let g:options = [['cmdheight', '8', '8', '8', '2', 'global', 'set']]
906  set cmdheight=2
907  call assert_equal([], g:options)
908  call assert_equal(g:opt[0], g:opt[1])
909
910
911  " 24a: Setting global number global-local (to buffer) option"
912  noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
913  noa setlocal undolevels=1
914  let g:options = [['undolevels', '8', '', '8', '2', 'global', 'setglobal']]
915  setglobal undolevels=2
916  call assert_equal([], g:options)
917  call assert_equal(g:opt[0], g:opt[1])
918
919  " 24b: Setting local number global-local (to buffer) option"
920  noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
921  noa setlocal undolevels=1
922  let g:options = [['undolevels', '1', '1', '', '2', 'local', 'setlocal']]
923  setlocal undolevels=2
924  call assert_equal([], g:options)
925  call assert_equal(g:opt[0], g:opt[1])
926
927  " 24c: Setting again number global-local (to buffer) option"
928  noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
929  noa setlocal undolevels=1
930  let g:options = [['undolevels', '1', '1', '8', '2', 'global', 'set']]
931  set undolevels=2
932  call assert_equal([], g:options)
933  call assert_equal(g:opt[0], g:opt[1])
934
935  " 24d: Setting again global number global-local (to buffer) option"
936  noa set undolevels=8 " Reset global and local value (without triggering autocmd)
937  let g:options = [['undolevels', '8', '8', '8', '2', 'global', 'set']]
938  set undolevels=2
939  call assert_equal([], g:options)
940  call assert_equal(g:opt[0], g:opt[1])
941
942
943  " 25a: Setting global number local (to buffer) option"
944  noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
945  noa setlocal wrapmargin=1
946  let g:options = [['wrapmargin', '8', '', '8', '2', 'global', 'setglobal']]
947  setglobal wrapmargin=2
948  call assert_equal([], g:options)
949  call assert_equal(g:opt[0], g:opt[1])
950
951  " 25b: Setting local number local (to buffer) option"
952  noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
953  noa setlocal wrapmargin=1
954  let g:options = [['wrapmargin', '1', '1', '', '2', 'local', 'setlocal']]
955  setlocal wrapmargin=2
956  call assert_equal([], g:options)
957  call assert_equal(g:opt[0], g:opt[1])
958
959  " 25c: Setting again number local (to buffer) option"
960  noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
961  noa setlocal wrapmargin=1
962  let g:options = [['wrapmargin', '1', '1', '8', '2', 'global', 'set']]
963  set wrapmargin=2
964  call assert_equal([], g:options)
965  call assert_equal(g:opt[0], g:opt[1])
966
967  " 25d: Setting again global number local (to buffer) option"
968  noa set wrapmargin=8 " Reset global and local value (without triggering autocmd)
969  let g:options = [['wrapmargin', '8', '8', '8', '2', 'global', 'set']]
970  set wrapmargin=2
971  call assert_equal([], g:options)
972  call assert_equal(g:opt[0], g:opt[1])
973
974
975  " 26: Setting number global-local (to window) option.
976  " Such option does currently not exist.
977
978
979  " 27a: Setting global number local (to window) option"
980  noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
981  noa setlocal foldcolumn=1
982  let g:options = [['foldcolumn', '8', '', '8', '2', 'global', 'setglobal']]
983  setglobal foldcolumn=2
984  call assert_equal([], g:options)
985  call assert_equal(g:opt[0], g:opt[1])
986
987  " 27b: Setting local number local (to window) option"
988  noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
989  noa setlocal foldcolumn=1
990  let g:options = [['foldcolumn', '1', '1', '', '2', 'local', 'setlocal']]
991  setlocal foldcolumn=2
992  call assert_equal([], g:options)
993  call assert_equal(g:opt[0], g:opt[1])
994
995  " 27c: Setting again number local (to window) option"
996  noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
997  noa setlocal foldcolumn=1
998  let g:options = [['foldcolumn', '1', '1', '8', '2', 'global', 'set']]
999  set foldcolumn=2
1000  call assert_equal([], g:options)
1001  call assert_equal(g:opt[0], g:opt[1])
1002
1003  " 27d: Ssettin again global number local (to window) option"
1004  noa set foldcolumn=8 " Reset global and local value (without triggering autocmd)
1005  let g:options = [['foldcolumn', '8', '8', '8', '2', 'global', 'set']]
1006  set foldcolumn=2
1007  call assert_equal([], g:options)
1008  call assert_equal(g:opt[0], g:opt[1])
1009
1010
1011  " 28a: Setting global boolean global option"
1012  noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
1013  noa setlocal wrapscan " Sets the global(!) value!
1014  let g:options = [['wrapscan', '1', '', '1', '0', 'global', 'setglobal']]
1015  setglobal nowrapscan
1016  call assert_equal([], g:options)
1017  call assert_equal(g:opt[0], g:opt[1])
1018
1019  " 28b: Setting local boolean global option"
1020  noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
1021  noa setlocal wrapscan " Sets the global(!) value!
1022  let g:options = [['wrapscan', '1', '1', '', '0', 'local', 'setlocal']]
1023  setlocal nowrapscan
1024  call assert_equal([], g:options)
1025  call assert_equal(g:opt[0], g:opt[1])
1026
1027  " 28c: Setting again boolean global option"
1028  noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
1029  noa setlocal wrapscan " Sets the global(!) value!
1030  let g:options = [['wrapscan', '1', '1', '1', '0', 'global', 'set']]
1031  set nowrapscan
1032  call assert_equal([], g:options)
1033  call assert_equal(g:opt[0], g:opt[1])
1034
1035  " 28d: Setting again global boolean global option"
1036  noa set nowrapscan " Reset global and local value (without triggering autocmd)
1037  let g:options = [['wrapscan', '0', '0', '0', '1', 'global', 'set']]
1038  set wrapscan
1039  call assert_equal([], g:options)
1040  call assert_equal(g:opt[0], g:opt[1])
1041
1042
1043  " 29a: Setting global boolean global-local (to buffer) option"
1044  noa setglobal noautoread " Reset global and local value (without triggering autocmd)
1045  noa setlocal autoread
1046  let g:options = [['autoread', '0', '', '0', '1', 'global', 'setglobal']]
1047  setglobal autoread
1048  call assert_equal([], g:options)
1049  call assert_equal(g:opt[0], g:opt[1])
1050
1051  " 29b: Setting local boolean global-local (to buffer) option"
1052  noa setglobal noautoread " Reset global and local value (without triggering autocmd)
1053  noa setlocal autoread
1054  let g:options = [['autoread', '1', '1', '', '0', 'local', 'setlocal']]
1055  setlocal noautoread
1056  call assert_equal([], g:options)
1057  call assert_equal(g:opt[0], g:opt[1])
1058
1059  " 29c: Setting again boolean global-local (to buffer) option"
1060  noa setglobal noautoread " Reset global and local value (without triggering autocmd)
1061  noa setlocal autoread
1062  let g:options = [['autoread', '1', '1', '0', '1', 'global', 'set']]
1063  set autoread
1064  call assert_equal([], g:options)
1065  call assert_equal(g:opt[0], g:opt[1])
1066
1067  " 29d: Setting again global boolean global-local (to buffer) option"
1068  noa set noautoread " Reset global and local value (without triggering autocmd)
1069  let g:options = [['autoread', '0', '0', '0', '1', 'global', 'set']]
1070  set autoread
1071  call assert_equal([], g:options)
1072  call assert_equal(g:opt[0], g:opt[1])
1073
1074
1075  " 30a: Setting global boolean local (to buffer) option"
1076  noa setglobal nocindent " Reset global and local value (without triggering autocmd)
1077  noa setlocal cindent
1078  let g:options = [['cindent', '0', '', '0', '1', 'global', 'setglobal']]
1079  setglobal cindent
1080  call assert_equal([], g:options)
1081  call assert_equal(g:opt[0], g:opt[1])
1082
1083  " 30b: Setting local boolean local (to buffer) option"
1084  noa setglobal nocindent " Reset global and local value (without triggering autocmd)
1085  noa setlocal cindent
1086  let g:options = [['cindent', '1', '1', '', '0', 'local', 'setlocal']]
1087  setlocal nocindent
1088  call assert_equal([], g:options)
1089  call assert_equal(g:opt[0], g:opt[1])
1090
1091  " 30c: Setting again boolean local (to buffer) option"
1092  noa setglobal nocindent " Reset global and local value (without triggering autocmd)
1093  noa setlocal cindent
1094  let g:options = [['cindent', '1', '1', '0', '1', 'global', 'set']]
1095  set cindent
1096  call assert_equal([], g:options)
1097  call assert_equal(g:opt[0], g:opt[1])
1098
1099  " 30d: Setting again global boolean local (to buffer) option"
1100  noa set nocindent " Reset global and local value (without triggering autocmd)
1101  let g:options = [['cindent', '0', '0', '0', '1', 'global', 'set']]
1102  set cindent
1103  call assert_equal([], g:options)
1104  call assert_equal(g:opt[0], g:opt[1])
1105
1106
1107  " 31: Setting boolean global-local (to window) option
1108  " Currently no such option exists.
1109
1110
1111  " 32a: Setting global boolean local (to window) option"
1112  noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
1113  noa setlocal cursorcolumn
1114  let g:options = [['cursorcolumn', '0', '', '0', '1', 'global', 'setglobal']]
1115  setglobal cursorcolumn
1116  call assert_equal([], g:options)
1117  call assert_equal(g:opt[0], g:opt[1])
1118
1119  " 32b: Setting local boolean local (to window) option"
1120  noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
1121  noa setlocal cursorcolumn
1122  let g:options = [['cursorcolumn', '1', '1', '', '0', 'local', 'setlocal']]
1123  setlocal nocursorcolumn
1124  call assert_equal([], g:options)
1125  call assert_equal(g:opt[0], g:opt[1])
1126
1127  " 32c: Setting again boolean local (to window) option"
1128  noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
1129  noa setlocal cursorcolumn
1130  let g:options = [['cursorcolumn', '1', '1', '0', '1', 'global', 'set']]
1131  set cursorcolumn
1132  call assert_equal([], g:options)
1133  call assert_equal(g:opt[0], g:opt[1])
1134
1135  " 32d: Setting again global boolean local (to window) option"
1136  noa set nocursorcolumn " Reset global and local value (without triggering autocmd)
1137  let g:options = [['cursorcolumn', '0', '0', '0', '1', 'global', 'set']]
1138  set cursorcolumn
1139  call assert_equal([], g:options)
1140  call assert_equal(g:opt[0], g:opt[1])
1141
1142
1143  " 33: Test autocommands when an option value is converted internally.
1144  noa set backspace=1 " Reset global and local value (without triggering autocmd)
1145  let g:options = [['backspace', 'indent,eol', 'indent,eol', 'indent,eol', '2', 'global', 'set']]
1146  set backspace=2
1147  call assert_equal([], g:options)
1148  call assert_equal(g:opt[0], g:opt[1])
1149
1150
1151  " Cleanup
1152  au! OptionSet
1153  " set tags&
1154  for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp', 'backupext', 'tags', 'spelllang', 'statusline', 'foldignore', 'cmdheight', 'undolevels', 'wrapmargin', 'foldcolumn', 'wrapscan', 'autoread', 'cindent', 'cursorcolumn']
1155    exe printf(":set %s&vim", opt)
1156  endfor
1157  call test_override('starting', 0)
1158  delfunc! AutoCommandOptionSet
1159endfunc
1160
1161func Test_OptionSet_diffmode()
1162  call test_override('starting', 1)
1163  " 18: Changing an option when entering diff mode
1164  new
1165  au OptionSet diff :let &l:cul = v:option_new
1166
1167  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
1168  call assert_equal(0, &l:cul)
1169  diffthis
1170  call assert_equal(1, &l:cul)
1171
1172  vnew
1173  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
1174  call assert_equal(0, &l:cul)
1175  diffthis
1176  call assert_equal(1, &l:cul)
1177
1178  diffoff
1179  call assert_equal(0, &l:cul)
1180  call assert_equal(1, getwinvar(2, '&l:cul'))
1181  bw!
1182
1183  call assert_equal(1, &l:cul)
1184  diffoff!
1185  call assert_equal(0, &l:cul)
1186  call assert_equal(0, getwinvar(1, '&l:cul'))
1187  bw!
1188
1189  " Cleanup
1190  au! OptionSet
1191  call test_override('starting', 0)
1192endfunc
1193
1194func Test_OptionSet_diffmode_close()
1195  call test_override('starting', 1)
1196  " 19: Try to close the current window when entering diff mode
1197  " should not segfault
1198  new
1199  au OptionSet diff close
1200
1201  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
1202  call assert_fails(':diffthis', 'E788:')
1203  call assert_equal(1, &diff)
1204  vnew
1205  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
1206  call assert_fails(':diffthis', 'E788:')
1207  call assert_equal(1, &diff)
1208  set diffopt-=closeoff
1209  bw!
1210  call assert_fails(':diffoff!', 'E788:')
1211  bw!
1212
1213  " Cleanup
1214  au! OptionSet
1215  call test_override('starting', 0)
1216  "delfunc! AutoCommandOptionSet
1217endfunc
1218
1219" Test for Bufleave autocommand that deletes the buffer we are about to edit.
1220func Test_BufleaveWithDelete()
1221  new | edit Xfile1
1222
1223  augroup test_bufleavewithdelete
1224      autocmd!
1225      autocmd BufLeave Xfile1 bwipe Xfile2
1226  augroup END
1227
1228  call assert_fails('edit Xfile2', 'E143:')
1229  call assert_equal('Xfile1', bufname('%'))
1230
1231  autocmd! test_bufleavewithdelete BufLeave Xfile1
1232  augroup! test_bufleavewithdelete
1233
1234  new
1235  bwipe! Xfile1
1236endfunc
1237
1238" Test for autocommand that changes the buffer list, when doing ":ball".
1239func Test_Acmd_BufAll()
1240  enew!
1241  %bwipe!
1242  call writefile(['Test file Xxx1'], 'Xxx1')
1243  call writefile(['Test file Xxx2'], 'Xxx2')
1244  call writefile(['Test file Xxx3'], 'Xxx3')
1245
1246  " Add three files to the buffer list
1247  split Xxx1
1248  close
1249  split Xxx2
1250  close
1251  split Xxx3
1252  close
1253
1254  " Wipe the buffer when the buffer is opened
1255  au BufReadPost Xxx2 bwipe
1256
1257  call append(0, 'Test file Xxx4')
1258  ball
1259
1260  call assert_equal(2, winnr('$'))
1261  call assert_equal('Xxx1', bufname(winbufnr(winnr('$'))))
1262  wincmd t
1263
1264  au! BufReadPost
1265  %bwipe!
1266  call delete('Xxx1')
1267  call delete('Xxx2')
1268  call delete('Xxx3')
1269  enew! | only
1270endfunc
1271
1272" Test for autocommand that changes current buffer on BufEnter event.
1273" Check if modelines are interpreted for the correct buffer.
1274func Test_Acmd_BufEnter()
1275  %bwipe!
1276  call writefile(['start of test file Xxx1',
1277	      \ "\<Tab>this is a test",
1278	      \ 'end of test file Xxx1'], 'Xxx1')
1279  call writefile(['start of test file Xxx2',
1280	      \ 'vim: set noai :',
1281	      \ "\<Tab>this is a test",
1282	      \ 'end of test file Xxx2'], 'Xxx2')
1283
1284  au BufEnter Xxx2 brew
1285  set ai modeline modelines=3
1286  edit Xxx1
1287  " edit Xxx2, autocmd will do :brew
1288  edit Xxx2
1289  exe "normal G?this is a\<CR>"
1290  " Append text with autoindent to this file
1291  normal othis should be auto-indented
1292  call assert_equal("\<Tab>this should be auto-indented", getline('.'))
1293  call assert_equal(3, line('.'))
1294  " Remove autocmd and edit Xxx2 again
1295  au! BufEnter Xxx2
1296  buf! Xxx2
1297  exe "normal G?this is a\<CR>"
1298  " append text without autoindent to Xxx
1299  normal othis should be in column 1
1300  call assert_equal("this should be in column 1", getline('.'))
1301  call assert_equal(4, line('.'))
1302
1303  %bwipe!
1304  call delete('Xxx1')
1305  call delete('Xxx2')
1306  set ai&vim modeline&vim modelines&vim
1307endfunc
1308
1309" Test for issue #57
1310" do not move cursor on <c-o> when autoindent is set
1311func Test_ai_CTRL_O()
1312  enew!
1313  set ai
1314  let save_fo = &fo
1315  set fo+=r
1316  exe "normal o# abcdef\<Esc>2hi\<CR>\<C-O>d0\<Esc>"
1317  exe "normal o# abcdef\<Esc>2hi\<C-O>d0\<Esc>"
1318  call assert_equal(['# abc', 'def', 'def'], getline(2, 4))
1319
1320  set ai&vim
1321  let &fo = save_fo
1322  enew!
1323endfunc
1324
1325" Test for autocommand that deletes the current buffer on BufLeave event.
1326" Also test deleting the last buffer, should give a new, empty buffer.
1327func Test_BufLeave_Wipe()
1328  %bwipe!
1329  let content = ['start of test file Xxx',
1330	      \ 'this is a test',
1331	      \ 'end of test file Xxx']
1332  call writefile(content, 'Xxx1')
1333  call writefile(content, 'Xxx2')
1334
1335  au BufLeave Xxx2 bwipe
1336  edit Xxx1
1337  split Xxx2
1338  " delete buffer Xxx2, we should be back to Xxx1
1339  bwipe
1340  call assert_equal('Xxx1', bufname('%'))
1341  call assert_equal(1, winnr('$'))
1342
1343  " Create an alternate buffer
1344  %write! test.out
1345  call assert_equal('test.out', bufname('#'))
1346  " delete alternate buffer
1347  bwipe test.out
1348  call assert_equal('Xxx1', bufname('%'))
1349  call assert_equal('', bufname('#'))
1350
1351  au BufLeave Xxx1 bwipe
1352  " delete current buffer, get an empty one
1353  bwipe!
1354  call assert_equal(1, line('$'))
1355  call assert_equal('', bufname('%'))
1356  let g:bufinfo = getbufinfo()
1357  call assert_equal(1, len(g:bufinfo))
1358
1359  call delete('Xxx1')
1360  call delete('Xxx2')
1361  call delete('test.out')
1362  %bwipe
1363  au! BufLeave
1364
1365  " check that bufinfo doesn't contain a pointer to freed memory
1366  call test_garbagecollect_now()
1367endfunc
1368
1369func Test_QuitPre()
1370  edit Xfoo
1371  let winid = win_getid(winnr())
1372  split Xbar
1373  au! QuitPre * let g:afile = expand('<afile>')
1374  " Close the other window, <afile> should be correct.
1375  exe win_id2win(winid) . 'q'
1376  call assert_equal('Xfoo', g:afile)
1377
1378  unlet g:afile
1379  bwipe Xfoo
1380  bwipe Xbar
1381endfunc
1382
1383func Test_Cmdline()
1384  au! CmdlineChanged : let g:text = getcmdline()
1385  let g:text = 0
1386  call feedkeys(":echom 'hello'\<CR>", 'xt')
1387  call assert_equal("echom 'hello'", g:text)
1388  au! CmdlineChanged
1389
1390  au! CmdlineChanged : let g:entered = expand('<afile>')
1391  let g:entered = 0
1392  call feedkeys(":echom 'hello'\<CR>", 'xt')
1393  call assert_equal(':', g:entered)
1394  au! CmdlineChanged
1395
1396  au! CmdlineEnter : let g:entered = expand('<afile>')
1397  au! CmdlineLeave : let g:left = expand('<afile>')
1398  let g:entered = 0
1399  let g:left = 0
1400  call feedkeys(":echo 'hello'\<CR>", 'xt')
1401  call assert_equal(':', g:entered)
1402  call assert_equal(':', g:left)
1403  au! CmdlineEnter
1404  au! CmdlineLeave
1405
1406  let save_shellslash = &shellslash
1407  set noshellslash
1408  au! CmdlineEnter / let g:entered = expand('<afile>')
1409  au! CmdlineLeave / let g:left = expand('<afile>')
1410  let g:entered = 0
1411  let g:left = 0
1412  new
1413  call setline(1, 'hello')
1414  call feedkeys("/hello\<CR>", 'xt')
1415  call assert_equal('/', g:entered)
1416  call assert_equal('/', g:left)
1417  bwipe!
1418  au! CmdlineEnter
1419  au! CmdlineLeave
1420  let &shellslash = save_shellslash
1421endfunc
1422
1423" Test for BufWritePre autocommand that deletes or unloads the buffer.
1424func Test_BufWritePre()
1425  %bwipe
1426  au BufWritePre Xxx1 bunload
1427  au BufWritePre Xxx2 bwipe
1428
1429  call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1')
1430  call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2')
1431
1432  edit Xtest
1433  e! Xxx2
1434  bdel Xtest
1435  e Xxx1
1436  " write it, will unload it and give an error msg
1437  call assert_fails('w', 'E203:')
1438  call assert_equal('Xxx2', bufname('%'))
1439  edit Xtest
1440  e! Xxx2
1441  bwipe Xtest
1442  " write it, will delete the buffer and give an error msg
1443  call assert_fails('w', 'E203:')
1444  call assert_equal('Xxx1', bufname('%'))
1445  au! BufWritePre
1446  call delete('Xxx1')
1447  call delete('Xxx2')
1448endfunc
1449
1450" Test for BufUnload autocommand that unloads all the other buffers
1451func Test_bufunload_all()
1452  call writefile(['Test file Xxx1'], 'Xxx1')"
1453  call writefile(['Test file Xxx2'], 'Xxx2')"
1454
1455  let content =<< trim [CODE]
1456    func UnloadAllBufs()
1457      let i = 1
1458      while i <= bufnr('$')
1459        if i != bufnr('%') && bufloaded(i)
1460          exe  i . 'bunload'
1461        endif
1462        let i += 1
1463      endwhile
1464    endfunc
1465    au BufUnload * call UnloadAllBufs()
1466    au VimLeave * call writefile(['Test Finished'], 'Xout')
1467    edit Xxx1
1468    split Xxx2
1469    q
1470  [CODE]
1471
1472  call writefile(content, 'Xtest')
1473
1474  call delete('Xout')
1475  call system(GetVimCommandClean() .. ' -N --not-a-term -S Xtest')
1476  call assert_true(filereadable('Xout'))
1477
1478  call delete('Xxx1')
1479  call delete('Xxx2')
1480  call delete('Xtest')
1481  call delete('Xout')
1482endfunc
1483
1484" Some tests for buffer-local autocommands
1485func Test_buflocal_autocmd()
1486  let g:bname = ''
1487  edit xx
1488  au BufLeave <buffer> let g:bname = expand("%")
1489  " here, autocommand for xx should trigger.
1490  " but autocommand shall not apply to buffer named <buffer>.
1491  edit somefile
1492  call assert_equal('xx', g:bname)
1493  let g:bname = ''
1494  " here, autocommand shall be auto-deleted
1495  bwipe xx
1496  " autocmd should not trigger
1497  edit xx
1498  call assert_equal('', g:bname)
1499  " autocmd should not trigger
1500  edit somefile
1501  call assert_equal('', g:bname)
1502  enew
1503  unlet g:bname
1504endfunc
1505
1506" Test for "*Cmd" autocommands
1507func Test_Cmd_Autocmds()
1508  call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx')
1509
1510  enew!
1511  au BufReadCmd XtestA 0r Xxx|$del
1512  edit XtestA			" will read text of Xxd instead
1513  call assert_equal('start of Xxx', getline(1))
1514
1515  au BufWriteCmd XtestA call append(line("$"), "write")
1516  write				" will append a line to the file
1517  call assert_equal('write', getline('$'))
1518  call assert_fails('read XtestA', 'E484:')	" should not read anything
1519  call assert_equal('write', getline(4))
1520
1521  " now we have:
1522  " 1	start of Xxx
1523  " 2		abc2
1524  " 3	end of Xxx
1525  " 4	write
1526
1527  au FileReadCmd XtestB '[r Xxx
1528  2r XtestB			" will read Xxx below line 2 instead
1529  call assert_equal('start of Xxx', getline(3))
1530
1531  " now we have:
1532  " 1	start of Xxx
1533  " 2		abc2
1534  " 3	start of Xxx
1535  " 4		abc2
1536  " 5	end of Xxx
1537  " 6	end of Xxx
1538  " 7	write
1539
1540  au FileWriteCmd XtestC '[,']copy $
1541  normal 4GA1
1542  4,5w XtestC			" will copy lines 4 and 5 to the end
1543  call assert_equal("\tabc21", getline(8))
1544  call assert_fails('r XtestC', 'E484:')	" should not read anything
1545  call assert_equal("end of Xxx", getline(9))
1546
1547  " now we have:
1548  " 1	start of Xxx
1549  " 2		abc2
1550  " 3	start of Xxx
1551  " 4		abc21
1552  " 5	end of Xxx
1553  " 6	end of Xxx
1554  " 7	write
1555  " 8		abc21
1556  " 9	end of Xxx
1557
1558  let g:lines = []
1559  au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']")))
1560  w >>XtestD			" will add lines to 'lines'
1561  call assert_equal(9, len(g:lines))
1562  call assert_fails('$r XtestD', 'E484:')	" should not read anything
1563  call assert_equal(9, line('$'))
1564  call assert_equal('end of Xxx', getline('$'))
1565
1566  au BufReadCmd XtestE 0r Xxx|$del
1567  sp XtestE			" split window with test.out
1568  call assert_equal('end of Xxx', getline(3))
1569
1570  let g:lines = []
1571  exe "normal 2Goasdf\<Esc>\<C-W>\<C-W>"
1572  au BufWriteCmd XtestE call extend(g:lines, getline(0, '$'))
1573  wall				" will write other window to 'lines'
1574  call assert_equal(4, len(g:lines), g:lines)
1575  call assert_equal('asdf', g:lines[2])
1576
1577  au! BufReadCmd
1578  au! BufWriteCmd
1579  au! FileReadCmd
1580  au! FileWriteCmd
1581  au! FileAppendCmd
1582  %bwipe!
1583  call delete('Xxx')
1584  enew!
1585endfunc
1586
1587func s:ReadFile()
1588  setl noswapfile nomodified
1589  let filename = resolve(expand("<afile>:p"))
1590  execute 'read' fnameescape(filename)
1591  1d_
1592  exe 'file' fnameescape(filename)
1593  setl buftype=acwrite
1594endfunc
1595
1596func s:WriteFile()
1597  let filename = resolve(expand("<afile>:p"))
1598  setl buftype=
1599  noautocmd execute 'write' fnameescape(filename)
1600  setl buftype=acwrite
1601  setl nomodified
1602endfunc
1603
1604func Test_BufReadCmd()
1605  autocmd BufReadCmd *.test call s:ReadFile()
1606  autocmd BufWriteCmd *.test call s:WriteFile()
1607
1608  call writefile(['one', 'two', 'three'], 'Xcmd.test')
1609  edit Xcmd.test
1610  call assert_match('Xcmd.test" line 1 of 3', execute('file'))
1611  normal! Gofour
1612  write
1613  call assert_equal(['one', 'two', 'three', 'four'], readfile('Xcmd.test'))
1614
1615  bwipe!
1616  call delete('Xcmd.test')
1617  au! BufReadCmd
1618  au! BufWriteCmd
1619endfunc
1620
1621func SetChangeMarks(start, end)
1622  exe a:start. 'mark ['
1623  exe a:end. 'mark ]'
1624endfunc
1625
1626" Verify the effects of autocmds on '[ and ']
1627func Test_change_mark_in_autocmds()
1628  edit! Xtest
1629  call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u", 'xtn')
1630
1631  call SetChangeMarks(2, 3)
1632  write
1633  call assert_equal([1, 4], [line("'["), line("']")])
1634
1635  call SetChangeMarks(2, 3)
1636  au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1637  write
1638  au! BufWritePre
1639
1640  if has('unix')
1641    write XtestFilter
1642    write >> XtestFilter
1643
1644    call SetChangeMarks(2, 3)
1645    " Marks are set to the entire range of the write
1646    au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1647    " '[ is adjusted to just before the line that will receive the filtered
1648    " data
1649    au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")])
1650    " The filtered data is read into the buffer, and the source lines are
1651    " still present, so the range is after the source lines
1652    au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")])
1653    %!cat XtestFilter
1654    " After the filtered data is read, the original lines are deleted
1655    call assert_equal([1, 8], [line("'["), line("']")])
1656    au! FilterWritePre,FilterReadPre,FilterReadPost
1657    undo
1658
1659    call SetChangeMarks(1, 4)
1660    au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1661    au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")])
1662    au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1663    2,3!cat XtestFilter
1664    call assert_equal([2, 9], [line("'["), line("']")])
1665    au! FilterWritePre,FilterReadPre,FilterReadPost
1666    undo
1667
1668    call delete('XtestFilter')
1669  endif
1670
1671  call SetChangeMarks(1, 4)
1672  au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1673  2,3write Xtest2
1674  au! FileWritePre
1675
1676  call SetChangeMarks(2, 3)
1677  au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")])
1678  write >> Xtest2
1679  au! FileAppendPre
1680
1681  call SetChangeMarks(1, 4)
1682  au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")])
1683  2,3write >> Xtest2
1684  au! FileAppendPre
1685
1686  call SetChangeMarks(1, 1)
1687  au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")])
1688  au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1689  3read Xtest2
1690  au! FileReadPre,FileReadPost
1691  undo
1692
1693  call SetChangeMarks(4, 4)
1694  " When the line is 0, it's adjusted to 1
1695  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1696  au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")])
1697  0read Xtest2
1698  au! FileReadPre,FileReadPost
1699  undo
1700
1701  call SetChangeMarks(4, 4)
1702  " When the line is 0, it's adjusted to 1
1703  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1704  au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")])
1705  1read Xtest2
1706  au! FileReadPre,FileReadPost
1707  undo
1708
1709  bwipe!
1710  call delete('Xtest')
1711  call delete('Xtest2')
1712endfunc
1713
1714func Test_Filter_noshelltemp()
1715  CheckExecutable cat
1716
1717  enew!
1718  call setline(1, ['a', 'b', 'c', 'd'])
1719
1720  let shelltemp = &shelltemp
1721  set shelltemp
1722
1723  let g:filter_au = 0
1724  au FilterWritePre * let g:filter_au += 1
1725  au FilterReadPre * let g:filter_au += 1
1726  au FilterReadPost * let g:filter_au += 1
1727  %!cat
1728  call assert_equal(3, g:filter_au)
1729
1730  if has('filterpipe')
1731    set noshelltemp
1732
1733    let g:filter_au = 0
1734    au FilterWritePre * let g:filter_au += 1
1735    au FilterReadPre * let g:filter_au += 1
1736    au FilterReadPost * let g:filter_au += 1
1737    %!cat
1738    call assert_equal(0, g:filter_au)
1739  endif
1740
1741  au! FilterWritePre,FilterReadPre,FilterReadPost
1742  let &shelltemp = shelltemp
1743  bwipe!
1744endfunc
1745
1746func Test_TextYankPost()
1747  enew!
1748  call setline(1, ['foo'])
1749
1750  let g:event = []
1751  au TextYankPost * let g:event = copy(v:event)
1752
1753  call assert_equal({}, v:event)
1754  call assert_fails('let v:event = {}', 'E46:')
1755  call assert_fails('let v:event.mykey = 0', 'E742:')
1756
1757  norm "ayiw
1758  call assert_equal(
1759    \{'regcontents': ['foo'], 'regname': 'a', 'operator': 'y', 'regtype': 'v', 'visual': v:false},
1760    \g:event)
1761  norm y_
1762  call assert_equal(
1763    \{'regcontents': ['foo'], 'regname': '',  'operator': 'y', 'regtype': 'V', 'visual': v:false},
1764    \g:event)
1765  norm Vy
1766  call assert_equal(
1767    \{'regcontents': ['foo'], 'regname': '',  'operator': 'y', 'regtype': 'V', 'visual': v:true},
1768    \g:event)
1769  call feedkeys("\<C-V>y", 'x')
1770  call assert_equal(
1771    \{'regcontents': ['f'], 'regname': '',  'operator': 'y', 'regtype': "\x161", 'visual': v:true},
1772    \g:event)
1773  norm "xciwbar
1774  call assert_equal(
1775    \{'regcontents': ['foo'], 'regname': 'x', 'operator': 'c', 'regtype': 'v', 'visual': v:false},
1776    \g:event)
1777  norm "bdiw
1778  call assert_equal(
1779    \{'regcontents': ['bar'], 'regname': 'b', 'operator': 'd', 'regtype': 'v', 'visual': v:false},
1780    \g:event)
1781
1782  call assert_equal({}, v:event)
1783
1784  if has('clipboard_working') && !has('gui_running')
1785    " Test that when the visual selection is automatically copied to clipboard
1786    " register a TextYankPost is emitted
1787    call setline(1, ['foobar'])
1788
1789    let @* = ''
1790    set clipboard=autoselect
1791    exe "norm! ggviw\<Esc>"
1792    call assert_equal(
1793        \{'regcontents': ['foobar'], 'regname': '*', 'operator': 'y', 'regtype': 'v', 'visual': v:true},
1794        \g:event)
1795
1796    let @+ = ''
1797    set clipboard=autoselectplus
1798    exe "norm! ggviw\<Esc>"
1799    call assert_equal(
1800        \{'regcontents': ['foobar'], 'regname': '+', 'operator': 'y', 'regtype': 'v', 'visual': v:true},
1801        \g:event)
1802
1803    set clipboard&vim
1804  endif
1805
1806  au! TextYankPost
1807  unlet g:event
1808  bwipe!
1809endfunc
1810
1811func Test_nocatch_wipe_all_buffers()
1812  " Real nasty autocommand: wipe all buffers on any event.
1813  au * * bwipe *
1814  call assert_fails('next x', ['E94:', 'E937:'])
1815  bwipe
1816  au!
1817endfunc
1818
1819func Test_nocatch_wipe_dummy_buffer()
1820  CheckFeature quickfix
1821  " Nasty autocommand: wipe buffer on any event.
1822  au * x bwipe
1823  call assert_fails('lv½ /x', 'E937:')
1824  au!
1825endfunc
1826
1827function s:Before_test_dirchanged()
1828  augroup test_dirchanged
1829    autocmd!
1830  augroup END
1831  let s:li = []
1832  let s:dir_this = getcwd()
1833  let s:dir_foo = s:dir_this . '/Xfoo'
1834  call mkdir(s:dir_foo)
1835  let s:dir_bar = s:dir_this . '/Xbar'
1836  call mkdir(s:dir_bar)
1837endfunc
1838
1839function s:After_test_dirchanged()
1840  call chdir(s:dir_this)
1841  call delete(s:dir_foo, 'd')
1842  call delete(s:dir_bar, 'd')
1843  augroup test_dirchanged
1844    autocmd!
1845  augroup END
1846endfunc
1847
1848function Test_dirchanged_global()
1849  call s:Before_test_dirchanged()
1850  autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
1851  autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
1852  call chdir(s:dir_foo)
1853  call assert_equal(["cd:", s:dir_foo], s:li)
1854  call chdir(s:dir_foo)
1855  call assert_equal(["cd:", s:dir_foo], s:li)
1856  exe 'lcd ' .. fnameescape(s:dir_bar)
1857  call assert_equal(["cd:", s:dir_foo], s:li)
1858  call s:After_test_dirchanged()
1859endfunc
1860
1861function Test_dirchanged_local()
1862  call s:Before_test_dirchanged()
1863  autocmd test_dirchanged DirChanged window call add(s:li, "lcd:")
1864  autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>"))
1865  call chdir(s:dir_foo)
1866  call assert_equal([], s:li)
1867  exe 'lcd ' .. fnameescape(s:dir_bar)
1868  call assert_equal(["lcd:", s:dir_bar], s:li)
1869  exe 'lcd ' .. fnameescape(s:dir_bar)
1870  call assert_equal(["lcd:", s:dir_bar], s:li)
1871  call s:After_test_dirchanged()
1872endfunc
1873
1874function Test_dirchanged_auto()
1875  CheckOption autochdir
1876  call s:Before_test_dirchanged()
1877  call test_autochdir()
1878  autocmd test_dirchanged DirChanged auto call add(s:li, "auto:")
1879  autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
1880  set acd
1881  cd ..
1882  call assert_equal([], s:li)
1883  exe 'edit ' . s:dir_foo . '/Xfile'
1884  call assert_equal(s:dir_foo, getcwd())
1885  call assert_equal(["auto:", s:dir_foo], s:li)
1886  set noacd
1887  bwipe!
1888  call s:After_test_dirchanged()
1889endfunc
1890
1891" Test TextChangedI and TextChangedP
1892func Test_ChangedP()
1893  new
1894  call setline(1, ['foo', 'bar', 'foobar'])
1895  call test_override("char_avail", 1)
1896  set complete=. completeopt=menuone
1897
1898  func! TextChangedAutocmd(char)
1899    let g:autocmd .= a:char
1900  endfunc
1901
1902  au! TextChanged <buffer> :call TextChangedAutocmd('N')
1903  au! TextChangedI <buffer> :call TextChangedAutocmd('I')
1904  au! TextChangedP <buffer> :call TextChangedAutocmd('P')
1905
1906  call cursor(3, 1)
1907  let g:autocmd = ''
1908  call feedkeys("o\<esc>", 'tnix')
1909  call assert_equal('I', g:autocmd)
1910
1911  let g:autocmd = ''
1912  call feedkeys("Sf", 'tnix')
1913  call assert_equal('II', g:autocmd)
1914
1915  let g:autocmd = ''
1916  call feedkeys("Sf\<C-N>", 'tnix')
1917  call assert_equal('IIP', g:autocmd)
1918
1919  let g:autocmd = ''
1920  call feedkeys("Sf\<C-N>\<C-N>", 'tnix')
1921  call assert_equal('IIPP', g:autocmd)
1922
1923  let g:autocmd = ''
1924  call feedkeys("Sf\<C-N>\<C-N>\<C-N>", 'tnix')
1925  call assert_equal('IIPPP', g:autocmd)
1926
1927  let g:autocmd = ''
1928  call feedkeys("Sf\<C-N>\<C-N>\<C-N>\<C-N>", 'tnix')
1929  call assert_equal('IIPPPP', g:autocmd)
1930
1931  call assert_equal(['foo', 'bar', 'foobar', 'foo'], getline(1, '$'))
1932  " TODO: how should it handle completeopt=noinsert,noselect?
1933
1934  " CleanUp
1935  call test_override("char_avail", 0)
1936  au! TextChanged
1937  au! TextChangedI
1938  au! TextChangedP
1939  delfu TextChangedAutocmd
1940  unlet! g:autocmd
1941  set complete&vim completeopt&vim
1942
1943  bw!
1944endfunc
1945
1946let g:setline_handled = v:false
1947func SetLineOne()
1948  if !g:setline_handled
1949    call setline(1, "(x)")
1950    let g:setline_handled = v:true
1951  endif
1952endfunc
1953
1954func Test_TextChangedI_with_setline()
1955  new
1956  call test_override('char_avail', 1)
1957  autocmd TextChangedI <buffer> call SetLineOne()
1958  call feedkeys("i(\<CR>\<Esc>", 'tx')
1959  call assert_equal('(', getline(1))
1960  call assert_equal('x)', getline(2))
1961  undo
1962  call assert_equal('', getline(1))
1963  call assert_equal('', getline(2))
1964
1965  call test_override('starting', 0)
1966  bwipe!
1967endfunc
1968
1969func Test_Changed_FirstTime()
1970  CheckFeature terminal
1971  CheckNotGui
1972  " Starting a terminal to run Vim is always considered flaky.
1973  let g:test_is_flaky = 1
1974
1975  " Prepare file for TextChanged event.
1976  call writefile([''], 'Xchanged.txt')
1977  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
1978  call assert_equal('running', term_getstatus(buf))
1979  " Wait for the ruler (in the status line) to be shown.
1980  " In ConPTY, there is additional character which is drawn up to the width of
1981  " the screen.
1982  if has('conpty')
1983    call WaitForAssert({-> assert_match('\<All.*$', term_getline(buf, 3))})
1984  else
1985    call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))})
1986  endif
1987  " It's only adding autocmd, so that no event occurs.
1988  call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>")
1989  call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
1990  call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
1991  call assert_equal([''], readfile('Xchanged.txt'))
1992
1993  " clean up
1994  call delete('Xchanged.txt')
1995  bwipe!
1996endfunc
1997
1998func Test_autocmd_nested()
1999  let g:did_nested = 0
2000  augroup Testing
2001    au WinNew * edit somefile
2002    au BufNew * let g:did_nested = 1
2003  augroup END
2004  split
2005  call assert_equal(0, g:did_nested)
2006  close
2007  bwipe! somefile
2008
2009  " old nested argument still works
2010  augroup Testing
2011    au!
2012    au WinNew * nested edit somefile
2013    au BufNew * let g:did_nested = 1
2014  augroup END
2015  split
2016  call assert_equal(1, g:did_nested)
2017  close
2018  bwipe! somefile
2019
2020  " New ++nested argument works
2021  augroup Testing
2022    au!
2023    au WinNew * ++nested edit somefile
2024    au BufNew * let g:did_nested = 1
2025  augroup END
2026  split
2027  call assert_equal(1, g:did_nested)
2028  close
2029  bwipe! somefile
2030
2031  augroup Testing
2032    au!
2033  augroup END
2034
2035  call assert_fails('au WinNew * ++nested ++nested echo bad', 'E983:')
2036  call assert_fails('au WinNew * nested nested echo bad', 'E983:')
2037endfunc
2038
2039func Test_autocmd_once()
2040  " Without ++once WinNew triggers twice
2041  let g:did_split = 0
2042  augroup Testing
2043    au WinNew * let g:did_split += 1
2044  augroup END
2045  split
2046  split
2047  call assert_equal(2, g:did_split)
2048  call assert_true(exists('#WinNew'))
2049  close
2050  close
2051
2052  " With ++once WinNew triggers once
2053  let g:did_split = 0
2054  augroup Testing
2055    au!
2056    au WinNew * ++once let g:did_split += 1
2057  augroup END
2058  split
2059  split
2060  call assert_equal(1, g:did_split)
2061  call assert_false(exists('#WinNew'))
2062  close
2063  close
2064
2065  call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
2066endfunc
2067
2068func Test_autocmd_bufreadpre()
2069  new
2070  let b:bufreadpre = 1
2071  call append(0, range(1000))
2072  w! XAutocmdBufReadPre.txt
2073  autocmd BufReadPre <buffer> :let b:bufreadpre += 1
2074  norm! 500gg
2075  sp
2076  norm! 1000gg
2077  wincmd p
2078  let g:wsv1 = winsaveview()
2079  wincmd p
2080  let g:wsv2 = winsaveview()
2081  " triggers BufReadPre, should not move the cursor in either window
2082  " The topline may change one line in a large window.
2083  edit
2084  call assert_inrange(g:wsv2.topline - 1, g:wsv2.topline + 1, winsaveview().topline)
2085  call assert_equal(g:wsv2.lnum, winsaveview().lnum)
2086  call assert_equal(2, b:bufreadpre)
2087  wincmd p
2088  call assert_equal(g:wsv1.topline, winsaveview().topline)
2089  call assert_equal(g:wsv1.lnum, winsaveview().lnum)
2090  call assert_equal(2, b:bufreadpre)
2091  " Now set the cursor position in an BufReadPre autocommand
2092  " (even though the position will be invalid, this should make Vim reset the
2093  " cursor position in the other window.
2094  wincmd p
2095  set cpo+=g
2096  " won't do anything, but try to set the cursor on an invalid lnum
2097  autocmd BufReadPre <buffer> :norm! 70gg
2098  " triggers BufReadPre, should not move the cursor in either window
2099  e
2100  call assert_equal(1, winsaveview().topline)
2101  call assert_equal(1, winsaveview().lnum)
2102  call assert_equal(3, b:bufreadpre)
2103  wincmd p
2104  call assert_equal(g:wsv1.topline, winsaveview().topline)
2105  call assert_equal(g:wsv1.lnum, winsaveview().lnum)
2106  call assert_equal(3, b:bufreadpre)
2107  close
2108  close
2109  call delete('XAutocmdBufReadPre.txt')
2110  set cpo-=g
2111endfunc
2112
2113" FileChangedShell tested in test_filechanged.vim
2114
2115" Tests for the following autocommands:
2116" - FileWritePre	writing a compressed file
2117" - FileReadPost	reading a compressed file
2118" - BufNewFile		reading a file template
2119" - BufReadPre		decompressing the file to be read
2120" - FilterReadPre	substituting characters in the temp file
2121" - FilterReadPost	substituting characters after filtering
2122" - FileReadPre		set options for decompression
2123" - FileReadPost	decompress the file
2124func Test_ReadWrite_Autocmds()
2125  " Run this test only on Unix-like systems and if gzip is available
2126  CheckUnix
2127  CheckExecutable gzip
2128
2129  " Make $GZIP empty, "-v" would cause trouble.
2130  let $GZIP = ""
2131
2132  " Use a FileChangedShell autocommand to avoid a prompt for 'Xtestfile.gz'
2133  " being modified outside of Vim (noticed on Solaris).
2134  au FileChangedShell * echo 'caught FileChangedShell'
2135
2136  " Test for the FileReadPost, FileWritePre and FileWritePost autocmds
2137  augroup Test1
2138    au!
2139    au FileWritePre    *.gz   '[,']!gzip
2140    au FileWritePost   *.gz   undo
2141    au FileReadPost    *.gz   '[,']!gzip -d
2142  augroup END
2143
2144  new
2145  set bin
2146  call append(0, [
2147	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2148	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2149	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2150	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2151	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2152	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2153	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2154	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2155	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2156	      \ ])
2157  1,9write! Xtestfile.gz
2158  enew! | close
2159
2160  new
2161  " Read and decompress the testfile
2162  0read Xtestfile.gz
2163  call assert_equal([
2164	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2165	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2166	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2167	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2168	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2169	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2170	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2171	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2172	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2173	      \ ], getline(1, 9))
2174  enew! | close
2175
2176  augroup Test1
2177    au!
2178  augroup END
2179
2180  " Test for the FileAppendPre and FileAppendPost autocmds
2181  augroup Test2
2182    au!
2183    au BufNewFile      *.c    read Xtest.c
2184    au FileAppendPre   *.out  '[,']s/new/NEW/
2185    au FileAppendPost  *.out  !cat Xtest.c >> test.out
2186  augroup END
2187
2188  call writefile(['/*', ' * Here is a new .c file', ' */'], 'Xtest.c')
2189  new foo.c			" should load Xtest.c
2190  call assert_equal(['/*', ' * Here is a new .c file', ' */'], getline(2, 4))
2191  w! >> test.out		" append it to the output file
2192
2193  let contents = readfile('test.out')
2194  call assert_equal(' * Here is a NEW .c file', contents[2])
2195  call assert_equal(' * Here is a new .c file', contents[5])
2196
2197  call delete('test.out')
2198  enew! | close
2199  augroup Test2
2200    au!
2201  augroup END
2202
2203  " Test for the BufReadPre and BufReadPost autocmds
2204  augroup Test3
2205    au!
2206    " setup autocommands to decompress before reading and re-compress
2207    " afterwards
2208    au BufReadPre  *.gz  exe '!gzip -d ' . shellescape(expand("<afile>"))
2209    au BufReadPre  *.gz  call rename(expand("<afile>:r"), expand("<afile>"))
2210    au BufReadPost *.gz  call rename(expand("<afile>"), expand("<afile>:r"))
2211    au BufReadPost *.gz  exe '!gzip ' . shellescape(expand("<afile>:r"))
2212  augroup END
2213
2214  e! Xtestfile.gz		" Edit compressed file
2215  call assert_equal([
2216	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2217	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2218	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2219	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2220	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2221	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2222	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2223	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2224	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2225	      \ ], getline(1, 9))
2226
2227  w! >> test.out		" Append it to the output file
2228
2229  augroup Test3
2230    au!
2231  augroup END
2232
2233  " Test for the FilterReadPre and FilterReadPost autocmds.
2234  set shelltemp			" need temp files here
2235  augroup Test4
2236    au!
2237    au FilterReadPre   *.out  call rename(expand("<afile>"), expand("<afile>") . ".t")
2238    au FilterReadPre   *.out  exe 'silent !sed s/e/E/ ' . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))
2239    au FilterReadPre   *.out  exe 'silent !rm ' . shellescape(expand("<afile>")) . '.t'
2240    au FilterReadPost  *.out  '[,']s/x/X/g
2241  augroup END
2242
2243  e! test.out			" Edit the output file
2244  1,$!cat
2245  call assert_equal([
2246	      \ 'linE 2	AbcdefghijklmnopqrstuvwXyz',
2247	      \ 'linE 3	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2248	      \ 'linE 4	AbcdefghijklmnopqrstuvwXyz',
2249	      \ 'linE 5	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2250	      \ 'linE 6	AbcdefghijklmnopqrstuvwXyz',
2251	      \ 'linE 7	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2252	      \ 'linE 8	AbcdefghijklmnopqrstuvwXyz',
2253	      \ 'linE 9	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2254	      \ 'linE 10 AbcdefghijklmnopqrstuvwXyz'
2255	      \ ], getline(1, 9))
2256  call assert_equal([
2257	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2258	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2259	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2260	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2261	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2262	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2263	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2264	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2265	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2266	      \ ], readfile('test.out'))
2267
2268  augroup Test4
2269    au!
2270  augroup END
2271  set shelltemp&vim
2272
2273  " Test for the FileReadPre and FileReadPost autocmds.
2274  augroup Test5
2275    au!
2276    au FileReadPre *.gz exe 'silent !gzip -d ' . shellescape(expand("<afile>"))
2277    au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
2278    au FileReadPost *.gz '[,']s/l/L/
2279  augroup END
2280
2281  new
2282  0r Xtestfile.gz		" Read compressed file
2283  call assert_equal([
2284	      \ 'Line 2	Abcdefghijklmnopqrstuvwxyz',
2285	      \ 'Line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2286	      \ 'Line 4	Abcdefghijklmnopqrstuvwxyz',
2287	      \ 'Line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2288	      \ 'Line 6	Abcdefghijklmnopqrstuvwxyz',
2289	      \ 'Line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2290	      \ 'Line 8	Abcdefghijklmnopqrstuvwxyz',
2291	      \ 'Line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2292	      \ 'Line 10 Abcdefghijklmnopqrstuvwxyz'
2293	      \ ], getline(1, 9))
2294  call assert_equal([
2295	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2296	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2297	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2298	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2299	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2300	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2301	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2302	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2303	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2304	      \ ], readfile('Xtestfile.gz'))
2305
2306  augroup Test5
2307    au!
2308  augroup END
2309
2310  au! FileChangedShell
2311  call delete('Xtestfile.gz')
2312  call delete('Xtest.c')
2313  call delete('test.out')
2314endfunc
2315
2316func Test_throw_in_BufWritePre()
2317  new
2318  call setline(1, ['one', 'two', 'three'])
2319  call assert_false(filereadable('Xthefile'))
2320  augroup throwing
2321    au BufWritePre X* throw 'do not write'
2322  augroup END
2323  try
2324    w Xthefile
2325  catch
2326    let caught = 1
2327  endtry
2328  call assert_equal(1, caught)
2329  call assert_false(filereadable('Xthefile'))
2330
2331  bwipe!
2332  au! throwing
2333endfunc
2334
2335func Test_autocmd_SafeState()
2336  CheckRunVimInTerminal
2337
2338  let lines =<< trim END
2339	let g:safe = 0
2340	let g:again = ''
2341	au SafeState * let g:safe += 1
2342	au SafeStateAgain * let g:again ..= 'x'
2343	func CallTimer()
2344	  call timer_start(10, {id -> execute('let g:again ..= "t"')})
2345	endfunc
2346  END
2347  call writefile(lines, 'XSafeState')
2348  let buf = RunVimInTerminal('-S XSafeState', #{rows: 6})
2349
2350  " Sometimes we loop to handle a K_IGNORE, SafeState may be triggered once or
2351  " more often.
2352  call term_sendkeys(buf, ":echo g:safe\<CR>")
2353  call WaitForAssert({-> assert_match('^\d ', term_getline(buf, 6))}, 1000)
2354
2355  " SafeStateAgain should be invoked at least three times
2356  call term_sendkeys(buf, ":echo g:again\<CR>")
2357  call WaitForAssert({-> assert_match('^xxx', term_getline(buf, 6))}, 1000)
2358
2359  call term_sendkeys(buf, ":let g:again = ''\<CR>:call CallTimer()\<CR>")
2360  call TermWait(buf, 50)
2361  call term_sendkeys(buf, ":\<CR>")
2362  call TermWait(buf, 50)
2363  call term_sendkeys(buf, ":echo g:again\<CR>")
2364  call WaitForAssert({-> assert_match('xtx', term_getline(buf, 6))}, 1000)
2365
2366  call StopVimInTerminal(buf)
2367  call delete('XSafeState')
2368endfunc
2369
2370func Test_autocmd_CmdWinEnter()
2371  CheckRunVimInTerminal
2372  " There is not cmdwin switch, so
2373  " test for cmdline_hist
2374  " (both are available with small builds)
2375  CheckFeature cmdline_hist
2376  let lines =<< trim END
2377    let b:dummy_var = 'This is a dummy'
2378    autocmd CmdWinEnter * quit
2379    let winnr = winnr('$')
2380  END
2381  let filename = 'XCmdWinEnter'
2382  call writefile(lines, filename)
2383  let buf = RunVimInTerminal('-S '.filename, #{rows: 6})
2384
2385  call term_sendkeys(buf, "q:")
2386  call TermWait(buf)
2387  call term_sendkeys(buf, ":echo b:dummy_var\<cr>")
2388  call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000)
2389  call term_sendkeys(buf, ":echo &buftype\<cr>")
2390  call WaitForAssert({-> assert_notmatch('^nofile', term_getline(buf, 6))}, 1000)
2391  call term_sendkeys(buf, ":echo winnr\<cr>")
2392  call WaitForAssert({-> assert_match('^1', term_getline(buf, 6))}, 1000)
2393
2394  " clean up
2395  call StopVimInTerminal(buf)
2396  call delete(filename)
2397endfunc
2398
2399func Test_autocmd_was_using_freed_memory()
2400  CheckFeature quickfix
2401
2402  pedit xx
2403  n x
2404  au WinEnter * quit
2405  split
2406  au! WinEnter
2407endfunc
2408
2409func Test_BufWrite_lockmarks()
2410  edit! Xtest
2411  call setline(1, ['a', 'b', 'c', 'd'])
2412
2413  " :lockmarks preserves the marks
2414  call SetChangeMarks(2, 3)
2415  lockmarks write
2416  call assert_equal([2, 3], [line("'["), line("']")])
2417
2418  " *WritePre autocmds get the correct line range, but lockmarks preserves the
2419  " original values for the user
2420  augroup lockmarks
2421    au!
2422    au BufWritePre,FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
2423    au FileWritePre * call assert_equal([3, 4], [line("'["), line("']")])
2424  augroup END
2425
2426  lockmarks write
2427  call assert_equal([2, 3], [line("'["), line("']")])
2428
2429  if executable('cat')
2430    lockmarks %!cat
2431    call assert_equal([2, 3], [line("'["), line("']")])
2432  endif
2433
2434  lockmarks 3,4write Xtest2
2435  call assert_equal([2, 3], [line("'["), line("']")])
2436
2437  au! lockmarks
2438  augroup! lockmarks
2439  call delete('Xtest')
2440  call delete('Xtest2')
2441endfunc
2442
2443func Test_FileType_spell()
2444  if !isdirectory('/tmp')
2445    throw "Skipped: requires /tmp directory"
2446  endif
2447
2448  " this was crashing with an invalid free()
2449  setglobal spellfile=/tmp/en.utf-8.add
2450  augroup crash
2451    autocmd!
2452    autocmd BufNewFile,BufReadPost crashfile setf somefiletype
2453    autocmd BufNewFile,BufReadPost crashfile set ft=anotherfiletype
2454    autocmd FileType anotherfiletype setlocal spell
2455  augroup END
2456  func! NoCrash() abort
2457    edit /tmp/crashfile
2458  endfunc
2459  call NoCrash()
2460
2461  au! crash
2462  setglobal spellfile=
2463endfunc
2464
2465" Test closing a window or editing another buffer from a FileChangedRO handler
2466" in a readonly buffer
2467func Test_FileChangedRO_winclose()
2468  call test_override('ui_delay', 10)
2469
2470  augroup FileChangedROTest
2471    au!
2472    autocmd FileChangedRO * quit
2473  augroup END
2474  new
2475  set readonly
2476  call assert_fails('normal i', 'E788:')
2477  close
2478  augroup! FileChangedROTest
2479
2480  augroup FileChangedROTest
2481    au!
2482    autocmd FileChangedRO * edit Xfile
2483  augroup END
2484  new
2485  set readonly
2486  call assert_fails('normal i', 'E788:')
2487  close
2488  augroup! FileChangedROTest
2489  call test_override('ALL', 0)
2490endfunc
2491
2492func LogACmd()
2493  call add(g:logged, line('$'))
2494endfunc
2495
2496func Test_TermChanged()
2497  CheckNotGui
2498
2499  enew!
2500  tabnew
2501  call setline(1, ['a', 'b', 'c', 'd'])
2502  $
2503  au TermChanged * call LogACmd()
2504  let g:logged = []
2505  let term_save = &term
2506  set term=xterm
2507  call assert_equal([1, 4], g:logged)
2508
2509  au! TermChanged
2510  let &term = term_save
2511  bwipe!
2512endfunc
2513
2514" Test for FileReadCmd autocmd
2515func Test_autocmd_FileReadCmd()
2516  func ReadFileCmd()
2517    call append(line('$'), "v:cmdarg = " .. v:cmdarg)
2518  endfunc
2519  augroup FileReadCmdTest
2520    au!
2521    au FileReadCmd Xtest call ReadFileCmd()
2522  augroup END
2523
2524  new
2525  read ++bin Xtest
2526  read ++nobin Xtest
2527  read ++edit Xtest
2528  read ++bad=keep Xtest
2529  read ++bad=drop Xtest
2530  read ++bad=- Xtest
2531  read ++ff=unix Xtest
2532  read ++ff=dos Xtest
2533  read ++ff=mac Xtest
2534  read ++enc=utf-8 Xtest
2535
2536  call assert_equal(['',
2537        \ 'v:cmdarg =  ++bin',
2538        \ 'v:cmdarg =  ++nobin',
2539        \ 'v:cmdarg =  ++edit',
2540        \ 'v:cmdarg =  ++bad=keep',
2541        \ 'v:cmdarg =  ++bad=drop',
2542        \ 'v:cmdarg =  ++bad=-',
2543        \ 'v:cmdarg =  ++ff=unix',
2544        \ 'v:cmdarg =  ++ff=dos',
2545        \ 'v:cmdarg =  ++ff=mac',
2546        \ 'v:cmdarg =  ++enc=utf-8'], getline(1, '$'))
2547
2548  close!
2549  augroup FileReadCmdTest
2550    au!
2551  augroup END
2552  delfunc ReadFileCmd
2553endfunc
2554
2555" Test for passing invalid arguments to autocmd
2556func Test_autocmd_invalid_args()
2557  " Additional character after * for event
2558  call assert_fails('autocmd *a Xfile set ff=unix', 'E215:')
2559  augroup Test
2560  augroup END
2561  " Invalid autocmd event
2562  call assert_fails('autocmd Bufabc Xfile set ft=vim', 'E216:')
2563  " Invalid autocmd event in a autocmd group
2564  call assert_fails('autocmd Test Bufabc Xfile set ft=vim', 'E216:')
2565  augroup! Test
2566  " Execute all autocmds
2567  call assert_fails('doautocmd * BufEnter', 'E217:')
2568  call assert_fails('augroup! x1a2b3', 'E367:')
2569  call assert_fails('autocmd BufNew <buffer=999> pwd', 'E680:')
2570  call assert_fails('autocmd BufNew \) set ff=unix', 'E55:')
2571endfunc
2572
2573" Test for deep nesting of autocmds
2574func Test_autocmd_deep_nesting()
2575  autocmd BufEnter Xfile doautocmd BufEnter Xfile
2576  call assert_fails('doautocmd BufEnter Xfile', 'E218:')
2577  autocmd! BufEnter Xfile
2578endfunc
2579
2580" Tests for SigUSR1 autocmd event, which is only available on posix systems.
2581func Test_autocmd_sigusr1()
2582  CheckUnix
2583  CheckExecutable /bin/kill
2584
2585  let g:sigusr1_passed = 0
2586  au SigUSR1 * let g:sigusr1_passed = 1
2587  call system('/bin/kill -s usr1 ' . getpid())
2588  call WaitForAssert({-> assert_true(g:sigusr1_passed)})
2589
2590  au! SigUSR1
2591  unlet g:sigusr1_passed
2592endfunc
2593
2594" Test for BufReadPre autocmd deleting the file
2595func Test_BufReadPre_delfile()
2596  augroup TestAuCmd
2597    au!
2598    autocmd BufReadPre Xfile call delete('Xfile')
2599  augroup END
2600  call writefile([], 'Xfile')
2601  call assert_fails('new Xfile', 'E200:')
2602  call assert_equal('Xfile', @%)
2603  call assert_equal(1, &readonly)
2604  call delete('Xfile')
2605  augroup TestAuCmd
2606    au!
2607  augroup END
2608  close!
2609endfunc
2610
2611" Test for BufReadPre autocmd changing the current buffer
2612func Test_BufReadPre_changebuf()
2613  augroup TestAuCmd
2614    au!
2615    autocmd BufReadPre Xfile edit Xsomeotherfile
2616  augroup END
2617  call writefile([], 'Xfile')
2618  call assert_fails('new Xfile', 'E201:')
2619  call assert_equal('Xsomeotherfile', @%)
2620  call assert_equal(1, &readonly)
2621  call delete('Xfile')
2622  augroup TestAuCmd
2623    au!
2624  augroup END
2625  close!
2626endfunc
2627
2628" Test for BufWipeouti autocmd changing the current buffer when reading a file
2629" in an empty buffer with 'f' flag in 'cpo'
2630func Test_BufDelete_changebuf()
2631  new
2632  augroup TestAuCmd
2633    au!
2634    autocmd BufWipeout * let bufnr = bufadd('somefile') | exe "b " .. bufnr
2635  augroup END
2636  let save_cpo = &cpo
2637  set cpo+=f
2638  call assert_fails('r Xfile', ['E812:', 'E484:'])
2639  call assert_equal('somefile', @%)
2640  let &cpo = save_cpo
2641  augroup TestAuCmd
2642    au!
2643  augroup END
2644  close!
2645endfunc
2646
2647" Test for the temporary internal window used to execute autocmds
2648func Test_autocmd_window()
2649  %bw!
2650  edit one.txt
2651  tabnew two.txt
2652  let g:blist = []
2653  augroup aucmd_win_test1
2654    au!
2655    au BufEnter * call add(g:blist, [expand('<afile>'),
2656          \ win_gettype(bufwinnr(expand('<afile>')))])
2657  augroup END
2658
2659  doautoall BufEnter
2660  call assert_equal([['one.txt', 'autocmd'], ['two.txt', '']], g:blist)
2661
2662  augroup aucmd_win_test1
2663    au!
2664  augroup END
2665  augroup! aucmd_win_test1
2666  %bw!
2667endfunc
2668
2669" Test for trying to close the temporary window used for executing an autocmd
2670func Test_close_autocmd_window()
2671  %bw!
2672  edit one.txt
2673  tabnew two.txt
2674  augroup aucmd_win_test2
2675    au!
2676    au BufEnter * if expand('<afile>') == 'one.txt' | 1close | endif
2677  augroup END
2678
2679  call assert_fails('doautoall BufEnter', 'E813:')
2680
2681  augroup aucmd_win_test2
2682    au!
2683  augroup END
2684  augroup! aucmd_win_test2
2685  %bwipe!
2686endfunc
2687
2688" Test for trying to close the tab that has the temporary window for exeucing
2689" an autocmd.
2690func Test_close_autocmd_tab()
2691  edit one.txt
2692  tabnew two.txt
2693   augroup aucmd_win_test
2694    au!
2695    au BufEnter * if expand('<afile>') == 'one.txt' | tabfirst | tabonly | endif
2696  augroup END
2697
2698  call assert_fails('doautoall BufEnter', 'E813:')
2699
2700  tabonly
2701  augroup aucmd_win_test
2702    au!
2703  augroup END
2704  augroup! aucmd_win_test
2705  %bwipe!
2706endfunc
2707
2708" vim: shiftwidth=2 sts=2 expandtab
2709