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