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