xref: /vim-8.2.3635/src/testdir/test_autocmd.vim (revision f0b03c4e)
1" Tests for autocommands
2
3func! s:cleanup_buffers() abort
4  for bnr in range(1, bufnr('$'))
5    if bufloaded(bnr) && bufnr('%') != bnr
6      execute 'bd! ' . bnr
7    endif
8  endfor
9endfunc
10
11func Test_vim_did_enter()
12  call assert_false(v:vim_did_enter)
13
14  " This script will never reach the main loop, can't check if v:vim_did_enter
15  " becomes one.
16endfunc
17
18if has('timers')
19  func ExitInsertMode(id)
20    call feedkeys("\<Esc>")
21  endfunc
22
23  func Test_cursorhold_insert()
24    " Need to move the cursor.
25    call feedkeys("ggG", "xt")
26
27    let g:triggered = 0
28    au CursorHoldI * let g:triggered += 1
29    set updatetime=20
30    call timer_start(100, 'ExitInsertMode')
31    call feedkeys('a', 'x!')
32    call assert_equal(1, g:triggered)
33    au! CursorHoldI
34    set updatetime&
35  endfunc
36
37  func Test_cursorhold_insert_ctrl_x()
38    let g:triggered = 0
39    au CursorHoldI * let g:triggered += 1
40    set updatetime=20
41    call timer_start(100, 'ExitInsertMode')
42    " CursorHoldI does not trigger after CTRL-X
43    call feedkeys("a\<C-X>", 'x!')
44    call assert_equal(0, g:triggered)
45    au! CursorHoldI
46    set updatetime&
47  endfunc
48endif
49
50func Test_bufunload()
51  augroup test_bufunload_group
52    autocmd!
53    autocmd BufUnload * call add(s:li, "bufunload")
54    autocmd BufDelete * call add(s:li, "bufdelete")
55    autocmd BufWipeout * call add(s:li, "bufwipeout")
56  augroup END
57
58  let s:li=[]
59  new
60  setlocal bufhidden=
61  bunload
62  call assert_equal(["bufunload", "bufdelete"], s:li)
63
64  let s:li=[]
65  new
66  setlocal bufhidden=delete
67  bunload
68  call assert_equal(["bufunload", "bufdelete"], s:li)
69
70  let s:li=[]
71  new
72  setlocal bufhidden=unload
73  bwipeout
74  call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li)
75
76  au! test_bufunload_group
77  augroup! test_bufunload_group
78endfunc
79
80" SEGV occurs in older versions.  (At least 7.4.2005 or older)
81func Test_autocmd_bufunload_with_tabnext()
82  tabedit
83  tabfirst
84
85  augroup test_autocmd_bufunload_with_tabnext_group
86    autocmd!
87    autocmd BufUnload <buffer> tabnext
88  augroup END
89
90  quit
91  call assert_equal(2, tabpagenr('$'))
92
93  autocmd! test_autocmd_bufunload_with_tabnext_group
94  augroup! test_autocmd_bufunload_with_tabnext_group
95  tablast
96  quit
97endfunc
98
99func Test_autocmd_bufwinleave_with_tabfirst()
100  tabedit
101  augroup sample
102    autocmd!
103    autocmd BufWinLeave <buffer> tabfirst
104  augroup END
105  call setline(1, ['a', 'b', 'c'])
106  edit! a.txt
107  tabclose
108endfunc
109
110" SEGV occurs in older versions.  (At least 7.4.2321 or older)
111func Test_autocmd_bufunload_avoiding_SEGV_01()
112  split aa.txt
113  let lastbuf = bufnr('$')
114
115  augroup test_autocmd_bufunload
116    autocmd!
117    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
118  augroup END
119
120  call assert_fails('edit bb.txt', 'E937:')
121
122  autocmd! test_autocmd_bufunload
123  augroup! test_autocmd_bufunload
124  bwipe! aa.txt
125  bwipe! bb.txt
126endfunc
127
128" SEGV occurs in older versions.  (At least 7.4.2321 or older)
129func Test_autocmd_bufunload_avoiding_SEGV_02()
130  setlocal buftype=nowrite
131  let lastbuf = bufnr('$')
132
133  augroup test_autocmd_bufunload
134    autocmd!
135    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
136  augroup END
137
138  normal! i1
139  call assert_fails('edit a.txt', 'E517:')
140  call feedkeys("\<CR>")
141
142  autocmd! test_autocmd_bufunload
143  augroup! test_autocmd_bufunload
144  bwipe! a.txt
145endfunc
146
147func Test_win_tab_autocmd()
148  let g:record = []
149
150  augroup testing
151    au WinNew * call add(g:record, 'WinNew')
152    au WinEnter * call add(g:record, 'WinEnter')
153    au WinLeave * call add(g:record, 'WinLeave')
154    au TabNew * call add(g:record, 'TabNew')
155    au TabClosed * call add(g:record, 'TabClosed')
156    au TabEnter * call add(g:record, 'TabEnter')
157    au TabLeave * call add(g:record, 'TabLeave')
158  augroup END
159
160  split
161  tabnew
162  close
163  close
164
165  call assert_equal([
166	\ 'WinLeave', 'WinNew', 'WinEnter',
167	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
168	\ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter',
169	\ 'WinLeave', 'WinEnter'
170	\ ], g:record)
171
172  let g:record = []
173  tabnew somefile
174  tabnext
175  bwipe somefile
176
177  call assert_equal([
178	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
179	\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
180	\ 'TabClosed'
181	\ ], g:record)
182
183  augroup testing
184    au!
185  augroup END
186  unlet g:record
187endfunc
188
189func s:AddAnAutocmd()
190  augroup vimBarTest
191    au BufReadCmd * echo 'hello'
192  augroup END
193  call assert_equal(3, len(split(execute('au vimBarTest'), "\n")))
194endfunc
195
196func Test_early_bar()
197  " test that a bar is recognized before the {event}
198  call s:AddAnAutocmd()
199  augroup vimBarTest | au! | augroup END
200  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
201
202  call s:AddAnAutocmd()
203  augroup vimBarTest| au!| augroup END
204  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
205
206  " test that a bar is recognized after the {event}
207  call s:AddAnAutocmd()
208  augroup vimBarTest| au!BufReadCmd| augroup END
209  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
210
211  " test that a bar is recognized after the {group}
212  call s:AddAnAutocmd()
213  au! vimBarTest|echo 'hello'
214  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
215endfunc
216
217func RemoveGroup()
218  autocmd! StartOK
219  augroup! StartOK
220endfunc
221
222func Test_augroup_warning()
223  augroup TheWarning
224    au VimEnter * echo 'entering'
225  augroup END
226  call assert_true(match(execute('au VimEnter'), "TheWarning.*VimEnter") >= 0)
227  redir => res
228  augroup! TheWarning
229  redir END
230  call assert_true(match(res, "W19:") >= 0)
231  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
232
233  " check "Another" does not take the pace of the deleted entry
234  augroup Another
235  augroup END
236  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
237  augroup! Another
238
239  " no warning for postpone aucmd delete
240  augroup StartOK
241    au VimEnter * call RemoveGroup()
242  augroup END
243  call assert_true(match(execute('au VimEnter'), "StartOK.*VimEnter") >= 0)
244  redir => res
245  doautocmd VimEnter
246  redir END
247  call assert_true(match(res, "W19:") < 0)
248  au! VimEnter
249endfunc
250
251func Test_BufReadCmdHelp()
252  " This used to cause access to free memory
253  au BufReadCmd * e +h
254  help
255
256  au! BufReadCmd
257endfunc
258
259func Test_BufReadCmdHelpJump()
260  " This used to cause access to free memory
261  au BufReadCmd * e +h{
262  " } to fix highlighting
263  call assert_fails('help', 'E434:')
264
265  au! BufReadCmd
266endfunc
267
268func Test_augroup_deleted()
269  " This caused a crash before E936 was introduced
270  augroup x
271    call assert_fails('augroup! x', 'E936:')
272    au VimEnter * echo
273  augroup end
274  augroup! x
275  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
276  au! VimEnter
277endfunc
278
279" Tests for autocommands on :close command.
280" This used to be in test13.
281func Test_three_windows()
282  " Clean up buffers, because in some cases this function fails.
283  call s:cleanup_buffers()
284
285  " Write three files and open them, each in a window.
286  " Then go to next window, with autocommand that deletes the previous one.
287  " Do this twice, writing the file.
288  e! Xtestje1
289  call setline(1, 'testje1')
290  w
291  sp Xtestje2
292  call setline(1, 'testje2')
293  w
294  sp Xtestje3
295  call setline(1, 'testje3')
296  w
297  wincmd w
298  au WinLeave Xtestje2 bwipe
299  wincmd w
300  call assert_equal('Xtestje1', expand('%'))
301
302  au WinLeave Xtestje1 bwipe Xtestje3
303  close
304  call assert_equal('Xtestje1', expand('%'))
305
306  " Test deleting the buffer on a Unload event.  If this goes wrong there
307  " will be the ATTENTION prompt.
308  e Xtestje1
309  au!
310  au! BufUnload Xtestje1 bwipe
311  call assert_fails('e Xtestje3', 'E937:')
312  call assert_equal('Xtestje3', expand('%'))
313
314  e Xtestje2
315  sp Xtestje1
316  call assert_fails('e', 'E937:')
317  call assert_equal('Xtestje2', expand('%'))
318
319  " Test changing buffers in a BufWipeout autocommand.  If this goes wrong
320  " there are ml_line errors and/or a Crash.
321  au!
322  only
323  e Xanother
324  e Xtestje1
325  bwipe Xtestje2
326  bwipe Xtestje3
327  au BufWipeout Xtestje1 buf Xtestje1
328  bwipe
329  call assert_equal('Xanother', expand('%'))
330
331  only
332  help
333  wincmd w
334  1quit
335  call assert_equal('Xanother', expand('%'))
336
337  au!
338  enew
339  bwipe! Xtestje1
340  call delete('Xtestje1')
341  call delete('Xtestje2')
342  call delete('Xtestje3')
343endfunc
344
345func Test_BufEnter()
346  au! BufEnter
347  au Bufenter * let val = val . '+'
348  let g:val = ''
349  split NewFile
350  call assert_equal('+', g:val)
351  bwipe!
352  call assert_equal('++', g:val)
353
354  " Also get BufEnter when editing a directory
355  call mkdir('Xdir')
356  split Xdir
357  call assert_equal('+++', g:val)
358
359  " On MS-Windows we can't edit the directory, make sure we wipe the right
360  " buffer.
361  bwipe! Xdir
362
363  call delete('Xdir', 'd')
364  au! BufEnter
365endfunc
366
367" Closing a window might cause an endless loop
368" E814 for older Vims
369func Test_autocmd_bufwipe_in_SessLoadPost()
370  edit Xtest
371  tabnew
372  file Xsomething
373  set noswapfile
374  mksession!
375
376  let content = ['set nocp noswapfile',
377        \ 'let v:swapchoice="e"',
378        \ 'augroup test_autocmd_sessionload',
379        \ 'autocmd!',
380        \ 'autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!"',
381        \ 'augroup END',
382	\ '',
383	\ 'func WriteErrors()',
384	\ '  call writefile([execute("messages")], "Xerrors")',
385	\ 'endfunc',
386	\ 'au VimLeave * call WriteErrors()',
387        \ ]
388  call writefile(content, 'Xvimrc')
389  call system(v:progpath. ' -u Xvimrc --not-a-term --noplugins -S Session.vim -c cq')
390  let errors = join(readfile('Xerrors'))
391  call assert_match('E814', errors)
392
393  set swapfile
394  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
395    call delete(file)
396  endfor
397endfunc
398
399" SEGV occurs in older versions.
400func Test_autocmd_bufwipe_in_SessLoadPost2()
401  tabnew
402  set noswapfile
403  mksession!
404
405  let content = ['set nocp noswapfile',
406      \ 'function! DeleteInactiveBufs()',
407      \ '  tabfirst',
408      \ '  let tabblist = []',
409      \ '  for i in range(1, tabpagenr(''$''))',
410      \ '    call extend(tabblist, tabpagebuflist(i))',
411      \ '  endfor',
412      \ '  for b in range(1, bufnr(''$''))',
413      \ '    if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')',
414      \ '      exec ''bwipeout '' . b',
415      \ '    endif',
416      \ '  endfor',
417      \ '  echomsg "SessionLoadPost DONE"',
418      \ 'endfunction',
419      \ 'au SessionLoadPost * call DeleteInactiveBufs()',
420      \ '',
421      \ 'func WriteErrors()',
422      \ '  call writefile([execute("messages")], "Xerrors")',
423      \ 'endfunc',
424      \ 'au VimLeave * call WriteErrors()',
425      \ ]
426  call writefile(content, 'Xvimrc')
427  call system(v:progpath. ' -u Xvimrc --not-a-term --noplugins -S Session.vim -c cq')
428  let errors = join(readfile('Xerrors'))
429  " This probably only ever matches on unix.
430  call assert_notmatch('Caught deadly signal SEGV', errors)
431  call assert_match('SessionLoadPost DONE', errors)
432
433  set swapfile
434  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
435    call delete(file)
436  endfor
437endfunc
438
439func Test_empty_doau()
440  doau \|
441endfunc
442
443func s:AutoCommandOptionSet(match)
444  let item     = remove(g:options, 0)
445  let expected = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", item[0], item[1], item[2], item[3])
446  let actual   = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", a:match, v:option_old, v:option_new, v:option_type)
447  let g:opt    = [expected, actual]
448  "call assert_equal(expected, actual)
449endfunc
450
451func Test_OptionSet()
452  if !has("eval") || !has("autocmd") || !exists("+autochdir")
453    return
454  endif
455
456  badd test_autocmd.vim
457
458  call test_override('starting', 1)
459  set nocp
460  au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>"))
461
462  " 1: Setting number option"
463  let g:options=[['number', 0, 1, 'global']]
464  set nu
465  call assert_equal([], g:options)
466  call assert_equal(g:opt[0], g:opt[1])
467
468  " 2: Setting local number option"
469  let g:options=[['number', 1, 0, 'local']]
470  setlocal nonu
471  call assert_equal([], g:options)
472  call assert_equal(g:opt[0], g:opt[1])
473
474  " 3: Setting global number option"
475  let g:options=[['number', 1, 0, 'global']]
476  setglobal nonu
477  call assert_equal([], g:options)
478  call assert_equal(g:opt[0], g:opt[1])
479
480  " 4: Setting local autoindent option"
481  let g:options=[['autoindent', 0, 1, 'local']]
482  setlocal ai
483  call assert_equal([], g:options)
484  call assert_equal(g:opt[0], g:opt[1])
485
486  " 5: Setting global autoindent option"
487  let g:options=[['autoindent', 0, 1, 'global']]
488  setglobal ai
489  call assert_equal([], g:options)
490  call assert_equal(g:opt[0], g:opt[1])
491
492  " 6: Setting global autoindent option"
493  let g:options=[['autoindent', 1, 0, 'global']]
494  set ai!
495  call assert_equal([], g:options)
496  call assert_equal(g:opt[0], g:opt[1])
497
498  " Should not print anything, use :noa
499  " 7: don't trigger OptionSet"
500  let g:options=[['invalid', 1, 1, 'invalid']]
501  noa set nonu
502  call assert_equal([['invalid', 1, 1, 'invalid']], g:options)
503  call assert_equal(g:opt[0], g:opt[1])
504
505  " 8: Setting several global list and number option"
506  let g:options=[['list', 0, 1, 'global'], ['number', 0, 1, 'global']]
507  set list nu
508  call assert_equal([], g:options)
509  call assert_equal(g:opt[0], g:opt[1])
510
511  " 9: don't trigger OptionSet"
512  let g:options=[['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']]
513  noa set nolist nonu
514  call assert_equal([['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']], g:options)
515  call assert_equal(g:opt[0], g:opt[1])
516
517  " 10: Setting global acd"
518  let g:options=[['autochdir', 0, 1, 'local']]
519  setlocal acd
520  call assert_equal([], g:options)
521  call assert_equal(g:opt[0], g:opt[1])
522
523  " 11: Setting global autoread (also sets local value)"
524  let g:options=[['autoread', 0, 1, 'global']]
525  set ar
526  call assert_equal([], g:options)
527  call assert_equal(g:opt[0], g:opt[1])
528
529  " 12: Setting local autoread"
530  let g:options=[['autoread', 1, 1, 'local']]
531  setlocal ar
532  call assert_equal([], g:options)
533  call assert_equal(g:opt[0], g:opt[1])
534
535  " 13: Setting global autoread"
536  let g:options=[['autoread', 1, 0, 'global']]
537  setglobal invar
538  call assert_equal([], g:options)
539  call assert_equal(g:opt[0], g:opt[1])
540
541  " 14: Setting option backspace through :let"
542  let g:options=[['backspace', '', 'eol,indent,start', 'global']]
543  let &bs="eol,indent,start"
544  call assert_equal([], g:options)
545  call assert_equal(g:opt[0], g:opt[1])
546
547  " 15: Setting option backspace through setbufvar()"
548  let g:options=[['backup', 0, 1, 'local']]
549  " try twice, first time, shouldn't trigger because option name is invalid,
550  " second time, it should trigger
551  let bnum = bufnr('%')
552  call assert_fails("call setbufvar(bnum, '&l:bk', 1)", "E355")
553  " should trigger, use correct option name
554  call setbufvar(bnum, '&backup', 1)
555  call assert_equal([], g:options)
556  call assert_equal(g:opt[0], g:opt[1])
557
558  " 16: Setting number option using setwinvar"
559  let g:options=[['number', 0, 1, 'local']]
560  call setwinvar(0, '&number', 1)
561  call assert_equal([], g:options)
562  call assert_equal(g:opt[0], g:opt[1])
563
564  " 17: Setting key option, shouldn't trigger"
565  let g:options=[['key', 'invalid', 'invalid1', 'invalid']]
566  setlocal key=blah
567  setlocal key=
568  call assert_equal([['key', 'invalid', 'invalid1', 'invalid']], g:options)
569  call assert_equal(g:opt[0], g:opt[1])
570
571  " 18: Setting string option"
572  let oldval = &tags
573  let g:options=[['tags', oldval, 'tagpath', 'global']]
574  set tags=tagpath
575  call assert_equal([], g:options)
576  call assert_equal(g:opt[0], g:opt[1])
577
578  " 1l: Resetting string option"
579  let g:options=[['tags', 'tagpath', oldval, 'global']]
580  set tags&
581  call assert_equal([], g:options)
582  call assert_equal(g:opt[0], g:opt[1])
583
584  " Cleanup
585  au! OptionSet
586  for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp']
587    exe printf(":set %s&vi", opt)
588  endfor
589  call test_override('starting', 0)
590  delfunc! AutoCommandOptionSet
591endfunc
592
593func Test_OptionSet_diffmode()
594  call test_override('starting', 1)
595  " 18: Changing an option when enetering diff mode
596  new
597  au OptionSet diff :let &l:cul=v:option_new
598
599  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
600  call assert_equal(0, &l:cul)
601  diffthis
602  call assert_equal(1, &l:cul)
603
604  vnew
605  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
606  call assert_equal(0, &l:cul)
607  diffthis
608  call assert_equal(1, &l:cul)
609
610  diffoff
611  call assert_equal(0, &l:cul)
612  call assert_equal(1, getwinvar(2, '&l:cul'))
613  bw!
614
615  call assert_equal(1, &l:cul)
616  diffoff!
617  call assert_equal(0, &l:cul)
618  call assert_equal(0, getwinvar(1, '&l:cul'))
619  bw!
620
621  " Cleanup
622  au! OptionSet
623  call test_override('starting', 0)
624endfunc
625
626func Test_OptionSet_diffmode_close()
627  call test_override('starting', 1)
628  " 19: Try to close the current window when entering diff mode
629  " should not segfault
630  new
631  au OptionSet diff close
632
633  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
634  call assert_fails(':diffthis', 'E788')
635  call assert_equal(1, &diff)
636  vnew
637  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
638  call assert_fails(':diffthis', 'E788')
639  call assert_equal(1, &diff)
640  bw!
641  call assert_fails(':diffoff!', 'E788')
642  bw!
643
644  " Cleanup
645  au! OptionSet
646  call test_override('starting', 0)
647  "delfunc! AutoCommandOptionSet
648endfunc
649
650" Test for Bufleave autocommand that deletes the buffer we are about to edit.
651func Test_BufleaveWithDelete()
652  new | edit Xfile1
653
654  augroup test_bufleavewithdelete
655      autocmd!
656      autocmd BufLeave Xfile1 bwipe Xfile2
657  augroup END
658
659  call assert_fails('edit Xfile2', 'E143:')
660  call assert_equal('Xfile1', bufname('%'))
661
662  autocmd! test_bufleavewithdelete BufLeave Xfile1
663  augroup! test_bufleavewithdelete
664
665  new
666  bwipe! Xfile1
667endfunc
668
669" Test for autocommand that changes the buffer list, when doing ":ball".
670func Test_Acmd_BufAll()
671  enew!
672  %bwipe!
673  call writefile(['Test file Xxx1'], 'Xxx1')
674  call writefile(['Test file Xxx2'], 'Xxx2')
675  call writefile(['Test file Xxx3'], 'Xxx3')
676
677  " Add three files to the buffer list
678  split Xxx1
679  close
680  split Xxx2
681  close
682  split Xxx3
683  close
684
685  " Wipe the buffer when the buffer is opened
686  au BufReadPost Xxx2 bwipe
687
688  call append(0, 'Test file Xxx4')
689  ball
690
691  call assert_equal(2, winnr('$'))
692  call assert_equal('Xxx1', bufname(winbufnr(winnr('$'))))
693  wincmd t
694
695  au! BufReadPost
696  %bwipe!
697  call delete('Xxx1')
698  call delete('Xxx2')
699  call delete('Xxx3')
700  enew! | only
701endfunc
702
703" Test for autocommand that changes current buffer on BufEnter event.
704" Check if modelines are interpreted for the correct buffer.
705func Test_Acmd_BufEnter()
706  %bwipe!
707  call writefile(['start of test file Xxx1',
708	      \ "\<Tab>this is a test",
709	      \ 'end of test file Xxx1'], 'Xxx1')
710  call writefile(['start of test file Xxx2',
711	      \ 'vim: set noai :',
712	      \ "\<Tab>this is a test",
713	      \ 'end of test file Xxx2'], 'Xxx2')
714
715  au BufEnter Xxx2 brew
716  set ai modeline modelines=3
717  edit Xxx1
718  " edit Xxx2, autocmd will do :brew
719  edit Xxx2
720  exe "normal G?this is a\<CR>"
721  " Append text with autoindent to this file
722  normal othis should be auto-indented
723  call assert_equal("\<Tab>this should be auto-indented", getline('.'))
724  call assert_equal(3, line('.'))
725  " Remove autocmd and edit Xxx2 again
726  au! BufEnter Xxx2
727  buf! Xxx2
728  exe "normal G?this is a\<CR>"
729  " append text without autoindent to Xxx
730  normal othis should be in column 1
731  call assert_equal("this should be in column 1", getline('.'))
732  call assert_equal(4, line('.'))
733
734  %bwipe!
735  call delete('Xxx1')
736  call delete('Xxx2')
737  set ai&vim modeline&vim modelines&vim
738endfunc
739
740" Test for issue #57
741" do not move cursor on <c-o> when autoindent is set
742func Test_ai_CTRL_O()
743  enew!
744  set ai
745  let save_fo = &fo
746  set fo+=r
747  exe "normal o# abcdef\<Esc>2hi\<CR>\<C-O>d0\<Esc>"
748  exe "normal o# abcdef\<Esc>2hi\<C-O>d0\<Esc>"
749  call assert_equal(['# abc', 'def', 'def'], getline(2, 4))
750
751  set ai&vim
752  let &fo = save_fo
753  enew!
754endfunc
755
756" Test for autocommand that deletes the current buffer on BufLeave event.
757" Also test deleting the last buffer, should give a new, empty buffer.
758func Test_BufLeave_Wipe()
759  %bwipe!
760  let content = ['start of test file Xxx',
761	      \ 'this is a test',
762	      \ 'end of test file Xxx']
763  call writefile(content, 'Xxx1')
764  call writefile(content, 'Xxx2')
765
766  au BufLeave Xxx2 bwipe
767  edit Xxx1
768  split Xxx2
769  " delete buffer Xxx2, we should be back to Xxx1
770  bwipe
771  call assert_equal('Xxx1', bufname('%'))
772  call assert_equal(1, winnr('$'))
773
774  " Create an alternate buffer
775  %write! test.out
776  call assert_equal('test.out', bufname('#'))
777  " delete alternate buffer
778  bwipe test.out
779  call assert_equal('Xxx1', bufname('%'))
780  call assert_equal('', bufname('#'))
781
782  au BufLeave Xxx1 bwipe
783  " delete current buffer, get an empty one
784  bwipe!
785  call assert_equal(1, line('$'))
786  call assert_equal('', bufname('%'))
787  let g:bufinfo = getbufinfo()
788  call assert_equal(1, len(g:bufinfo))
789
790  call delete('Xxx1')
791  call delete('Xxx2')
792  call delete('test.out')
793  %bwipe
794  au! BufLeave
795
796  " check that bufinfo doesn't contain a pointer to freed memory
797  call test_garbagecollect_now()
798endfunc
799
800func Test_QuitPre()
801  edit Xfoo
802  let winid = win_getid(winnr())
803  split Xbar
804  au! QuitPre * let g:afile = expand('<afile>')
805  " Close the other window, <afile> should be correct.
806  exe win_id2win(winid) . 'q'
807  call assert_equal('Xfoo', g:afile)
808
809  unlet g:afile
810  bwipe Xfoo
811  bwipe Xbar
812endfunc
813
814func Test_Cmdline()
815  au! CmdlineEnter : let g:entered = expand('<afile>')
816  au! CmdlineLeave : let g:left = expand('<afile>')
817  let g:entered = 0
818  let g:left = 0
819  call feedkeys(":echo 'hello'\<CR>", 'xt')
820  call assert_equal(':', g:entered)
821  call assert_equal(':', g:left)
822  au! CmdlineEnter
823  au! CmdlineLeave
824
825  au! CmdlineEnter / let g:entered = expand('<afile>')
826  au! CmdlineLeave / let g:left = expand('<afile>')
827  let g:entered = 0
828  let g:left = 0
829  new
830  call setline(1, 'hello')
831  call feedkeys("/hello\<CR>", 'xt')
832  call assert_equal('/', g:entered)
833  call assert_equal('/', g:left)
834  bwipe!
835  au! CmdlineEnter
836  au! CmdlineLeave
837endfunc
838
839" Test for BufWritePre autocommand that deletes or unloads the buffer.
840func Test_BufWritePre()
841  %bwipe
842  au BufWritePre Xxx1 bunload
843  au BufWritePre Xxx2 bwipe
844
845  call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1')
846  call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2')
847
848  edit Xtest
849  e! Xxx2
850  bdel Xtest
851  e Xxx1
852  " write it, will unload it and give an error msg
853  call assert_fails('w', 'E203')
854  call assert_equal('Xxx2', bufname('%'))
855  edit Xtest
856  e! Xxx2
857  bwipe Xtest
858  " write it, will delete the buffer and give an error msg
859  call assert_fails('w', 'E203')
860  call assert_equal('Xxx1', bufname('%'))
861  au! BufWritePre
862  call delete('Xxx1')
863  call delete('Xxx2')
864endfunc
865
866" Test for BufUnload autocommand that unloads all the other buffers
867func Test_bufunload_all()
868  call writefile(['Test file Xxx1'], 'Xxx1')"
869  call writefile(['Test file Xxx2'], 'Xxx2')"
870
871  let content = [
872	      \ "func UnloadAllBufs()",
873	      \ "  let i = 1",
874	      \ "  while i <= bufnr('$')",
875	      \ "    if i != bufnr('%') && bufloaded(i)",
876	      \ "      exe  i . 'bunload'",
877	      \ "    endif",
878	      \ "    let i += 1",
879	      \ "  endwhile",
880	      \ "endfunc",
881	      \ "au BufUnload * call UnloadAllBufs()",
882	      \ "au VimLeave * call writefile(['Test Finished'], 'Xout')",
883	      \ "edit Xxx1",
884	      \ "split Xxx2",
885	      \ "q"]
886  call writefile(content, 'Xtest')
887
888  call delete('Xout')
889  call system(v:progpath. ' --clean -N --not-a-term -S Xtest')
890  call assert_true(filereadable('Xout'))
891
892  call delete('Xxx1')
893  call delete('Xxx2')
894  call delete('Xtest')
895  call delete('Xout')
896endfunc
897
898" Some tests for buffer-local autocommands
899func Test_buflocal_autocmd()
900  let g:bname = ''
901  edit xx
902  au BufLeave <buffer> let g:bname = expand("%")
903  " here, autocommand for xx should trigger.
904  " but autocommand shall not apply to buffer named <buffer>.
905  edit somefile
906  call assert_equal('xx', g:bname)
907  let g:bname = ''
908  " here, autocommand shall be auto-deleted
909  bwipe xx
910  " autocmd should not trigger
911  edit xx
912  call assert_equal('', g:bname)
913  " autocmd should not trigger
914  edit somefile
915  call assert_equal('', g:bname)
916  enew
917  unlet g:bname
918endfunc
919
920" Test for "*Cmd" autocommands
921func Test_Cmd_Autocmds()
922  call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx')
923
924  enew!
925  au BufReadCmd XtestA 0r Xxx|$del
926  edit XtestA			" will read text of Xxd instead
927  call assert_equal('start of Xxx', getline(1))
928
929  au BufWriteCmd XtestA call append(line("$"), "write")
930  write				" will append a line to the file
931  call assert_equal('write', getline('$'))
932  call assert_fails('read XtestA', 'E484')	" should not read anything
933  call assert_equal('write', getline(4))
934
935  " now we have:
936  " 1	start of Xxx
937  " 2		abc2
938  " 3	end of Xxx
939  " 4	write
940
941  au FileReadCmd XtestB '[r Xxx
942  2r XtestB			" will read Xxx below line 2 instead
943  call assert_equal('start of Xxx', getline(3))
944
945  " now we have:
946  " 1	start of Xxx
947  " 2		abc2
948  " 3	start of Xxx
949  " 4		abc2
950  " 5	end of Xxx
951  " 6	end of Xxx
952  " 7	write
953
954  au FileWriteCmd XtestC '[,']copy $
955  normal 4GA1
956  4,5w XtestC			" will copy lines 4 and 5 to the end
957  call assert_equal("\tabc21", getline(8))
958  call assert_fails('r XtestC', 'E484')	" should not read anything
959  call assert_equal("end of Xxx", getline(9))
960
961  " now we have:
962  " 1	start of Xxx
963  " 2		abc2
964  " 3	start of Xxx
965  " 4		abc21
966  " 5	end of Xxx
967  " 6	end of Xxx
968  " 7	write
969  " 8		abc21
970  " 9	end of Xxx
971
972  let g:lines = []
973  au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']")))
974  w >>XtestD			" will add lines to 'lines'
975  call assert_equal(9, len(g:lines))
976  call assert_fails('$r XtestD', 'E484')	" should not read anything
977  call assert_equal(9, line('$'))
978  call assert_equal('end of Xxx', getline('$'))
979
980  au BufReadCmd XtestE 0r Xxx|$del
981  sp XtestE			" split window with test.out
982  call assert_equal('end of Xxx', getline(3))
983
984  let g:lines = []
985  exe "normal 2Goasdf\<Esc>\<C-W>\<C-W>"
986  au BufWriteCmd XtestE call extend(g:lines, getline(0, '$'))
987  wall				" will write other window to 'lines'
988  call assert_equal(4, len(g:lines), g:lines)
989  call assert_equal('asdf', g:lines[2])
990
991  au! BufReadCmd
992  au! BufWriteCmd
993  au! FileReadCmd
994  au! FileWriteCmd
995  au! FileAppendCmd
996  %bwipe!
997  call delete('Xxx')
998  enew!
999endfunc
1000
1001func SetChangeMarks(start, end)
1002  exe a:start. 'mark ['
1003  exe a:end. 'mark ]'
1004endfunc
1005
1006" Verify the effects of autocmds on '[ and ']
1007func Test_change_mark_in_autocmds()
1008  edit! Xtest
1009  call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u", 'xtn')
1010
1011  call SetChangeMarks(2, 3)
1012  write
1013  call assert_equal([1, 4], [line("'["), line("']")])
1014
1015  call SetChangeMarks(2, 3)
1016  au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1017  write
1018  au! BufWritePre
1019
1020  if executable('cat')
1021    write XtestFilter
1022    write >> XtestFilter
1023
1024    call SetChangeMarks(2, 3)
1025    " Marks are set to the entire range of the write
1026    au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1027    " '[ is adjusted to just before the line that will receive the filtered
1028    " data
1029    au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")])
1030    " The filtered data is read into the buffer, and the source lines are
1031    " still present, so the range is after the source lines
1032    au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")])
1033    %!cat XtestFilter
1034    " After the filtered data is read, the original lines are deleted
1035    call assert_equal([1, 8], [line("'["), line("']")])
1036    au! FilterWritePre,FilterReadPre,FilterReadPost
1037    undo
1038
1039    call SetChangeMarks(1, 4)
1040    au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1041    au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")])
1042    au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1043    2,3!cat XtestFilter
1044    call assert_equal([2, 9], [line("'["), line("']")])
1045    au! FilterWritePre,FilterReadPre,FilterReadPost
1046    undo
1047
1048    call delete('XtestFilter')
1049  endif
1050
1051  call SetChangeMarks(1, 4)
1052  au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1053  2,3write Xtest2
1054  au! FileWritePre
1055
1056  call SetChangeMarks(2, 3)
1057  au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")])
1058  write >> Xtest2
1059  au! FileAppendPre
1060
1061  call SetChangeMarks(1, 4)
1062  au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")])
1063  2,3write >> Xtest2
1064  au! FileAppendPre
1065
1066  call SetChangeMarks(1, 1)
1067  au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")])
1068  au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1069  3read Xtest2
1070  au! FileReadPre,FileReadPost
1071  undo
1072
1073  call SetChangeMarks(4, 4)
1074  " When the line is 0, it's adjusted to 1
1075  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1076  au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")])
1077  0read Xtest2
1078  au! FileReadPre,FileReadPost
1079  undo
1080
1081  call SetChangeMarks(4, 4)
1082  " When the line is 0, it's adjusted to 1
1083  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1084  au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")])
1085  1read Xtest2
1086  au! FileReadPre,FileReadPost
1087  undo
1088
1089  bwipe!
1090  call delete('Xtest')
1091  call delete('Xtest2')
1092endfunc
1093
1094func Test_Filter_noshelltemp()
1095  if !executable('cat')
1096    return
1097  endif
1098
1099  enew!
1100  call setline(1, ['a', 'b', 'c', 'd'])
1101
1102  let shelltemp = &shelltemp
1103  set shelltemp
1104
1105  let g:filter_au = 0
1106  au FilterWritePre * let g:filter_au += 1
1107  au FilterReadPre * let g:filter_au += 1
1108  au FilterReadPost * let g:filter_au += 1
1109  %!cat
1110  call assert_equal(3, g:filter_au)
1111
1112  if has('filterpipe')
1113    set noshelltemp
1114
1115    let g:filter_au = 0
1116    au FilterWritePre * let g:filter_au += 1
1117    au FilterReadPre * let g:filter_au += 1
1118    au FilterReadPost * let g:filter_au += 1
1119    %!cat
1120    call assert_equal(0, g:filter_au)
1121  endif
1122
1123  au! FilterWritePre,FilterReadPre,FilterReadPost
1124  let &shelltemp = shelltemp
1125  bwipe!
1126endfunc
1127
1128func Test_TextYankPost()
1129  enew!
1130  call setline(1, ['foo'])
1131
1132  let g:event = []
1133  au TextYankPost * let g:event = copy(v:event)
1134
1135  call assert_equal({}, v:event)
1136  call assert_fails('let v:event = {}', 'E46:')
1137  call assert_fails('let v:event.mykey = 0', 'E742:')
1138
1139  norm "ayiw
1140  call assert_equal(
1141    \{'regcontents': ['foo'], 'regname': 'a', 'operator': 'y', 'regtype': 'v'},
1142    \g:event)
1143  norm y_
1144  call assert_equal(
1145    \{'regcontents': ['foo'], 'regname': '',  'operator': 'y', 'regtype': 'V'},
1146    \g:event)
1147  call feedkeys("\<C-V>y", 'x')
1148  call assert_equal(
1149    \{'regcontents': ['f'], 'regname': '',  'operator': 'y', 'regtype': "\x161"},
1150    \g:event)
1151  norm "xciwbar
1152  call assert_equal(
1153    \{'regcontents': ['foo'], 'regname': 'x', 'operator': 'c', 'regtype': 'v'},
1154    \g:event)
1155  norm "bdiw
1156  call assert_equal(
1157    \{'regcontents': ['bar'], 'regname': 'b', 'operator': 'd', 'regtype': 'v'},
1158    \g:event)
1159
1160  call assert_equal({}, v:event)
1161
1162  au! TextYankPost
1163  unlet g:event
1164  bwipe!
1165endfunc
1166