xref: /vim-8.2.3635/src/testdir/test_autocmd.vim (revision 12ee7ff0)
1" Tests for autocommands
2
3source shared.vim
4
5func s:cleanup_buffers() abort
6  for bnr in range(1, bufnr('$'))
7    if bufloaded(bnr) && bufnr('%') != bnr
8      execute 'bd! ' . bnr
9    endif
10  endfor
11endfunc
12
13func Test_vim_did_enter()
14  call assert_false(v:vim_did_enter)
15
16  " This script will never reach the main loop, can't check if v:vim_did_enter
17  " becomes one.
18endfunc
19
20if has('timers')
21
22  func ExitInsertMode(id)
23    call feedkeys("\<Esc>")
24  endfunc
25
26  func Test_cursorhold_insert()
27    " Need to move the cursor.
28    call feedkeys("ggG", "xt")
29
30    let g:triggered = 0
31    au CursorHoldI * let g:triggered += 1
32    set updatetime=20
33    call timer_start(100, 'ExitInsertMode')
34    call feedkeys('a', 'x!')
35    call assert_equal(1, g:triggered)
36    unlet g:triggered
37    au! CursorHoldI
38    set updatetime&
39  endfunc
40
41  func Test_cursorhold_insert_with_timer_interrupt()
42    if !has('job')
43      return
44    endif
45    " Need to move the cursor.
46    call feedkeys("ggG", "xt")
47
48    " Confirm the timer invoked in exit_cb of the job doesn't disturb
49    " CursorHoldI event.
50    let g:triggered = 0
51    au CursorHoldI * let g:triggered += 1
52    set updatetime=500
53    call job_start(has('win32') ? 'cmd /c echo:' : 'echo',
54          \ {'exit_cb': {-> timer_start(1000, 'ExitInsertMode')}})
55    call feedkeys('a', 'x!')
56    call assert_equal(1, g:triggered)
57    unlet g:triggered
58    au! CursorHoldI
59    set updatetime&
60  endfunc
61
62  func Test_cursorhold_insert_ctrl_x()
63    let g:triggered = 0
64    au CursorHoldI * let g:triggered += 1
65    set updatetime=20
66    call timer_start(100, 'ExitInsertMode')
67    " CursorHoldI does not trigger after CTRL-X
68    call feedkeys("a\<C-X>", 'x!')
69    call assert_equal(0, g:triggered)
70    unlet g:triggered
71    au! CursorHoldI
72    set updatetime&
73  endfunc
74
75  func Test_OptionSet_modeline()
76    call test_override('starting', 1)
77    au! OptionSet
78    augroup set_tabstop
79      au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler called'", "")})
80    augroup END
81    call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline')
82    set modeline
83    let v:errmsg = ''
84    call assert_fails('split XoptionsetModeline', 'E12:')
85    call assert_equal(7, &ts)
86    call assert_equal('', v:errmsg)
87
88    augroup set_tabstop
89      au!
90    augroup END
91    bwipe!
92    set ts&
93    call delete('XoptionsetModeline')
94    call test_override('starting', 0)
95  endfunc
96
97endif "has('timers')
98
99func Test_bufunload()
100  augroup test_bufunload_group
101    autocmd!
102    autocmd BufUnload * call add(s:li, "bufunload")
103    autocmd BufDelete * call add(s:li, "bufdelete")
104    autocmd BufWipeout * call add(s:li, "bufwipeout")
105  augroup END
106
107  let s:li=[]
108  new
109  setlocal bufhidden=
110  bunload
111  call assert_equal(["bufunload", "bufdelete"], s:li)
112
113  let s:li=[]
114  new
115  setlocal bufhidden=delete
116  bunload
117  call assert_equal(["bufunload", "bufdelete"], s:li)
118
119  let s:li=[]
120  new
121  setlocal bufhidden=unload
122  bwipeout
123  call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li)
124
125  au! test_bufunload_group
126  augroup! test_bufunload_group
127endfunc
128
129" SEGV occurs in older versions.  (At least 7.4.2005 or older)
130func Test_autocmd_bufunload_with_tabnext()
131  tabedit
132  tabfirst
133
134  augroup test_autocmd_bufunload_with_tabnext_group
135    autocmd!
136    autocmd BufUnload <buffer> tabnext
137  augroup END
138
139  quit
140  call assert_equal(2, tabpagenr('$'))
141
142  autocmd! test_autocmd_bufunload_with_tabnext_group
143  augroup! test_autocmd_bufunload_with_tabnext_group
144  tablast
145  quit
146endfunc
147
148func Test_autocmd_bufwinleave_with_tabfirst()
149  tabedit
150  augroup sample
151    autocmd!
152    autocmd BufWinLeave <buffer> tabfirst
153  augroup END
154  call setline(1, ['a', 'b', 'c'])
155  edit! a.txt
156  tabclose
157endfunc
158
159" SEGV occurs in older versions.  (At least 7.4.2321 or older)
160func Test_autocmd_bufunload_avoiding_SEGV_01()
161  split aa.txt
162  let lastbuf = bufnr('$')
163
164  augroup test_autocmd_bufunload
165    autocmd!
166    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
167  augroup END
168
169  " Todo: check for E937 generated first
170  " call assert_fails('edit bb.txt', 'E937:')
171  call assert_fails('edit bb.txt', 'E517:')
172
173  autocmd! test_autocmd_bufunload
174  augroup! test_autocmd_bufunload
175  bwipe! aa.txt
176  bwipe! bb.txt
177endfunc
178
179" SEGV occurs in older versions.  (At least 7.4.2321 or older)
180func Test_autocmd_bufunload_avoiding_SEGV_02()
181  setlocal buftype=nowrite
182  let lastbuf = bufnr('$')
183
184  augroup test_autocmd_bufunload
185    autocmd!
186    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
187  augroup END
188
189  normal! i1
190  call assert_fails('edit a.txt', 'E517:')
191  call feedkeys("\<CR>")
192
193  autocmd! test_autocmd_bufunload
194  augroup! test_autocmd_bufunload
195  bwipe! a.txt
196endfunc
197
198func Test_win_tab_autocmd()
199  let g:record = []
200
201  augroup testing
202    au WinNew * call add(g:record, 'WinNew')
203    au WinEnter * call add(g:record, 'WinEnter')
204    au WinLeave * call add(g:record, 'WinLeave')
205    au TabNew * call add(g:record, 'TabNew')
206    au TabClosed * call add(g:record, 'TabClosed')
207    au TabEnter * call add(g:record, 'TabEnter')
208    au TabLeave * call add(g:record, 'TabLeave')
209  augroup END
210
211  split
212  tabnew
213  close
214  close
215
216  call assert_equal([
217	\ 'WinLeave', 'WinNew', 'WinEnter',
218	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
219	\ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter',
220	\ 'WinLeave', 'WinEnter'
221	\ ], g:record)
222
223  let g:record = []
224  tabnew somefile
225  tabnext
226  bwipe somefile
227
228  call assert_equal([
229	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
230	\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
231	\ 'TabClosed'
232	\ ], g:record)
233
234  augroup testing
235    au!
236  augroup END
237  unlet g:record
238endfunc
239
240func s:AddAnAutocmd()
241  augroup vimBarTest
242    au BufReadCmd * echo 'hello'
243  augroup END
244  call assert_equal(3, len(split(execute('au vimBarTest'), "\n")))
245endfunc
246
247func Test_early_bar()
248  " test that a bar is recognized before the {event}
249  call s:AddAnAutocmd()
250  augroup vimBarTest | au! | augroup END
251  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
252
253  call s:AddAnAutocmd()
254  augroup vimBarTest| au!| augroup END
255  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
256
257  " test that a bar is recognized after the {event}
258  call s:AddAnAutocmd()
259  augroup vimBarTest| au!BufReadCmd| augroup END
260  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
261
262  " test that a bar is recognized after the {group}
263  call s:AddAnAutocmd()
264  au! vimBarTest|echo 'hello'
265  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
266endfunc
267
268func RemoveGroup()
269  autocmd! StartOK
270  augroup! StartOK
271endfunc
272
273func Test_augroup_warning()
274  augroup TheWarning
275    au VimEnter * echo 'entering'
276  augroup END
277  call assert_true(match(execute('au VimEnter'), "TheWarning.*VimEnter") >= 0)
278  redir => res
279  augroup! TheWarning
280  redir END
281  call assert_true(match(res, "W19:") >= 0)
282  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
283
284  " check "Another" does not take the pace of the deleted entry
285  augroup Another
286  augroup END
287  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
288  augroup! Another
289
290  " no warning for postpone aucmd delete
291  augroup StartOK
292    au VimEnter * call RemoveGroup()
293  augroup END
294  call assert_true(match(execute('au VimEnter'), "StartOK.*VimEnter") >= 0)
295  redir => res
296  doautocmd VimEnter
297  redir END
298  call assert_true(match(res, "W19:") < 0)
299  au! VimEnter
300endfunc
301
302func Test_BufReadCmdHelp()
303  " This used to cause access to free memory
304  au BufReadCmd * e +h
305  help
306
307  au! BufReadCmd
308endfunc
309
310func Test_BufReadCmdHelpJump()
311  " This used to cause access to free memory
312  au BufReadCmd * e +h{
313  " } to fix highlighting
314  call assert_fails('help', 'E434:')
315
316  au! BufReadCmd
317endfunc
318
319func Test_augroup_deleted()
320  " This caused a crash before E936 was introduced
321  augroup x
322    call assert_fails('augroup! x', 'E936:')
323    au VimEnter * echo
324  augroup end
325  augroup! x
326  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
327  au! VimEnter
328endfunc
329
330" Tests for autocommands on :close command.
331" This used to be in test13.
332func Test_three_windows()
333  " Clean up buffers, because in some cases this function fails.
334  call s:cleanup_buffers()
335
336  " Write three files and open them, each in a window.
337  " Then go to next window, with autocommand that deletes the previous one.
338  " Do this twice, writing the file.
339  e! Xtestje1
340  call setline(1, 'testje1')
341  w
342  sp Xtestje2
343  call setline(1, 'testje2')
344  w
345  sp Xtestje3
346  call setline(1, 'testje3')
347  w
348  wincmd w
349  au WinLeave Xtestje2 bwipe
350  wincmd w
351  call assert_equal('Xtestje1', expand('%'))
352
353  au WinLeave Xtestje1 bwipe Xtestje3
354  close
355  call assert_equal('Xtestje1', expand('%'))
356
357  " Test deleting the buffer on a Unload event.  If this goes wrong there
358  " will be the ATTENTION prompt.
359  e Xtestje1
360  au!
361  au! BufUnload Xtestje1 bwipe
362  call assert_fails('e Xtestje3', 'E937:')
363  call assert_equal('Xtestje3', expand('%'))
364
365  e Xtestje2
366  sp Xtestje1
367  call assert_fails('e', 'E937:')
368  call assert_equal('Xtestje1', expand('%'))
369
370  " Test changing buffers in a BufWipeout autocommand.  If this goes wrong
371  " there are ml_line errors and/or a Crash.
372  au!
373  only
374  e Xanother
375  e Xtestje1
376  bwipe Xtestje2
377  bwipe Xtestje3
378  au BufWipeout Xtestje1 buf Xtestje1
379  bwipe
380  call assert_equal('Xanother', expand('%'))
381
382  only
383  help
384  wincmd w
385  1quit
386  call assert_equal('Xanother', expand('%'))
387
388  au!
389  enew
390  call delete('Xtestje1')
391  call delete('Xtestje2')
392  call delete('Xtestje3')
393endfunc
394
395func Test_BufEnter()
396  au! BufEnter
397  au Bufenter * let val = val . '+'
398  let g:val = ''
399  split NewFile
400  call assert_equal('+', g:val)
401  bwipe!
402  call assert_equal('++', g:val)
403
404  " Also get BufEnter when editing a directory
405  call mkdir('Xdir')
406  split Xdir
407  call assert_equal('+++', g:val)
408
409  " On MS-Windows we can't edit the directory, make sure we wipe the right
410  " buffer.
411  bwipe! Xdir
412
413  call delete('Xdir', 'd')
414  au! BufEnter
415endfunc
416
417" Closing a window might cause an endless loop
418" E814 for older Vims
419func Test_autocmd_bufwipe_in_SessLoadPost()
420  edit Xtest
421  tabnew
422  file Xsomething
423  set noswapfile
424  mksession!
425
426  let content =<< trim [CODE]
427    set nocp noswapfile
428    let v:swapchoice="e"
429    augroup test_autocmd_sessionload
430    autocmd!
431    autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!"
432    augroup END
433
434    func WriteErrors()
435      call writefile([execute("messages")], "Xerrors")
436    endfunc
437    au VimLeave * call WriteErrors()
438  [CODE]
439
440  call writefile(content, 'Xvimrc')
441  call system(v:progpath. ' -u Xvimrc --not-a-term --noplugins -S Session.vim -c cq')
442  let errors = join(readfile('Xerrors'))
443  call assert_match('E814', errors)
444
445  set swapfile
446  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
447    call delete(file)
448  endfor
449endfunc
450
451" SEGV occurs in older versions.
452func Test_autocmd_bufwipe_in_SessLoadPost2()
453  tabnew
454  set noswapfile
455  mksession!
456
457  let content =<< trim [CODE]
458    set nocp noswapfile
459    function! DeleteInactiveBufs()
460      tabfirst
461      let tabblist = []
462      for i in range(1, tabpagenr(''$''))
463        call extend(tabblist, tabpagebuflist(i))
464      endfor
465      for b in range(1, bufnr(''$''))
466        if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')
467          exec ''bwipeout '' . b
468        endif
469      endfor
470      echomsg "SessionLoadPost DONE"
471    endfunction
472    au SessionLoadPost * call DeleteInactiveBufs()
473
474    func WriteErrors()
475      call writefile([execute("messages")], "Xerrors")
476    endfunc
477    au VimLeave * call WriteErrors()
478  [CODE]
479
480  call writefile(content, 'Xvimrc')
481  call system(v:progpath. ' -u Xvimrc --not-a-term --noplugins -S Session.vim -c cq')
482  let errors = join(readfile('Xerrors'))
483  " This probably only ever matches on unix.
484  call assert_notmatch('Caught deadly signal SEGV', errors)
485  call assert_match('SessionLoadPost DONE', errors)
486
487  set swapfile
488  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
489    call delete(file)
490  endfor
491endfunc
492
493func Test_empty_doau()
494  doau \|
495endfunc
496
497func s:AutoCommandOptionSet(match)
498  let item     = remove(g:options, 0)
499  let expected = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", item[0], item[1], item[2], item[3])
500  let actual   = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", a:match, v:option_old, v:option_new, v:option_type)
501  let g:opt    = [expected, actual]
502  "call assert_equal(expected, actual)
503endfunc
504
505func Test_OptionSet()
506  if !has("eval") || !exists("+autochdir")
507    return
508  endif
509
510  badd test_autocmd.vim
511
512  call test_override('starting', 1)
513  set nocp
514  au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>"))
515
516  " 1: Setting number option"
517  let g:options=[['number', 0, 1, 'global']]
518  set nu
519  call assert_equal([], g:options)
520  call assert_equal(g:opt[0], g:opt[1])
521
522  " 2: Setting local number option"
523  let g:options=[['number', 1, 0, 'local']]
524  setlocal nonu
525  call assert_equal([], g:options)
526  call assert_equal(g:opt[0], g:opt[1])
527
528  " 3: Setting global number option"
529  let g:options=[['number', 1, 0, 'global']]
530  setglobal nonu
531  call assert_equal([], g:options)
532  call assert_equal(g:opt[0], g:opt[1])
533
534  " 4: Setting local autoindent option"
535  let g:options=[['autoindent', 0, 1, 'local']]
536  setlocal ai
537  call assert_equal([], g:options)
538  call assert_equal(g:opt[0], g:opt[1])
539
540  " 5: Setting global autoindent option"
541  let g:options=[['autoindent', 0, 1, 'global']]
542  setglobal ai
543  call assert_equal([], g:options)
544  call assert_equal(g:opt[0], g:opt[1])
545
546  " 6: Setting global autoindent option"
547  let g:options=[['autoindent', 1, 0, 'global']]
548  set ai!
549  call assert_equal([], g:options)
550  call assert_equal(g:opt[0], g:opt[1])
551
552  " Should not print anything, use :noa
553  " 7: don't trigger OptionSet"
554  let g:options=[['invalid', 1, 1, 'invalid']]
555  noa set nonu
556  call assert_equal([['invalid', 1, 1, 'invalid']], g:options)
557  call assert_equal(g:opt[0], g:opt[1])
558
559  " 8: Setting several global list and number option"
560  let g:options=[['list', 0, 1, 'global'], ['number', 0, 1, 'global']]
561  set list nu
562  call assert_equal([], g:options)
563  call assert_equal(g:opt[0], g:opt[1])
564
565  " 9: don't trigger OptionSet"
566  let g:options=[['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']]
567  noa set nolist nonu
568  call assert_equal([['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']], g:options)
569  call assert_equal(g:opt[0], g:opt[1])
570
571  " 10: Setting global acd"
572  let g:options=[['autochdir', 0, 1, 'local']]
573  setlocal acd
574  call assert_equal([], g:options)
575  call assert_equal(g:opt[0], g:opt[1])
576
577  " 11: Setting global autoread (also sets local value)"
578  let g:options=[['autoread', 0, 1, 'global']]
579  set ar
580  call assert_equal([], g:options)
581  call assert_equal(g:opt[0], g:opt[1])
582
583  " 12: Setting local autoread"
584  let g:options=[['autoread', 1, 1, 'local']]
585  setlocal ar
586  call assert_equal([], g:options)
587  call assert_equal(g:opt[0], g:opt[1])
588
589  " 13: Setting global autoread"
590  let g:options=[['autoread', 1, 0, 'global']]
591  setglobal invar
592  call assert_equal([], g:options)
593  call assert_equal(g:opt[0], g:opt[1])
594
595  " 14: Setting option backspace through :let"
596  let g:options=[['backspace', '', 'eol,indent,start', 'global']]
597  let &bs="eol,indent,start"
598  call assert_equal([], g:options)
599  call assert_equal(g:opt[0], g:opt[1])
600
601  " 15: Setting option backspace through setbufvar()"
602  let g:options=[['backup', 0, 1, 'local']]
603  " try twice, first time, shouldn't trigger because option name is invalid,
604  " second time, it should trigger
605  let bnum = bufnr('%')
606  call assert_fails("call setbufvar(bnum, '&l:bk', 1)", "E355")
607  " should trigger, use correct option name
608  call setbufvar(bnum, '&backup', 1)
609  call assert_equal([], g:options)
610  call assert_equal(g:opt[0], g:opt[1])
611
612  " 16: Setting number option using setwinvar"
613  let g:options=[['number', 0, 1, 'local']]
614  call setwinvar(0, '&number', 1)
615  call assert_equal([], g:options)
616  call assert_equal(g:opt[0], g:opt[1])
617
618  " 17: Setting key option, shouldn't trigger"
619  let g:options=[['key', 'invalid', 'invalid1', 'invalid']]
620  setlocal key=blah
621  setlocal key=
622  call assert_equal([['key', 'invalid', 'invalid1', 'invalid']], g:options)
623  call assert_equal(g:opt[0], g:opt[1])
624
625  " 18: Setting string option"
626  let oldval = &tags
627  let g:options=[['tags', oldval, 'tagpath', 'global']]
628  set tags=tagpath
629  call assert_equal([], g:options)
630  call assert_equal(g:opt[0], g:opt[1])
631
632  " 1l: Resetting string option"
633  let g:options=[['tags', 'tagpath', oldval, 'global']]
634  set tags&
635  call assert_equal([], g:options)
636  call assert_equal(g:opt[0], g:opt[1])
637
638  " Cleanup
639  au! OptionSet
640  for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp']
641    exe printf(":set %s&vim", opt)
642  endfor
643  call test_override('starting', 0)
644  delfunc! AutoCommandOptionSet
645endfunc
646
647func Test_OptionSet_diffmode()
648  call test_override('starting', 1)
649  " 18: Changing an option when entering diff mode
650  new
651  au OptionSet diff :let &l:cul=v:option_new
652
653  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
654  call assert_equal(0, &l:cul)
655  diffthis
656  call assert_equal(1, &l:cul)
657
658  vnew
659  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
660  call assert_equal(0, &l:cul)
661  diffthis
662  call assert_equal(1, &l:cul)
663
664  diffoff
665  call assert_equal(0, &l:cul)
666  call assert_equal(1, getwinvar(2, '&l:cul'))
667  bw!
668
669  call assert_equal(1, &l:cul)
670  diffoff!
671  call assert_equal(0, &l:cul)
672  call assert_equal(0, getwinvar(1, '&l:cul'))
673  bw!
674
675  " Cleanup
676  au! OptionSet
677  call test_override('starting', 0)
678endfunc
679
680func Test_OptionSet_diffmode_close()
681  call test_override('starting', 1)
682  " 19: Try to close the current window when entering diff mode
683  " should not segfault
684  new
685  au OptionSet diff close
686
687  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
688  call assert_fails(':diffthis', 'E788')
689  call assert_equal(1, &diff)
690  vnew
691  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
692  call assert_fails(':diffthis', 'E788')
693  call assert_equal(1, &diff)
694  bw!
695  call assert_fails(':diffoff!', 'E788')
696  bw!
697
698  " Cleanup
699  au! OptionSet
700  call test_override('starting', 0)
701  "delfunc! AutoCommandOptionSet
702endfunc
703
704" Test for Bufleave autocommand that deletes the buffer we are about to edit.
705func Test_BufleaveWithDelete()
706  new | edit Xfile1
707
708  augroup test_bufleavewithdelete
709      autocmd!
710      autocmd BufLeave Xfile1 bwipe Xfile2
711  augroup END
712
713  call assert_fails('edit Xfile2', 'E143:')
714  call assert_equal('Xfile1', bufname('%'))
715
716  autocmd! test_bufleavewithdelete BufLeave Xfile1
717  augroup! test_bufleavewithdelete
718
719  new
720  bwipe! Xfile1
721endfunc
722
723" Test for autocommand that changes the buffer list, when doing ":ball".
724func Test_Acmd_BufAll()
725  enew!
726  %bwipe!
727  call writefile(['Test file Xxx1'], 'Xxx1')
728  call writefile(['Test file Xxx2'], 'Xxx2')
729  call writefile(['Test file Xxx3'], 'Xxx3')
730
731  " Add three files to the buffer list
732  split Xxx1
733  close
734  split Xxx2
735  close
736  split Xxx3
737  close
738
739  " Wipe the buffer when the buffer is opened
740  au BufReadPost Xxx2 bwipe
741
742  call append(0, 'Test file Xxx4')
743  ball
744
745  call assert_equal(2, winnr('$'))
746  call assert_equal('Xxx1', bufname(winbufnr(winnr('$'))))
747  wincmd t
748
749  au! BufReadPost
750  %bwipe!
751  call delete('Xxx1')
752  call delete('Xxx2')
753  call delete('Xxx3')
754  enew! | only
755endfunc
756
757" Test for autocommand that changes current buffer on BufEnter event.
758" Check if modelines are interpreted for the correct buffer.
759func Test_Acmd_BufEnter()
760  %bwipe!
761  call writefile(['start of test file Xxx1',
762	      \ "\<Tab>this is a test",
763	      \ 'end of test file Xxx1'], 'Xxx1')
764  call writefile(['start of test file Xxx2',
765	      \ 'vim: set noai :',
766	      \ "\<Tab>this is a test",
767	      \ 'end of test file Xxx2'], 'Xxx2')
768
769  au BufEnter Xxx2 brew
770  set ai modeline modelines=3
771  edit Xxx1
772  " edit Xxx2, autocmd will do :brew
773  edit Xxx2
774  exe "normal G?this is a\<CR>"
775  " Append text with autoindent to this file
776  normal othis should be auto-indented
777  call assert_equal("\<Tab>this should be auto-indented", getline('.'))
778  call assert_equal(3, line('.'))
779  " Remove autocmd and edit Xxx2 again
780  au! BufEnter Xxx2
781  buf! Xxx2
782  exe "normal G?this is a\<CR>"
783  " append text without autoindent to Xxx
784  normal othis should be in column 1
785  call assert_equal("this should be in column 1", getline('.'))
786  call assert_equal(4, line('.'))
787
788  %bwipe!
789  call delete('Xxx1')
790  call delete('Xxx2')
791  set ai&vim modeline&vim modelines&vim
792endfunc
793
794" Test for issue #57
795" do not move cursor on <c-o> when autoindent is set
796func Test_ai_CTRL_O()
797  enew!
798  set ai
799  let save_fo = &fo
800  set fo+=r
801  exe "normal o# abcdef\<Esc>2hi\<CR>\<C-O>d0\<Esc>"
802  exe "normal o# abcdef\<Esc>2hi\<C-O>d0\<Esc>"
803  call assert_equal(['# abc', 'def', 'def'], getline(2, 4))
804
805  set ai&vim
806  let &fo = save_fo
807  enew!
808endfunc
809
810" Test for autocommand that deletes the current buffer on BufLeave event.
811" Also test deleting the last buffer, should give a new, empty buffer.
812func Test_BufLeave_Wipe()
813  %bwipe!
814  let content = ['start of test file Xxx',
815	      \ 'this is a test',
816	      \ 'end of test file Xxx']
817  call writefile(content, 'Xxx1')
818  call writefile(content, 'Xxx2')
819
820  au BufLeave Xxx2 bwipe
821  edit Xxx1
822  split Xxx2
823  " delete buffer Xxx2, we should be back to Xxx1
824  bwipe
825  call assert_equal('Xxx1', bufname('%'))
826  call assert_equal(1, winnr('$'))
827
828  " Create an alternate buffer
829  %write! test.out
830  call assert_equal('test.out', bufname('#'))
831  " delete alternate buffer
832  bwipe test.out
833  call assert_equal('Xxx1', bufname('%'))
834  call assert_equal('', bufname('#'))
835
836  au BufLeave Xxx1 bwipe
837  " delete current buffer, get an empty one
838  bwipe!
839  call assert_equal(1, line('$'))
840  call assert_equal('', bufname('%'))
841  let g:bufinfo = getbufinfo()
842  call assert_equal(1, len(g:bufinfo))
843
844  call delete('Xxx1')
845  call delete('Xxx2')
846  call delete('test.out')
847  %bwipe
848  au! BufLeave
849
850  " check that bufinfo doesn't contain a pointer to freed memory
851  call test_garbagecollect_now()
852endfunc
853
854func Test_QuitPre()
855  edit Xfoo
856  let winid = win_getid(winnr())
857  split Xbar
858  au! QuitPre * let g:afile = expand('<afile>')
859  " Close the other window, <afile> should be correct.
860  exe win_id2win(winid) . 'q'
861  call assert_equal('Xfoo', g:afile)
862
863  unlet g:afile
864  bwipe Xfoo
865  bwipe Xbar
866endfunc
867
868func Test_Cmdline()
869  au! CmdlineChanged : let g:text = getcmdline()
870  let g:text = 0
871  call feedkeys(":echom 'hello'\<CR>", 'xt')
872  call assert_equal("echom 'hello'", g:text)
873  au! CmdlineChanged
874
875  au! CmdlineChanged : let g:entered = expand('<afile>')
876  let g:entered = 0
877  call feedkeys(":echom 'hello'\<CR>", 'xt')
878  call assert_equal(':', g:entered)
879  au! CmdlineChanged
880
881  au! CmdlineEnter : let g:entered = expand('<afile>')
882  au! CmdlineLeave : let g:left = expand('<afile>')
883  let g:entered = 0
884  let g:left = 0
885  call feedkeys(":echo 'hello'\<CR>", 'xt')
886  call assert_equal(':', g:entered)
887  call assert_equal(':', g:left)
888  au! CmdlineEnter
889  au! CmdlineLeave
890
891  let save_shellslash = &shellslash
892  set noshellslash
893  au! CmdlineEnter / let g:entered = expand('<afile>')
894  au! CmdlineLeave / let g:left = expand('<afile>')
895  let g:entered = 0
896  let g:left = 0
897  new
898  call setline(1, 'hello')
899  call feedkeys("/hello\<CR>", 'xt')
900  call assert_equal('/', g:entered)
901  call assert_equal('/', g:left)
902  bwipe!
903  au! CmdlineEnter
904  au! CmdlineLeave
905  let &shellslash = save_shellslash
906endfunc
907
908" Test for BufWritePre autocommand that deletes or unloads the buffer.
909func Test_BufWritePre()
910  %bwipe
911  au BufWritePre Xxx1 bunload
912  au BufWritePre Xxx2 bwipe
913
914  call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1')
915  call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2')
916
917  edit Xtest
918  e! Xxx2
919  bdel Xtest
920  e Xxx1
921  " write it, will unload it and give an error msg
922  call assert_fails('w', 'E203')
923  call assert_equal('Xxx2', bufname('%'))
924  edit Xtest
925  e! Xxx2
926  bwipe Xtest
927  " write it, will delete the buffer and give an error msg
928  call assert_fails('w', 'E203')
929  call assert_equal('Xxx1', bufname('%'))
930  au! BufWritePre
931  call delete('Xxx1')
932  call delete('Xxx2')
933endfunc
934
935" Test for BufUnload autocommand that unloads all the other buffers
936func Test_bufunload_all()
937  call writefile(['Test file Xxx1'], 'Xxx1')"
938  call writefile(['Test file Xxx2'], 'Xxx2')"
939
940  let content =<< trim [CODE]
941    func UnloadAllBufs()
942      let i = 1
943      while i <= bufnr('$')
944        if i != bufnr('%') && bufloaded(i)
945          exe  i . 'bunload'
946        endif
947        let i += 1
948      endwhile
949    endfunc
950    au BufUnload * call UnloadAllBufs()
951    au VimLeave * call writefile(['Test Finished'], 'Xout')
952    edit Xxx1
953    split Xxx2
954    q
955  [CODE]
956
957  call writefile(content, 'Xtest')
958
959  call delete('Xout')
960  call system(v:progpath. ' --clean -N --not-a-term -S Xtest')
961  call assert_true(filereadable('Xout'))
962
963  call delete('Xxx1')
964  call delete('Xxx2')
965  call delete('Xtest')
966  call delete('Xout')
967endfunc
968
969" Some tests for buffer-local autocommands
970func Test_buflocal_autocmd()
971  let g:bname = ''
972  edit xx
973  au BufLeave <buffer> let g:bname = expand("%")
974  " here, autocommand for xx should trigger.
975  " but autocommand shall not apply to buffer named <buffer>.
976  edit somefile
977  call assert_equal('xx', g:bname)
978  let g:bname = ''
979  " here, autocommand shall be auto-deleted
980  bwipe xx
981  " autocmd should not trigger
982  edit xx
983  call assert_equal('', g:bname)
984  " autocmd should not trigger
985  edit somefile
986  call assert_equal('', g:bname)
987  enew
988  unlet g:bname
989endfunc
990
991" Test for "*Cmd" autocommands
992func Test_Cmd_Autocmds()
993  call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx')
994
995  enew!
996  au BufReadCmd XtestA 0r Xxx|$del
997  edit XtestA			" will read text of Xxd instead
998  call assert_equal('start of Xxx', getline(1))
999
1000  au BufWriteCmd XtestA call append(line("$"), "write")
1001  write				" will append a line to the file
1002  call assert_equal('write', getline('$'))
1003  call assert_fails('read XtestA', 'E484')	" should not read anything
1004  call assert_equal('write', getline(4))
1005
1006  " now we have:
1007  " 1	start of Xxx
1008  " 2		abc2
1009  " 3	end of Xxx
1010  " 4	write
1011
1012  au FileReadCmd XtestB '[r Xxx
1013  2r XtestB			" will read Xxx below line 2 instead
1014  call assert_equal('start of Xxx', getline(3))
1015
1016  " now we have:
1017  " 1	start of Xxx
1018  " 2		abc2
1019  " 3	start of Xxx
1020  " 4		abc2
1021  " 5	end of Xxx
1022  " 6	end of Xxx
1023  " 7	write
1024
1025  au FileWriteCmd XtestC '[,']copy $
1026  normal 4GA1
1027  4,5w XtestC			" will copy lines 4 and 5 to the end
1028  call assert_equal("\tabc21", getline(8))
1029  call assert_fails('r XtestC', 'E484')	" should not read anything
1030  call assert_equal("end of Xxx", getline(9))
1031
1032  " now we have:
1033  " 1	start of Xxx
1034  " 2		abc2
1035  " 3	start of Xxx
1036  " 4		abc21
1037  " 5	end of Xxx
1038  " 6	end of Xxx
1039  " 7	write
1040  " 8		abc21
1041  " 9	end of Xxx
1042
1043  let g:lines = []
1044  au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']")))
1045  w >>XtestD			" will add lines to 'lines'
1046  call assert_equal(9, len(g:lines))
1047  call assert_fails('$r XtestD', 'E484')	" should not read anything
1048  call assert_equal(9, line('$'))
1049  call assert_equal('end of Xxx', getline('$'))
1050
1051  au BufReadCmd XtestE 0r Xxx|$del
1052  sp XtestE			" split window with test.out
1053  call assert_equal('end of Xxx', getline(3))
1054
1055  let g:lines = []
1056  exe "normal 2Goasdf\<Esc>\<C-W>\<C-W>"
1057  au BufWriteCmd XtestE call extend(g:lines, getline(0, '$'))
1058  wall				" will write other window to 'lines'
1059  call assert_equal(4, len(g:lines), g:lines)
1060  call assert_equal('asdf', g:lines[2])
1061
1062  au! BufReadCmd
1063  au! BufWriteCmd
1064  au! FileReadCmd
1065  au! FileWriteCmd
1066  au! FileAppendCmd
1067  %bwipe!
1068  call delete('Xxx')
1069  enew!
1070endfunc
1071
1072func SetChangeMarks(start, end)
1073  exe a:start. 'mark ['
1074  exe a:end. 'mark ]'
1075endfunc
1076
1077" Verify the effects of autocmds on '[ and ']
1078func Test_change_mark_in_autocmds()
1079  edit! Xtest
1080  call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u", 'xtn')
1081
1082  call SetChangeMarks(2, 3)
1083  write
1084  call assert_equal([1, 4], [line("'["), line("']")])
1085
1086  call SetChangeMarks(2, 3)
1087  au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1088  write
1089  au! BufWritePre
1090
1091  if executable('cat')
1092    write XtestFilter
1093    write >> XtestFilter
1094
1095    call SetChangeMarks(2, 3)
1096    " Marks are set to the entire range of the write
1097    au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1098    " '[ is adjusted to just before the line that will receive the filtered
1099    " data
1100    au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")])
1101    " The filtered data is read into the buffer, and the source lines are
1102    " still present, so the range is after the source lines
1103    au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")])
1104    %!cat XtestFilter
1105    " After the filtered data is read, the original lines are deleted
1106    call assert_equal([1, 8], [line("'["), line("']")])
1107    au! FilterWritePre,FilterReadPre,FilterReadPost
1108    undo
1109
1110    call SetChangeMarks(1, 4)
1111    au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1112    au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")])
1113    au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1114    2,3!cat XtestFilter
1115    call assert_equal([2, 9], [line("'["), line("']")])
1116    au! FilterWritePre,FilterReadPre,FilterReadPost
1117    undo
1118
1119    call delete('XtestFilter')
1120  endif
1121
1122  call SetChangeMarks(1, 4)
1123  au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1124  2,3write Xtest2
1125  au! FileWritePre
1126
1127  call SetChangeMarks(2, 3)
1128  au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")])
1129  write >> Xtest2
1130  au! FileAppendPre
1131
1132  call SetChangeMarks(1, 4)
1133  au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")])
1134  2,3write >> Xtest2
1135  au! FileAppendPre
1136
1137  call SetChangeMarks(1, 1)
1138  au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")])
1139  au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1140  3read Xtest2
1141  au! FileReadPre,FileReadPost
1142  undo
1143
1144  call SetChangeMarks(4, 4)
1145  " When the line is 0, it's adjusted to 1
1146  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1147  au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")])
1148  0read Xtest2
1149  au! FileReadPre,FileReadPost
1150  undo
1151
1152  call SetChangeMarks(4, 4)
1153  " When the line is 0, it's adjusted to 1
1154  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1155  au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")])
1156  1read Xtest2
1157  au! FileReadPre,FileReadPost
1158  undo
1159
1160  bwipe!
1161  call delete('Xtest')
1162  call delete('Xtest2')
1163endfunc
1164
1165func Test_Filter_noshelltemp()
1166  if !executable('cat')
1167    return
1168  endif
1169
1170  enew!
1171  call setline(1, ['a', 'b', 'c', 'd'])
1172
1173  let shelltemp = &shelltemp
1174  set shelltemp
1175
1176  let g:filter_au = 0
1177  au FilterWritePre * let g:filter_au += 1
1178  au FilterReadPre * let g:filter_au += 1
1179  au FilterReadPost * let g:filter_au += 1
1180  %!cat
1181  call assert_equal(3, g:filter_au)
1182
1183  if has('filterpipe')
1184    set noshelltemp
1185
1186    let g:filter_au = 0
1187    au FilterWritePre * let g:filter_au += 1
1188    au FilterReadPre * let g:filter_au += 1
1189    au FilterReadPost * let g:filter_au += 1
1190    %!cat
1191    call assert_equal(0, g:filter_au)
1192  endif
1193
1194  au! FilterWritePre,FilterReadPre,FilterReadPost
1195  let &shelltemp = shelltemp
1196  bwipe!
1197endfunc
1198
1199func Test_TextYankPost()
1200  enew!
1201  call setline(1, ['foo'])
1202
1203  let g:event = []
1204  au TextYankPost * let g:event = copy(v:event)
1205
1206  call assert_equal({}, v:event)
1207  call assert_fails('let v:event = {}', 'E46:')
1208  call assert_fails('let v:event.mykey = 0', 'E742:')
1209
1210  norm "ayiw
1211  call assert_equal(
1212    \{'regcontents': ['foo'], 'regname': 'a', 'operator': 'y', 'regtype': 'v'},
1213    \g:event)
1214  norm y_
1215  call assert_equal(
1216    \{'regcontents': ['foo'], 'regname': '',  'operator': 'y', 'regtype': 'V'},
1217    \g:event)
1218  call feedkeys("\<C-V>y", 'x')
1219  call assert_equal(
1220    \{'regcontents': ['f'], 'regname': '',  'operator': 'y', 'regtype': "\x161"},
1221    \g:event)
1222  norm "xciwbar
1223  call assert_equal(
1224    \{'regcontents': ['foo'], 'regname': 'x', 'operator': 'c', 'regtype': 'v'},
1225    \g:event)
1226  norm "bdiw
1227  call assert_equal(
1228    \{'regcontents': ['bar'], 'regname': 'b', 'operator': 'd', 'regtype': 'v'},
1229    \g:event)
1230
1231  call assert_equal({}, v:event)
1232
1233  au! TextYankPost
1234  unlet g:event
1235  bwipe!
1236endfunc
1237
1238func Test_nocatch_wipe_all_buffers()
1239  " Real nasty autocommand: wipe all buffers on any event.
1240  au * * bwipe *
1241  " Get E93 first?
1242  " call assert_fails('next x', 'E93:')
1243  call assert_fails('next x', 'E517:')
1244  bwipe
1245  au!
1246endfunc
1247
1248func Test_nocatch_wipe_dummy_buffer()
1249  " Nasty autocommand: wipe buffer on any event.
1250  au * x bwipe
1251  call assert_fails('lv½ /x', 'E480')
1252  au!
1253endfunc
1254
1255function s:Before_test_dirchanged()
1256  augroup test_dirchanged
1257    autocmd!
1258  augroup END
1259  let s:li = []
1260  let s:dir_this = getcwd()
1261  let s:dir_foo = s:dir_this . '/foo'
1262  call mkdir(s:dir_foo)
1263  let s:dir_bar = s:dir_this . '/bar'
1264  call mkdir(s:dir_bar)
1265endfunc
1266
1267function s:After_test_dirchanged()
1268  exe 'cd' s:dir_this
1269  call delete(s:dir_foo, 'd')
1270  call delete(s:dir_bar, 'd')
1271  augroup test_dirchanged
1272    autocmd!
1273  augroup END
1274endfunc
1275
1276function Test_dirchanged_global()
1277  call s:Before_test_dirchanged()
1278  autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
1279  autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
1280  exe 'cd' s:dir_foo
1281  call assert_equal(["cd:", s:dir_foo], s:li)
1282  exe 'cd' s:dir_foo
1283  call assert_equal(["cd:", s:dir_foo], s:li)
1284  exe 'lcd' s:dir_bar
1285  call assert_equal(["cd:", s:dir_foo], s:li)
1286  call s:After_test_dirchanged()
1287endfunc
1288
1289function Test_dirchanged_local()
1290  call s:Before_test_dirchanged()
1291  autocmd test_dirchanged DirChanged window call add(s:li, "lcd:")
1292  autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>"))
1293  exe 'cd' s:dir_foo
1294  call assert_equal([], s:li)
1295  exe 'lcd' s:dir_bar
1296  call assert_equal(["lcd:", s:dir_bar], s:li)
1297  exe 'lcd' s:dir_bar
1298  call assert_equal(["lcd:", s:dir_bar], s:li)
1299  call s:After_test_dirchanged()
1300endfunc
1301
1302function Test_dirchanged_auto()
1303  if !exists('+autochdir')
1304    return
1305  endif
1306  call s:Before_test_dirchanged()
1307  call test_autochdir()
1308  autocmd test_dirchanged DirChanged auto call add(s:li, "auto:")
1309  autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
1310  set acd
1311  exe 'cd ..'
1312  call assert_equal([], s:li)
1313  exe 'edit ' . s:dir_foo . '/Xfile'
1314  call assert_equal(s:dir_foo, getcwd())
1315  call assert_equal(["auto:", s:dir_foo], s:li)
1316  set noacd
1317  bwipe!
1318  call s:After_test_dirchanged()
1319endfunc
1320
1321" Test TextChangedI and TextChangedP
1322func Test_ChangedP()
1323  new
1324  call setline(1, ['foo', 'bar', 'foobar'])
1325  call test_override("char_avail", 1)
1326  set complete=. completeopt=menuone
1327
1328  func! TextChangedAutocmd(char)
1329    let g:autocmd .= a:char
1330  endfunc
1331
1332  au! TextChanged <buffer> :call TextChangedAutocmd('N')
1333  au! TextChangedI <buffer> :call TextChangedAutocmd('I')
1334  au! TextChangedP <buffer> :call TextChangedAutocmd('P')
1335
1336  call cursor(3, 1)
1337  let g:autocmd = ''
1338  call feedkeys("o\<esc>", 'tnix')
1339  call assert_equal('I', g:autocmd)
1340
1341  let g:autocmd = ''
1342  call feedkeys("Sf", 'tnix')
1343  call assert_equal('II', g:autocmd)
1344
1345  let g:autocmd = ''
1346  call feedkeys("Sf\<C-N>", 'tnix')
1347  call assert_equal('IIP', g:autocmd)
1348
1349  let g:autocmd = ''
1350  call feedkeys("Sf\<C-N>\<C-N>", 'tnix')
1351  call assert_equal('IIPP', g:autocmd)
1352
1353  let g:autocmd = ''
1354  call feedkeys("Sf\<C-N>\<C-N>\<C-N>", 'tnix')
1355  call assert_equal('IIPPP', g:autocmd)
1356
1357  let g:autocmd = ''
1358  call feedkeys("Sf\<C-N>\<C-N>\<C-N>\<C-N>", 'tnix')
1359  call assert_equal('IIPPPP', g:autocmd)
1360
1361  call assert_equal(['foo', 'bar', 'foobar', 'foo'], getline(1, '$'))
1362  " TODO: how should it handle completeopt=noinsert,noselect?
1363
1364  " CleanUp
1365  call test_override("char_avail", 0)
1366  au! TextChanged
1367  au! TextChangedI
1368  au! TextChangedP
1369  delfu TextChangedAutocmd
1370  unlet! g:autocmd
1371  set complete&vim completeopt&vim
1372
1373  bw!
1374endfunc
1375
1376let g:setline_handled = v:false
1377func SetLineOne()
1378  if !g:setline_handled
1379    call setline(1, "(x)")
1380    let g:setline_handled = v:true
1381  endif
1382endfunc
1383
1384func Test_TextChangedI_with_setline()
1385  new
1386  call test_override('char_avail', 1)
1387  autocmd TextChangedI <buffer> call SetLineOne()
1388  call feedkeys("i(\<CR>\<Esc>", 'tx')
1389  call assert_equal('(', getline(1))
1390  call assert_equal('x)', getline(2))
1391  undo
1392  call assert_equal('', getline(1))
1393  call assert_equal('', getline(2))
1394
1395  call test_override('starting', 0)
1396  bwipe!
1397endfunc
1398
1399func Test_Changed_FirstTime()
1400  if !has('terminal') || has('gui_running')
1401    return
1402  endif
1403  " Prepare file for TextChanged event.
1404  call writefile([''], 'Xchanged.txt')
1405  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
1406  call assert_equal('running', term_getstatus(buf))
1407  " Wait for the ruler (in the status line) to be shown.
1408  " In ConPTY, there is additional character which is drawn up to the width of
1409  " the screen.
1410  if has('conpty')
1411    call WaitForAssert({-> assert_match('\<All.*$', term_getline(buf, 3))})
1412  else
1413    call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))})
1414  endif
1415  " It's only adding autocmd, so that no event occurs.
1416  call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>")
1417  call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
1418  call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
1419  call assert_equal([''], readfile('Xchanged.txt'))
1420
1421  " clean up
1422  call delete('Xchanged.txt')
1423  bwipe!
1424endfunc
1425
1426func Test_autocmd_nested()
1427  let g:did_nested = 0
1428  augroup Testing
1429    au WinNew * edit somefile
1430    au BufNew * let g:did_nested = 1
1431  augroup END
1432  split
1433  call assert_equal(0, g:did_nested)
1434  close
1435  bwipe! somefile
1436
1437  " old nested argument still works
1438  augroup Testing
1439    au!
1440    au WinNew * nested edit somefile
1441    au BufNew * let g:did_nested = 1
1442  augroup END
1443  split
1444  call assert_equal(1, g:did_nested)
1445  close
1446  bwipe! somefile
1447
1448  " New ++nested argument works
1449  augroup Testing
1450    au!
1451    au WinNew * ++nested edit somefile
1452    au BufNew * let g:did_nested = 1
1453  augroup END
1454  split
1455  call assert_equal(1, g:did_nested)
1456  close
1457  bwipe! somefile
1458
1459  augroup Testing
1460    au!
1461  augroup END
1462
1463  call assert_fails('au WinNew * ++nested ++nested echo bad', 'E983:')
1464  call assert_fails('au WinNew * nested nested echo bad', 'E983:')
1465endfunc
1466
1467func Test_autocmd_once()
1468  " Without ++once WinNew triggers twice
1469  let g:did_split = 0
1470  augroup Testing
1471    au WinNew * let g:did_split += 1
1472  augroup END
1473  split
1474  split
1475  call assert_equal(2, g:did_split)
1476  call assert_true(exists('#WinNew'))
1477  close
1478  close
1479
1480  " With ++once WinNew triggers once
1481  let g:did_split = 0
1482  augroup Testing
1483    au!
1484    au WinNew * ++once let g:did_split += 1
1485  augroup END
1486  split
1487  split
1488  call assert_equal(1, g:did_split)
1489  call assert_false(exists('#WinNew'))
1490  close
1491  close
1492
1493  call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
1494endfunc
1495
1496func Test_autocmd_bufreadpre()
1497  new
1498  let b:bufreadpre = 1
1499  call append(0, range(100))
1500  w! XAutocmdBufReadPre.txt
1501  autocmd BufReadPre <buffer> :let b:bufreadpre += 1
1502  norm! 50gg
1503  sp
1504  norm! 100gg
1505  wincmd p
1506  let g:wsv1 = winsaveview()
1507  wincmd p
1508  let g:wsv2 = winsaveview()
1509  " triggers BufReadPre, should not move the cursor in either window
1510  " The topline may change one line in a large window.
1511  edit
1512  call assert_inrange(g:wsv2.topline - 1, g:wsv2.topline + 1, winsaveview().topline)
1513  call assert_equal(g:wsv2.lnum, winsaveview().lnum)
1514  call assert_equal(2, b:bufreadpre)
1515  wincmd p
1516  call assert_equal(g:wsv1.topline, winsaveview().topline)
1517  call assert_equal(g:wsv1.lnum, winsaveview().lnum)
1518  call assert_equal(2, b:bufreadpre)
1519  " Now set the cursor position in an BufReadPre autocommand
1520  " (even though the position will be invalid, this should make Vim reset the
1521  " cursor position in the other window.
1522  wincmd p
1523  set cpo+=g
1524  " won't do anything, but try to set the cursor on an invalid lnum
1525  autocmd BufReadPre <buffer> :norm! 70gg
1526  " triggers BufReadPre, should not move the cursor in either window
1527  e
1528  call assert_equal(1, winsaveview().topline)
1529  call assert_equal(1, winsaveview().lnum)
1530  call assert_equal(3, b:bufreadpre)
1531  wincmd p
1532  call assert_equal(g:wsv1.topline, winsaveview().topline)
1533  call assert_equal(g:wsv1.lnum, winsaveview().lnum)
1534  call assert_equal(3, b:bufreadpre)
1535  close
1536  close
1537  call delete('XAutocmdBufReadPre.txt')
1538  set cpo-=g
1539endfunc
1540
1541" FileChangedShell tested in test_filechanged.vim
1542
1543" Tests for the following autocommands:
1544" - FileWritePre	writing a compressed file
1545" - FileReadPost	reading a compressed file
1546" - BufNewFile		reading a file template
1547" - BufReadPre		decompressing the file to be read
1548" - FilterReadPre	substituting characters in the temp file
1549" - FilterReadPost	substituting characters after filtering
1550" - FileReadPre		set options for decompression
1551" - FileReadPost	decompress the file
1552func Test_ReadWrite_Autocmds()
1553  " Run this test only on Unix-like systems and if gzip is available
1554  if !has('unix') || !executable("gzip")
1555    return
1556  endif
1557
1558  " Make $GZIP empty, "-v" would cause trouble.
1559  let $GZIP = ""
1560
1561  " Use a FileChangedShell autocommand to avoid a prompt for 'Xtestfile.gz'
1562  " being modified outside of Vim (noticed on Solaris).
1563  au FileChangedShell * echo 'caught FileChangedShell'
1564
1565  " Test for the FileReadPost, FileWritePre and FileWritePost autocmds
1566  augroup Test1
1567    au!
1568    au FileWritePre    *.gz   '[,']!gzip
1569    au FileWritePost   *.gz   undo
1570    au FileReadPost    *.gz   '[,']!gzip -d
1571  augroup END
1572
1573  new
1574  set bin
1575  call append(0, [
1576	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
1577	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1578	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
1579	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1580	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
1581	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1582	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
1583	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1584	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
1585	      \ ])
1586  1,9write! Xtestfile.gz
1587  enew! | close
1588
1589  new
1590  " Read and decompress the testfile
1591  0read Xtestfile.gz
1592  call assert_equal([
1593	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
1594	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1595	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
1596	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1597	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
1598	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1599	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
1600	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1601	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
1602	      \ ], getline(1, 9))
1603  enew! | close
1604
1605  augroup Test1
1606    au!
1607  augroup END
1608
1609  " Test for the FileAppendPre and FileAppendPost autocmds
1610  augroup Test2
1611    au!
1612    au BufNewFile      *.c    read Xtest.c
1613    au FileAppendPre   *.out  '[,']s/new/NEW/
1614    au FileAppendPost  *.out  !cat Xtest.c >> test.out
1615  augroup END
1616
1617  call writefile(['/*', ' * Here is a new .c file', ' */'], 'Xtest.c')
1618  new foo.c			" should load Xtest.c
1619  call assert_equal(['/*', ' * Here is a new .c file', ' */'], getline(2, 4))
1620  w! >> test.out		" append it to the output file
1621
1622  let contents = readfile('test.out')
1623  call assert_equal(' * Here is a NEW .c file', contents[2])
1624  call assert_equal(' * Here is a new .c file', contents[5])
1625
1626  call delete('test.out')
1627  enew! | close
1628  augroup Test2
1629    au!
1630  augroup END
1631
1632  " Test for the BufReadPre and BufReadPost autocmds
1633  augroup Test3
1634    au!
1635    " setup autocommands to decompress before reading and re-compress
1636    " afterwards
1637    au BufReadPre  *.gz  exe '!gzip -d ' . shellescape(expand("<afile>"))
1638    au BufReadPre  *.gz  call rename(expand("<afile>:r"), expand("<afile>"))
1639    au BufReadPost *.gz  call rename(expand("<afile>"), expand("<afile>:r"))
1640    au BufReadPost *.gz  exe '!gzip ' . shellescape(expand("<afile>:r"))
1641  augroup END
1642
1643  e! Xtestfile.gz		" Edit compressed file
1644  call assert_equal([
1645	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
1646	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1647	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
1648	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1649	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
1650	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1651	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
1652	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1653	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
1654	      \ ], getline(1, 9))
1655
1656  w! >> test.out		" Append it to the output file
1657
1658  augroup Test3
1659    au!
1660  augroup END
1661
1662  " Test for the FilterReadPre and FilterReadPost autocmds.
1663  set shelltemp			" need temp files here
1664  augroup Test4
1665    au!
1666    au FilterReadPre   *.out  call rename(expand("<afile>"), expand("<afile>") . ".t")
1667    au FilterReadPre   *.out  exe 'silent !sed s/e/E/ ' . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))
1668    au FilterReadPre   *.out  exe 'silent !rm ' . shellescape(expand("<afile>")) . '.t'
1669    au FilterReadPost  *.out  '[,']s/x/X/g
1670  augroup END
1671
1672  e! test.out			" Edit the output file
1673  1,$!cat
1674  call assert_equal([
1675	      \ 'linE 2	AbcdefghijklmnopqrstuvwXyz',
1676	      \ 'linE 3	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
1677	      \ 'linE 4	AbcdefghijklmnopqrstuvwXyz',
1678	      \ 'linE 5	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
1679	      \ 'linE 6	AbcdefghijklmnopqrstuvwXyz',
1680	      \ 'linE 7	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
1681	      \ 'linE 8	AbcdefghijklmnopqrstuvwXyz',
1682	      \ 'linE 9	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
1683	      \ 'linE 10 AbcdefghijklmnopqrstuvwXyz'
1684	      \ ], getline(1, 9))
1685  call assert_equal([
1686	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
1687	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1688	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
1689	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1690	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
1691	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1692	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
1693	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1694	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
1695	      \ ], readfile('test.out'))
1696
1697  augroup Test4
1698    au!
1699  augroup END
1700  set shelltemp&vim
1701
1702  " Test for the FileReadPre and FileReadPost autocmds.
1703  augroup Test5
1704    au!
1705    au FileReadPre *.gz exe 'silent !gzip -d ' . shellescape(expand("<afile>"))
1706    au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
1707    au FileReadPost *.gz '[,']s/l/L/
1708  augroup END
1709
1710  new
1711  0r Xtestfile.gz		" Read compressed file
1712  call assert_equal([
1713	      \ 'Line 2	Abcdefghijklmnopqrstuvwxyz',
1714	      \ 'Line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1715	      \ 'Line 4	Abcdefghijklmnopqrstuvwxyz',
1716	      \ 'Line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1717	      \ 'Line 6	Abcdefghijklmnopqrstuvwxyz',
1718	      \ 'Line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1719	      \ 'Line 8	Abcdefghijklmnopqrstuvwxyz',
1720	      \ 'Line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1721	      \ 'Line 10 Abcdefghijklmnopqrstuvwxyz'
1722	      \ ], getline(1, 9))
1723  call assert_equal([
1724	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
1725	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1726	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
1727	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1728	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
1729	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1730	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
1731	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
1732	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
1733	      \ ], readfile('Xtestfile.gz'))
1734
1735  augroup Test5
1736    au!
1737  augroup END
1738
1739  au! FileChangedShell
1740  call delete('Xtestfile.gz')
1741  call delete('Xtest.c')
1742  call delete('test.out')
1743endfunc
1744
1745func Test_throw_in_BufWritePre()
1746  new
1747  call setline(1, ['one', 'two', 'three'])
1748  call assert_false(filereadable('Xthefile'))
1749  augroup throwing
1750    au BufWritePre X* throw 'do not write'
1751  augroup END
1752  try
1753    w Xthefile
1754  catch
1755    let caught = 1
1756  endtry
1757  call assert_equal(1, caught)
1758  call assert_false(filereadable('Xthefile'))
1759
1760  bwipe!
1761  au! throwing
1762endfunc
1763