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