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