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