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