test_autocmd.vim (153526B)
1 " Tests for autocommands 2 3 source shared.vim 4 source check.vim 5 source term_util.vim 6 source screendump.vim 7 source vim9.vim 8 source load.vim 9 10 func s:cleanup_buffers() abort 11 for bnr in range(1, bufnr('$')) 12 if bufloaded(bnr) && bufnr('%') != bnr 13 execute 'bd! ' . bnr 14 endif 15 endfor 16 endfunc 17 18 func CleanUpTestAuGroup() 19 augroup testing 20 au! 21 augroup END 22 augroup! testing 23 endfunc 24 25 func Test_vim_did_enter() 26 call assert_false(v:vim_did_enter) 27 28 " This script will never reach the main loop, can't check if v:vim_did_enter 29 " becomes one. 30 endfunc 31 32 " Test for the CursorHold autocmd 33 func Test_CursorHold_autocmd() 34 CheckRunVimInTerminal 35 call writefile(['one', 'two', 'three'], 'XoneTwoThree', 'D') 36 let before =<< trim END 37 set updatetime=10 38 au CursorHold * call writefile([line('.')], 'XCHoutput', 'a') 39 END 40 call writefile(before, 'XCHinit', 'D') 41 let buf = RunVimInTerminal('-S XCHinit XoneTwoThree', {}) 42 call term_sendkeys(buf, "G") 43 call term_wait(buf, 50) 44 call term_sendkeys(buf, "gg") 45 call term_wait(buf) 46 call WaitForAssert({-> assert_equal(['1'], readfile('XCHoutput')[-1:-1])}) 47 call term_sendkeys(buf, "j") 48 call term_wait(buf) 49 call WaitForAssert({-> assert_equal(['1', '2'], readfile('XCHoutput')[-2:-1])}) 50 call term_sendkeys(buf, "j") 51 call term_wait(buf) 52 call WaitForAssert({-> assert_equal(['1', '2', '3'], readfile('XCHoutput')[-3:-1])}) 53 call StopVimInTerminal(buf) 54 55 call delete('XCHoutput') 56 endfunc 57 58 if has('timers') 59 60 func ExitInsertMode(id) 61 call feedkeys("\<Esc>") 62 endfunc 63 64 func Test_cursorhold_insert() 65 " depends on timing 66 let g:test_is_flaky = 1 67 68 " Need to move the cursor. 69 call feedkeys("ggG", "xt") 70 71 let g:triggered = 0 72 au CursorHoldI * let g:triggered += 1 73 set updatetime=20 74 call timer_start(LoadAdjust(200), 'ExitInsertMode') 75 call feedkeys('a', 'x!') 76 call assert_equal(1, g:triggered) 77 unlet g:triggered 78 au! CursorHoldI 79 set updatetime& 80 endfunc 81 82 func Test_cursorhold_insert_with_timer_interrupt() 83 CheckFeature job 84 " Need to move the cursor. 85 call feedkeys("ggG", "xt") 86 87 " Confirm the timer invoked in exit_cb of the job doesn't disturb 88 " CursorHoldI event. 89 let g:triggered = 0 90 au CursorHoldI * let g:triggered += 1 91 set updatetime=100 92 call job_start(has('win32') ? 'cmd /D /c echo:' : 'echo', 93 \ {'exit_cb': {-> timer_start(200, 'ExitInsertMode')}}) 94 call feedkeys('a', 'x!') 95 call assert_equal(1, g:triggered) 96 unlet g:triggered 97 au! CursorHoldI 98 set updatetime& 99 endfunc 100 101 func Test_cursorhold_insert_ctrl_x() 102 let g:triggered = 0 103 au CursorHoldI * let g:triggered += 1 104 set updatetime=20 105 call timer_start(LoadAdjust(100), 'ExitInsertMode') 106 " CursorHoldI does not trigger after CTRL-X 107 call feedkeys("a\<C-X>", 'x!') 108 call assert_equal(0, g:triggered) 109 unlet g:triggered 110 au! CursorHoldI 111 set updatetime& 112 endfunc 113 114 func Test_cursorhold_insert_ctrl_g_U() 115 au CursorHoldI * : 116 set updatetime=20 117 new 118 call timer_start(100, { -> feedkeys("\<Left>foo\<Esc>", 't') }) 119 call feedkeys("i()\<C-g>U", 'tx!') 120 sleep 200m 121 call assert_equal('(foo)', getline(1)) 122 undo 123 call assert_equal('', getline(1)) 124 125 bwipe! 126 au! CursorHoldI 127 set updatetime& 128 endfunc 129 130 func Test_OptionSet_modeline() 131 call Ntest_override('starting', 1) 132 au! OptionSet 133 augroup set_tabstop 134 au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler called'", "")}) 135 augroup END 136 call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline', 'D') 137 set modeline 138 let v:errmsg = '' 139 call assert_fails('split XoptionsetModeline', 'E12:') 140 call assert_equal(7, &ts) 141 call assert_equal('', v:errmsg) 142 143 augroup set_tabstop 144 au! 145 augroup END 146 bwipe! 147 set ts& 148 call Ntest_override('starting', 0) 149 endfunc 150 151 endif "has('timers') 152 153 func Test_bufunload() 154 augroup test_bufunload_group 155 autocmd! 156 autocmd BufUnload * call add(s:li, "bufunload") 157 autocmd BufDelete * call add(s:li, "bufdelete") 158 autocmd BufWipeout * call add(s:li, "bufwipeout") 159 augroup END 160 161 let s:li = [] 162 new 163 setlocal bufhidden= 164 bunload 165 call assert_equal(["bufunload", "bufdelete"], s:li) 166 167 let s:li = [] 168 new 169 setlocal bufhidden=delete 170 bunload 171 call assert_equal(["bufunload", "bufdelete"], s:li) 172 173 let s:li = [] 174 new 175 setlocal bufhidden=unload 176 bwipeout 177 call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li) 178 179 au! test_bufunload_group 180 augroup! test_bufunload_group 181 endfunc 182 183 " SEGV occurs in older versions. (At least 7.4.2005 or older) 184 func Test_autocmd_bufunload_with_tabnext() 185 tabedit 186 tabfirst 187 188 augroup test_autocmd_bufunload_with_tabnext_group 189 autocmd! 190 autocmd BufUnload <buffer> tabnext 191 augroup END 192 193 quit 194 call assert_equal(2, tabpagenr('$')) 195 196 autocmd! test_autocmd_bufunload_with_tabnext_group 197 augroup! test_autocmd_bufunload_with_tabnext_group 198 tablast 199 quit 200 endfunc 201 202 func Test_argdelete_in_next() 203 au BufNew,BufEnter,BufLeave,BufWinEnter * argdel 204 call assert_fails('next a b', 'E1156:') 205 au! BufNew,BufEnter,BufLeave,BufWinEnter * 206 endfunc 207 208 func Test_autocmd_bufwinleave_with_tabfirst() 209 tabedit 210 augroup sample 211 autocmd! 212 autocmd BufWinLeave <buffer> tabfirst 213 augroup END 214 call setline(1, ['a', 'b', 'c']) 215 edit! a.txt 216 tabclose 217 endfunc 218 219 " SEGV occurs in older versions. (At least 7.4.2321 or older) 220 func Test_autocmd_bufunload_avoiding_SEGV_01() 221 split aa.txt 222 let lastbuf = bufnr('$') 223 224 augroup test_autocmd_bufunload 225 autocmd! 226 exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!' 227 augroup END 228 229 call assert_fails('edit bb.txt', 'E937:') 230 231 autocmd! test_autocmd_bufunload 232 augroup! test_autocmd_bufunload 233 bwipe! aa.txt 234 bwipe! bb.txt 235 endfunc 236 237 " SEGV occurs in older versions. (At least 7.4.2321 or older) 238 func Test_autocmd_bufunload_avoiding_SEGV_02() 239 setlocal buftype=nowrite 240 let lastbuf = bufnr('$') 241 242 augroup test_autocmd_bufunload 243 autocmd! 244 exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!' 245 augroup END 246 247 normal! i1 248 call assert_fails('edit a.txt', 'E517:') 249 250 autocmd! test_autocmd_bufunload 251 augroup! test_autocmd_bufunload 252 bwipe! a.txt 253 endfunc 254 255 func Test_autocmd_dummy_wipeout() 256 " prepare files 257 call writefile([''], 'Xdummywipetest1.txt', 'D') 258 call writefile([''], 'Xdummywipetest2.txt', 'D') 259 augroup test_bufunload_group 260 autocmd! 261 autocmd BufUnload * call add(s:li, "bufunload") 262 autocmd BufDelete * call add(s:li, "bufdelete") 263 autocmd BufWipeout * call add(s:li, "bufwipeout") 264 augroup END 265 266 let s:li = [] 267 split Xdummywipetest1.txt 268 silent! vimgrep /notmatched/ Xdummywipetest* 269 call assert_equal(["bufunload", "bufwipeout"], s:li) 270 271 bwipeout 272 au! test_bufunload_group 273 augroup! test_bufunload_group 274 endfunc 275 276 func Test_win_tab_autocmd() 277 let g:record = [] 278 279 defer CleanUpTestAuGroup() 280 augroup testing 281 au WinNewPre * call add(g:record, 'WinNewPre') 282 au WinNew * call add(g:record, 'WinNew') 283 au WinClosed * call add(g:record, 'WinClosed') 284 au WinEnter * call add(g:record, 'WinEnter') 285 au WinLeave * call add(g:record, 'WinLeave') 286 au TabNew * call add(g:record, 'TabNew') 287 au TabClosed * call add(g:record, 'TabClosed') 288 au TabEnter * call add(g:record, 'TabEnter') 289 au TabLeave * call add(g:record, 'TabLeave') 290 augroup END 291 292 split 293 tabnew 294 close 295 close 296 297 call assert_equal([ 298 \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter', 299 \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', 300 \ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter', 301 \ 'WinLeave', 'WinClosed', 'WinEnter' 302 \ ], g:record) 303 304 let g:record = [] 305 tabnew somefile 306 tabnext 307 bwipe somefile 308 309 call assert_equal([ 310 \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', 311 \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', 312 \ 'WinClosed', 'TabClosed' 313 \ ], g:record) 314 315 let g:record = [] 316 copen 317 help 318 tabnext 319 vnew 320 321 call assert_equal([ 322 \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter', 323 \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter', 324 \ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter' 325 \ ], g:record) 326 327 unlet g:record 328 endfunc 329 330 func Test_WinNewPre() 331 " Test that the old window layout can be accessed before a new window is created. 332 let g:layouts_pre = [] 333 let g:layouts_post = [] 334 augroup testing 335 au WinNewPre * call add(g:layouts_pre, winlayout()) 336 au WinNew * call add(g:layouts_post, winlayout()) 337 augroup END 338 defer CleanUpTestAuGroup() 339 split 340 call assert_notequal(g:layouts_pre[0], g:layouts_post[0]) 341 split 342 call assert_equal(g:layouts_pre[1], g:layouts_post[0]) 343 call assert_notequal(g:layouts_pre[1], g:layouts_post[1]) 344 " not triggered for tabnew 345 tabnew 346 call assert_equal(2, len(g:layouts_pre)) 347 unlet g:layouts_pre 348 unlet g:layouts_post 349 350 " Test modifying window layout during WinNewPre throws. 351 let g:caught = 0 352 augroup testing 353 au! 354 au WinNewPre * split 355 augroup END 356 try 357 vnew 358 catch 359 let g:caught += 1 360 endtry 361 augroup testing 362 au! 363 au WinNewPre * tabnew 364 augroup END 365 try 366 vnew 367 catch 368 let g:caught += 1 369 endtry 370 augroup testing 371 au! 372 au WinNewPre * close 373 augroup END 374 try 375 vnew 376 catch 377 let g:caught += 1 378 endtry 379 augroup testing 380 au! 381 au WinNewPre * tabclose 382 augroup END 383 try 384 vnew 385 catch 386 let g:caught += 1 387 endtry 388 call assert_equal(4, g:caught) 389 unlet g:caught 390 endfunc 391 392 func Test_WinResized() 393 CheckRunVimInTerminal 394 395 let lines =<< trim END 396 set scrolloff=0 397 call setline(1, ['111', '222']) 398 vnew 399 call setline(1, ['aaa', 'bbb']) 400 new 401 call setline(1, ['foo', 'bar']) 402 403 let g:resized = 0 404 au WinResized * let g:resized += 1 405 406 func WriteResizedEvent() 407 call writefile([json_encode(v:event)], 'XresizeEvent') 408 endfunc 409 au WinResized * call WriteResizedEvent() 410 END 411 call writefile(lines, 'Xtest_winresized', 'D') 412 let buf = RunVimInTerminal('-S Xtest_winresized', {'rows': 10}) 413 414 " redraw now to avoid a redraw after the :echo command 415 call term_sendkeys(buf, ":redraw!\<CR>") 416 call TermWait(buf) 417 418 call term_sendkeys(buf, ":echo g:resized\<CR>") 419 call WaitForAssert({-> assert_match('^0$', term_getline(buf, 10))}, 1000) 420 421 " increase window height, two windows will be reported 422 call term_sendkeys(buf, "\<C-W>+") 423 call TermWait(buf) 424 call term_sendkeys(buf, ":echo g:resized\<CR>") 425 call WaitForAssert({-> assert_match('^1$', term_getline(buf, 10))}, 1000) 426 427 let event = readfile('XresizeEvent')[0]->json_decode() 428 call assert_equal({ 429 \ 'windows': [1002, 1001], 430 \ }, event) 431 432 " increase window width, three windows will be reported 433 call term_sendkeys(buf, "\<C-W>>") 434 call TermWait(buf) 435 call term_sendkeys(buf, ":echo g:resized\<CR>") 436 call WaitForAssert({-> assert_match('^2$', term_getline(buf, 10))}, 1000) 437 438 let event = readfile('XresizeEvent')[0]->json_decode() 439 call assert_equal({ 440 \ 'windows': [1002, 1001, 1000], 441 \ }, event) 442 443 call delete('XresizeEvent') 444 call StopVimInTerminal(buf) 445 endfunc 446 447 func Test_WinScrolled() 448 CheckRunVimInTerminal 449 450 let lines =<< trim END 451 set nowrap scrolloff=0 452 for ii in range(1, 18) 453 call setline(ii, repeat(nr2char(96 + ii), ii * 2)) 454 endfor 455 let win_id = win_getid() 456 let g:matched = v:false 457 func WriteScrollEvent() 458 call writefile([json_encode(v:event)], 'XscrollEvent') 459 endfunc 460 execute 'au WinScrolled' win_id 'let g:matched = v:true' 461 let g:scrolled = 0 462 au WinScrolled * let g:scrolled += 1 463 au WinScrolled * let g:amatch = str2nr(expand('<amatch>')) 464 au WinScrolled * let g:afile = str2nr(expand('<afile>')) 465 au WinScrolled * call WriteScrollEvent() 466 END 467 call writefile(lines, 'Xtest_winscrolled', 'D') 468 let buf = RunVimInTerminal('-S Xtest_winscrolled', {'rows': 6}) 469 470 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 471 call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000) 472 473 " Scroll left/right in Normal mode. 474 call term_sendkeys(buf, "zlzh:echo g:scrolled\<CR>") 475 call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000) 476 477 let event = readfile('XscrollEvent')[0]->json_decode() 478 call assert_equal({ 479 \ 'all': {'leftcol': 1, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 480 \ '1000': {'leftcol': -1, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} 481 \ }, event) 482 483 " Scroll up/down in Normal mode. 484 call term_sendkeys(buf, "\<c-e>\<c-y>:echo g:scrolled\<CR>") 485 call WaitForAssert({-> assert_match('^4 ', term_getline(buf, 6))}, 1000) 486 487 let event = readfile('XscrollEvent')[0]->json_decode() 488 call assert_equal({ 489 \ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 490 \ '1000': {'leftcol': 0, 'topline': -1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} 491 \ }, event) 492 493 " Scroll up/down in Insert mode. 494 call term_sendkeys(buf, "Mi\<c-x>\<c-e>\<Esc>i\<c-x>\<c-y>\<Esc>") 495 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 496 call WaitForAssert({-> assert_match('^6 ', term_getline(buf, 6))}, 1000) 497 498 let event = readfile('XscrollEvent')[0]->json_decode() 499 call assert_equal({ 500 \ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 501 \ '1000': {'leftcol': 0, 'topline': -1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} 502 \ }, event) 503 504 " Scroll the window horizontally to focus the last letter of the third line 505 " containing only six characters. Moving to the previous and shorter lines 506 " should trigger another autocommand as Vim has to make them visible. 507 call term_sendkeys(buf, "5zl2k") 508 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 509 call WaitForAssert({-> assert_match('^8 ', term_getline(buf, 6))}, 1000) 510 511 let event = readfile('XscrollEvent')[0]->json_decode() 512 call assert_equal({ 513 \ 'all': {'leftcol': 5, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 514 \ '1000': {'leftcol': -5, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} 515 \ }, event) 516 517 " Ensure the command was triggered for the specified window ID. 518 call term_sendkeys(buf, ":echo g:matched\<CR>") 519 call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000) 520 521 " Ensure the expansion of <amatch> and <afile> matches the window ID. 522 call term_sendkeys(buf, ":echo g:amatch == win_id && g:afile == win_id\<CR>") 523 call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000) 524 525 call delete('XscrollEvent') 526 call StopVimInTerminal(buf) 527 endfunc 528 529 func Test_WinScrolled_mouse() 530 CheckRunVimInTerminal 531 532 let lines =<< trim END 533 set nowrap scrolloff=0 534 set mouse=a term=xterm ttymouse=sgr mousetime=200 clipboard= 535 call setline(1, ['foo']->repeat(32)) 536 split 537 let g:scrolled = 0 538 au WinScrolled * let g:scrolled += 1 539 END 540 call writefile(lines, 'Xtest_winscrolled_mouse', 'D') 541 let buf = RunVimInTerminal('-S Xtest_winscrolled_mouse', {'rows': 10}) 542 543 " With the upper split focused, send a scroll-down event to the unfocused one. 544 call test_setmouse(7, 1) 545 call term_sendkeys(buf, "\<ScrollWheelDown>") 546 call TermWait(buf) 547 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 548 call WaitForAssert({-> assert_match('^1', term_getline(buf, 10))}, 1000) 549 550 " Again, but this time while we're in insert mode. 551 call term_sendkeys(buf, "i\<ScrollWheelDown>\<Esc>") 552 call TermWait(buf) 553 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 554 call WaitForAssert({-> assert_match('^2', term_getline(buf, 10))}, 1000) 555 556 call StopVimInTerminal(buf) 557 endfunc 558 559 func Test_WinScrolled_close_curwin() 560 CheckRunVimInTerminal 561 562 let lines =<< trim END 563 set nowrap scrolloff=0 564 call setline(1, ['aaa', 'bbb']) 565 vsplit 566 au WinScrolled * close 567 au VimLeave * call writefile(['123456'], 'Xtestout') 568 END 569 call writefile(lines, 'Xtest_winscrolled_close_curwin', 'D') 570 let buf = RunVimInTerminal('-S Xtest_winscrolled_close_curwin', {'rows': 6}) 571 572 " This was using freed memory 573 call term_sendkeys(buf, "\<C-E>") 574 call TermWait(buf) 575 call StopVimInTerminal(buf) 576 577 " check the startup script finished to the end 578 call assert_equal(['123456'], readfile('Xtestout')) 579 call delete('Xtestout') 580 endfunc 581 582 func Test_WinScrolled_once_only() 583 CheckScreendump 584 CheckRunVimInTerminal 585 586 let lines =<< trim END 587 set cmdheight=2 588 call setline(1, ['aaa', 'bbb']) 589 let trigger_count = 0 590 func ShowInfo(id) 591 echo g:trigger_count g:winid winlayout() 592 endfunc 593 594 vsplit 595 split 596 " use a timer to show the info after a redraw 597 au WinScrolled * let trigger_count += 1 | let winid = expand('<amatch>') | call timer_start(100, 'ShowInfo') 598 wincmd j 599 wincmd l 600 END 601 call writefile(lines, 'Xtest_winscrolled_once', 'D') 602 let buf = RunVimInTerminal('-S Xtest_winscrolled_once', #{rows: 10, cols: 60, statusoff: 2}) 603 604 call term_sendkeys(buf, "\<C-E>") 605 call VerifyScreenDump(buf, 'Test_winscrolled_once_only_1', {}) 606 607 call StopVimInTerminal(buf) 608 endfunc 609 610 " Check that WinScrolled is not triggered immediately when defined and there 611 " are split windows. 612 func Test_WinScrolled_not_when_defined() 613 CheckScreendump 614 CheckRunVimInTerminal 615 616 let lines =<< trim END 617 call setline(1, ['aaa', 'bbb']) 618 echo 'nothing happened' 619 func ShowTriggered(id) 620 echo 'triggered' 621 endfunc 622 END 623 call writefile(lines, 'Xtest_winscrolled_not', 'D') 624 let buf = RunVimInTerminal('-S Xtest_winscrolled_not', #{rows: 10, cols: 60, statusoff: 2}) 625 call term_sendkeys(buf, ":split\<CR>") 626 call TermWait(buf) 627 " use a timer to show the message after redrawing 628 call term_sendkeys(buf, ":au WinScrolled * call timer_start(100, 'ShowTriggered')\<CR>") 629 call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_1', {}) 630 631 call term_sendkeys(buf, "\<C-E>") 632 call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_2', {}) 633 634 call StopVimInTerminal(buf) 635 endfunc 636 637 func Test_WinScrolled_long_wrapped() 638 CheckRunVimInTerminal 639 640 let lines =<< trim END 641 set scrolloff=0 642 let height = winheight(0) 643 let width = winwidth(0) 644 let g:scrolled = 0 645 au WinScrolled * let g:scrolled += 1 646 call setline(1, repeat('foo', height * width)) 647 call cursor(1, height * width) 648 END 649 call writefile(lines, 'Xtest_winscrolled_long_wrapped', 'D') 650 let buf = RunVimInTerminal('-S Xtest_winscrolled_long_wrapped', {'rows': 6}) 651 652 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 653 call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000) 654 655 call term_sendkeys(buf, 'gj') 656 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 657 call WaitForAssert({-> assert_match('^1 ', term_getline(buf, 6))}, 1000) 658 659 call term_sendkeys(buf, '0') 660 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 661 call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000) 662 663 call term_sendkeys(buf, '$') 664 call term_sendkeys(buf, ":echo g:scrolled\<CR>") 665 call WaitForAssert({-> assert_match('^3 ', term_getline(buf, 6))}, 1000) 666 667 call StopVimInTerminal(buf) 668 endfunc 669 670 func Test_WinScrolled_diff() 671 CheckRunVimInTerminal 672 673 let lines =<< trim END 674 set diffopt+=foldcolumn:0 675 call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']) 676 vnew 677 call setline(1, ['d', 'e', 'f', 'g', 'h', 'i']) 678 windo diffthis 679 func WriteScrollEvent() 680 call writefile([json_encode(v:event)], 'XscrollEvent') 681 endfunc 682 au WinScrolled * call WriteScrollEvent() 683 END 684 call writefile(lines, 'Xtest_winscrolled_diff', 'D') 685 let buf = RunVimInTerminal('-S Xtest_winscrolled_diff', {'rows': 8}) 686 687 call term_sendkeys(buf, "\<C-E>") 688 call WaitForAssert({-> assert_match('^d', term_getline(buf, 3))}, 1000) 689 690 let event = readfile('XscrollEvent')[0]->json_decode() 691 call assert_equal({ 692 \ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0}, 693 \ '1000': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 694 \ '1001': {'leftcol': 0, 'topline': 0, 'topfill': -1, 'width': 0, 'height': 0, 'skipcol': 0} 695 \ }, event) 696 697 call term_sendkeys(buf, "2\<C-E>") 698 call WaitForAssert({-> assert_match('^f', term_getline(buf, 3))}, 1000) 699 700 let event = readfile('XscrollEvent')[0]->json_decode() 701 call assert_equal({ 702 \ 'all': {'leftcol': 0, 'topline': 2, 'topfill': 2, 'width': 0, 'height': 0, 'skipcol': 0}, 703 \ '1000': {'leftcol': 0, 'topline': 2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 704 \ '1001': {'leftcol': 0, 'topline': 0, 'topfill': -2, 'width': 0, 'height': 0, 'skipcol': 0} 705 \ }, event) 706 707 call term_sendkeys(buf, "\<C-E>") 708 call WaitForAssert({-> assert_match('^g', term_getline(buf, 3))}, 1000) 709 710 let event = readfile('XscrollEvent')[0]->json_decode() 711 call assert_equal({ 712 \ 'all': {'leftcol': 0, 'topline': 2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 713 \ '1000': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 714 \ '1001': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} 715 \ }, event) 716 717 call term_sendkeys(buf, "2\<C-Y>") 718 call WaitForAssert({-> assert_match('^e', term_getline(buf, 3))}, 1000) 719 720 let event = readfile('XscrollEvent')[0]->json_decode() 721 call assert_equal({ 722 \ 'all': {'leftcol': 0, 'topline': 3, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0}, 723 \ '1000': {'leftcol': 0, 'topline': -2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, 724 \ '1001': {'leftcol': 0, 'topline': -1, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0} 725 \ }, event) 726 727 call StopVimInTerminal(buf) 728 call delete('XscrollEvent') 729 endfunc 730 731 func Test_WinClosed() 732 " Test that the pattern is matched against the closed window's ID, and both 733 " <amatch> and <afile> are set to it. 734 new 735 let winid = win_getid() 736 let g:matched = v:false 737 augroup test-WinClosed 738 autocmd! 739 execute 'autocmd WinClosed' winid 'let g:matched = v:true' 740 autocmd WinClosed * let g:amatch = str2nr(expand('<amatch>')) 741 autocmd WinClosed * let g:afile = str2nr(expand('<afile>')) 742 augroup END 743 close 744 call assert_true(g:matched) 745 call assert_equal(winid, g:amatch) 746 call assert_equal(winid, g:afile) 747 748 " Test that WinClosed is non-recursive. 749 new 750 new 751 call assert_equal(3, winnr('$')) 752 let g:triggered = 0 753 augroup test-WinClosed 754 autocmd! 755 autocmd WinClosed * let g:triggered += 1 756 autocmd WinClosed * 2 wincmd c 757 augroup END 758 close 759 call assert_equal(1, winnr('$')) 760 call assert_equal(1, g:triggered) 761 762 autocmd! test-WinClosed 763 augroup! test-WinClosed 764 unlet g:matched 765 unlet g:amatch 766 unlet g:afile 767 unlet g:triggered 768 endfunc 769 770 func Test_WinClosed_throws() 771 vnew 772 let bnr = bufnr() 773 call assert_equal(1, bufloaded(bnr)) 774 augroup test-WinClosed 775 autocmd WinClosed * throw 'foo' 776 augroup END 777 try 778 close 779 catch /.*/ 780 endtry 781 call assert_equal(0, bufloaded(bnr)) 782 783 autocmd! test-WinClosed 784 augroup! test-WinClosed 785 endfunc 786 787 func Test_WinClosed_throws_with_tabs() 788 tabnew 789 let bnr = bufnr() 790 call assert_equal(1, bufloaded(bnr)) 791 augroup test-WinClosed 792 autocmd WinClosed * throw 'foo' 793 augroup END 794 try 795 close 796 catch /.*/ 797 endtry 798 call assert_equal(0, bufloaded(bnr)) 799 800 autocmd! test-WinClosed 801 augroup! test-WinClosed 802 endfunc 803 804 " This used to trigger WinClosed twice for the same window, and the window's 805 " buffer was NULL in the second autocommand. 806 func Test_WinClosed_switch_tab() 807 edit Xa 808 split Xb 809 split Xc 810 tab split 811 new 812 augroup test-WinClosed 813 autocmd WinClosed * tabprev | bwipe! 814 augroup END 815 close 816 " Check that the tabline has been fully removed 817 call assert_equal([1, 1], win_screenpos(0)) 818 819 autocmd! test-WinClosed 820 augroup! test-WinClosed 821 %bwipe! 822 endfunc 823 824 " This used to trigger WinClosed/WinLeave/BufLeave twice for the same window, 825 " and the window's buffer was NULL in the second autocommand. 826 func Run_test_BufUnload_close_other(extra_cmd) 827 let oldtab = tabpagenr() 828 tabnew Xb1 829 let g:tab = tabpagenr() 830 let g:w1 = win_getid() 831 new Xb2 832 let g:w2 = win_getid() 833 let g:log = [] 834 exe a:extra_cmd 835 836 augroup test-BufUnload-close-other 837 autocmd BufUnload * ++nested ++once bwipe! Xb1 838 for event in ['WinClosed', 'BufLeave', 'WinLeave', 'TabLeave'] 839 exe $'autocmd {event} * call tabpagebuflist(g:tab)' 840 exe $'autocmd {event} * let g:log += ["{event}:" .. expand("<afile>")]' 841 endfor 842 augroup END 843 844 close 845 " WinClosed is triggered once for each of the 2 closed windows. 846 " Others are only triggered once. 847 call assert_equal(['BufLeave:Xb2', 'WinLeave:Xb2', $'WinClosed:{g:w2}', 848 \ $'WinClosed:{g:w1}', 'TabLeave:Xb2'], g:log) 849 call assert_equal(oldtab, tabpagenr()) 850 call assert_equal([0, 0], win_id2tabwin(g:w1)) 851 call assert_equal([0, 0], win_id2tabwin(g:w2)) 852 853 unlet g:tab 854 unlet g:w1 855 unlet g:w2 856 unlet g:log 857 autocmd! test-BufUnload-close-other 858 augroup! test-BufUnload-close-other 859 %bwipe! 860 endfunc 861 862 func Test_BufUnload_close_other() 863 call Run_test_BufUnload_close_other('') 864 call Run_test_BufUnload_close_other('setlocal bufhidden=wipe') 865 endfunc 866 867 func Run_test_BufUnload_tabonly(first_cmd) 868 exe a:first_cmd 869 tabnew Xa 870 setlocal bufhidden=wipe 871 tabprevious 872 autocmd BufWinLeave Xa ++once tabnext 873 autocmd BufUnload Xa ++once tabonly 874 tabonly 875 876 %bwipe! 877 endfunc 878 879 func Test_BufUnload_tabonly() 880 " This used to dereference a NULL curbuf. 881 call Run_test_BufUnload_tabonly('setlocal bufhidden=hide') 882 " This used to dereference a NULL firstbuf. 883 call Run_test_BufUnload_tabonly('setlocal bufhidden=wipe') 884 endfunc 885 886 func Run_test_BufUnload_tabonly_nested(second_autocmd) 887 file Xa 888 tabnew Xb 889 setlocal bufhidden=wipe 890 tabnew Xc 891 setlocal bufhidden=wipe 892 autocmd BufUnload Xb ++once ++nested bwipe! Xa 893 exe $'autocmd BufUnload Xa ++once ++nested {a:second_autocmd}' 894 autocmd BufWinLeave Xc ++once tabnext 895 tabfirst 896 2tabclose 897 898 %bwipe! 899 endfunc 900 901 func Test_BufUnload_tabonly_nested() 902 " These used to cause heap-use-after-free. 903 call Run_test_BufUnload_tabonly_nested('tabonly') 904 call Run_test_BufUnload_tabonly_nested('tabonly | tabprevious') 905 endfunc 906 907 func s:AddAnAutocmd() 908 augroup vimBarTest 909 au BufReadCmd * echo 'hello' 910 augroup END 911 call assert_equal(3, len(split(execute('au vimBarTest'), "\n"))) 912 endfunc 913 914 func Test_early_bar() 915 " test that a bar is recognized before the {event} 916 call s:AddAnAutocmd() 917 augroup vimBarTest | au! | let done = 77 | augroup END 918 call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) 919 call assert_equal(77, done) 920 921 call s:AddAnAutocmd() 922 augroup vimBarTest| au!| let done = 88 | augroup END 923 call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) 924 call assert_equal(88, done) 925 926 " test that a bar is recognized after the {event} 927 call s:AddAnAutocmd() 928 augroup vimBarTest| au!BufReadCmd| let done = 99 | augroup END 929 call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) 930 call assert_equal(99, done) 931 932 " test that a bar is recognized after the {group} 933 call s:AddAnAutocmd() 934 au! vimBarTest|echo 'hello' 935 call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) 936 endfunc 937 938 func RemoveGroup() 939 autocmd! StartOK 940 augroup! StartOK 941 endfunc 942 943 func Test_augroup_warning() 944 augroup TheWarning 945 au VimEnter * echo 'entering' 946 augroup END 947 call assert_match("TheWarning.*VimEnter", execute('au VimEnter')) 948 redir => res 949 augroup! TheWarning 950 redir END 951 call assert_match("W19:", res) 952 call assert_match("-Deleted-.*VimEnter", execute('au VimEnter')) 953 954 " check "Another" does not take the pace of the deleted entry 955 augroup Another 956 augroup END 957 call assert_match("-Deleted-.*VimEnter", execute('au VimEnter')) 958 augroup! Another 959 960 " no warning for postpone aucmd delete 961 augroup StartOK 962 au VimEnter * call RemoveGroup() 963 augroup END 964 call assert_match("StartOK.*VimEnter", execute('au VimEnter')) 965 redir => res 966 doautocmd VimEnter 967 redir END 968 call assert_notmatch("W19:", res) 969 au! VimEnter 970 971 call assert_fails('augroup!', 'E471:') 972 endfunc 973 974 func Test_BufReadCmdHelp() 975 " This used to cause access to free memory 976 au BufReadCmd * e +h 977 help 978 979 au! BufReadCmd 980 endfunc 981 982 func Test_BufReadCmdHelpJump() 983 " This used to cause access to free memory 984 au BufReadCmd * e +h{ 985 " } to fix highlighting 986 call assert_fails('help', 'E434:') 987 988 au! BufReadCmd 989 endfunc 990 991 " BufReadCmd is triggered for a "nofile" buffer. Check all values. 992 func Test_BufReadCmdNofile() 993 for val in ['nofile', 994 \ 'nowrite', 995 \ 'acwrite', 996 \ 'quickfix', 997 \ 'help', 998 "\ 'terminal', 999 "\ 'prompt', 1000 "\ 'popup', 1001 \ ] 1002 new somefile 1003 exe 'set buftype=' .. val 1004 au BufReadCmd somefile call setline(1, 'triggered') 1005 edit 1006 call assert_equal('triggered', getline(1)) 1007 1008 au! BufReadCmd 1009 bwipe! 1010 endfor 1011 endfunc 1012 1013 func Test_augroup_deleted() 1014 " This caused a crash before E936 was introduced 1015 augroup x 1016 call assert_fails('augroup! x', 'E936:') 1017 au VimEnter * echo 1018 augroup end 1019 augroup! x 1020 call assert_match("-Deleted-.*VimEnter", execute('au VimEnter')) 1021 au! VimEnter 1022 endfunc 1023 1024 " Tests for autocommands on :close command. 1025 " This used to be in test13. 1026 func Test_three_windows() 1027 " Clean up buffers, because in some cases this function fails. 1028 call s:cleanup_buffers() 1029 1030 " Write three files and open them, each in a window. 1031 " Then go to next window, with autocommand that deletes the previous one. 1032 " Do this twice, writing the file. 1033 e! Xtestje1 1034 call setline(1, 'testje1') 1035 w 1036 sp Xtestje2 1037 call setline(1, 'testje2') 1038 w 1039 sp Xtestje3 1040 call setline(1, 'testje3') 1041 w 1042 wincmd w 1043 au WinLeave Xtestje2 bwipe 1044 wincmd w 1045 call assert_equal('Xtestje1', expand('%')) 1046 1047 au WinLeave Xtestje1 bwipe Xtestje3 1048 close 1049 call assert_equal('Xtestje1', expand('%')) 1050 1051 " Test deleting the buffer on a Unload event. If this goes wrong there 1052 " will be the ATTENTION prompt. 1053 e Xtestje1 1054 au! 1055 au! BufUnload Xtestje1 bwipe 1056 call assert_fails('e Xtestje3', 'E937:') 1057 call assert_equal('Xtestje3', expand('%')) 1058 1059 e Xtestje2 1060 sp Xtestje1 1061 call assert_fails('e', 'E937:') 1062 call assert_equal('Xtestje1', expand('%')) 1063 1064 " Test changing buffers in a BufWipeout autocommand. If this goes wrong 1065 " there are ml_line errors and/or a Crash. 1066 au! 1067 only 1068 e Xanother 1069 e Xtestje1 1070 bwipe Xtestje2 1071 bwipe Xtestje3 1072 au BufWipeout Xtestje1 buf Xtestje1 1073 bwipe 1074 call assert_equal('Xanother', expand('%')) 1075 1076 only 1077 1078 help 1079 wincmd w 1080 1quit 1081 call assert_equal('Xanother', expand('%')) 1082 1083 au! 1084 enew 1085 call delete('Xtestje1') 1086 call delete('Xtestje2') 1087 call delete('Xtestje3') 1088 endfunc 1089 1090 func Test_BufEnter() 1091 au! BufEnter 1092 au Bufenter * let val = val . '+' 1093 let g:val = '' 1094 split NewFile 1095 call assert_equal('+', g:val) 1096 bwipe! 1097 call assert_equal('++', g:val) 1098 1099 " Also get BufEnter when editing a directory 1100 call mkdir('Xbufenterdir', 'D') 1101 split Xbufenterdir 1102 call assert_equal('+++', g:val) 1103 1104 " On MS-Windows we can't edit the directory, make sure we wipe the right 1105 " buffer. 1106 bwipe! Xbufenterdir 1107 au! BufEnter 1108 1109 " Editing a "nofile" buffer doesn't read the file but does trigger BufEnter 1110 " for historic reasons. Also test other 'buftype' values. 1111 for val in ['nofile', 1112 \ 'nowrite', 1113 \ 'acwrite', 1114 \ 'quickfix', 1115 \ 'help', 1116 "\ 'terminal', 1117 "\ 'prompt', 1118 "\ 'popup', 1119 \ ] 1120 new somefile 1121 exe 'set buftype=' .. val 1122 au BufEnter somefile call setline(1, 'some text') 1123 edit 1124 call assert_equal('some text', getline(1)) 1125 bwipe! 1126 au! BufEnter 1127 endfor 1128 1129 new 1130 new 1131 autocmd BufEnter * ++once close 1132 call assert_fails('close', 'E1312:') 1133 1134 au! BufEnter 1135 only 1136 endfunc 1137 1138 func Test_autocmd_SessLoadPre() 1139 tabnew 1140 set noswapfile 1141 mksession! Session.vim 1142 1143 call assert_false(exists('g:session_loaded_var')) 1144 1145 let content =<< trim [CODE] 1146 set nocp noswapfile 1147 1148 func! Assert(cond, msg) 1149 if !a:cond 1150 echomsg "ASSERT_FAIL: " .. a:msg 1151 else 1152 echomsg "ASSERT_OK: " .. a:msg 1153 endif 1154 endfunc 1155 1156 func! OnSessionLoadPre() 1157 call Assert(!exists('g:session_loaded_var'), 1158 \ 'SessionLoadPre: var NOT set') 1159 endfunc 1160 au SessionLoadPre * call OnSessionLoadPre() 1161 1162 func! OnSessionLoadPost() 1163 call Assert(exists('g:session_loaded_var'), 1164 \ 'SessionLoadPost: var IS set') 1165 echomsg "SessionLoadPost DONE" 1166 endfunc 1167 au SessionLoadPost * call OnSessionLoadPost() 1168 1169 func! WriteErrors() 1170 call writefile([execute("messages")], "XerrorsPost") 1171 endfunc 1172 au VimLeave * call WriteErrors() 1173 [CODE] 1174 1175 call writefile(content, 'Xvimrc', 'D') 1176 1177 call writefile( 1178 \ ['let g:session_loaded_var = 1'], 1179 \ 'Sessionx.vim', 1180 \ 'b' 1181 \ ) 1182 1183 " --- Run child Vim --- 1184 call system( 1185 \ GetVimCommand('Xvimrc') 1186 \ .. ' --headless --noplugins -S Session.vim -c cq' 1187 \ ) 1188 1189 call WaitForAssert({-> assert_true(filereadable('XerrorsPost'))}) 1190 1191 let errors = join(readfile('XerrorsPost'), "\n") 1192 call assert_notmatch('ASSERT_FAIL', errors) 1193 call assert_match('ASSERT_OK: SessionLoadPre: var NOT set', errors) 1194 call assert_match('ASSERT_OK: SessionLoadPost: var IS set', errors) 1195 call assert_match('SessionLoadPost DONE', errors) 1196 1197 set swapfile 1198 for file in ['Session.vim', 'Sessionx.vim', 'XerrorsPost'] 1199 call delete(file) 1200 endfor 1201 endfunc 1202 1203 " Closing a window might cause an endless loop 1204 " E814 for older Vims 1205 func Test_autocmd_bufwipe_in_SessLoadPost() 1206 edit Xtest 1207 tabnew 1208 file Xsomething 1209 set noswapfile 1210 mksession! 1211 1212 let content =<< trim [CODE] 1213 set nocp noswapfile 1214 let v:swapchoice = "e" 1215 augroup test_autocmd_sessionload 1216 autocmd! 1217 autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!" 1218 augroup END 1219 1220 func WriteErrors() 1221 call writefile([execute("messages")], "XerrorsBwipe") 1222 endfunc 1223 au VimLeave * call WriteErrors() 1224 [CODE] 1225 1226 call writefile(content, 'Xvimrc', 'D') 1227 call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq') 1228 sleep 100m 1229 let errors = join(readfile('XerrorsBwipe')) 1230 call assert_match('E814:', errors) 1231 1232 set swapfile 1233 for file in ['Session.vim', 'XerrorsBwipe'] 1234 call delete(file) 1235 endfor 1236 endfunc 1237 1238 " Using :blast and :ball for many events caused a crash, because b_nwindows was 1239 " not incremented correctly. 1240 func Test_autocmd_blast_badd() 1241 let content =<< trim [CODE] 1242 au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* blast 1243 edit foo1 1244 au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* ball 1245 edit foo2 1246 call writefile(['OK'], 'XerrorsBlast') 1247 qall 1248 [CODE] 1249 1250 call writefile(content, 'XblastBall', 'D') 1251 call system(GetVimCommand() .. ' --clean -S XblastBall') 1252 sleep 100m 1253 call assert_match('OK', readfile('XerrorsBlast')->join()) 1254 1255 call delete('XerrorsBlast') 1256 endfunc 1257 1258 " SEGV occurs in older versions. 1259 func Test_autocmd_bufwipe_in_SessLoadPost2() 1260 tabnew 1261 set noswapfile 1262 mksession! 1263 1264 let content =<< trim [CODE] 1265 set nocp noswapfile 1266 function! DeleteInactiveBufs() 1267 tabfirst 1268 let tabblist = [] 1269 for i in range(1, tabpagenr(''$'')) 1270 call extend(tabblist, tabpagebuflist(i)) 1271 endfor 1272 for b in range(1, bufnr(''$'')) 1273 if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'') 1274 exec ''bwipeout '' . b 1275 endif 1276 endfor 1277 echomsg "SessionLoadPost DONE" 1278 endfunction 1279 au SessionLoadPost * call DeleteInactiveBufs() 1280 1281 func WriteErrors() 1282 call writefile([execute("messages")], "XerrorsPost") 1283 endfunc 1284 au VimLeave * call WriteErrors() 1285 [CODE] 1286 1287 call writefile(content, 'Xvimrc', 'D') 1288 call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq') 1289 sleep 100m 1290 let errors = join(readfile('XerrorsPost')) 1291 " This probably only ever matches on unix. 1292 call assert_notmatch('Caught deadly signal SEGV', errors) 1293 call assert_match('SessionLoadPost DONE', errors) 1294 1295 set swapfile 1296 for file in ['Session.vim', 'XerrorsPost'] 1297 call delete(file) 1298 endfor 1299 endfunc 1300 1301 func Test_empty_doau() 1302 doau \| 1303 endfunc 1304 1305 func s:AutoCommandOptionSet(match) 1306 let template = "Option: <%s>, OldVal: <%s>, OldValLocal: <%s>, OldValGlobal: <%s>, NewVal: <%s>, Scope: <%s>, Command: <%s>\n" 1307 let item = remove(g:options, 0) 1308 let expected = printf(template, item[0], item[1], item[2], item[3], item[4], item[5], item[6]) 1309 let actual = printf(template, a:match, v:option_old, v:option_oldlocal, v:option_oldglobal, v:option_new, v:option_type, v:option_command) 1310 let g:opt = [expected, actual] 1311 "call assert_equal(expected, actual) 1312 endfunc 1313 1314 func Test_OptionSet() 1315 " Use test/functional/legacy/autocmd_option_spec.lua 1316 throw 'Skipped: Nvim changed types of OptionSet v: variables' 1317 CheckOption autochdir 1318 1319 call test_override('starting', 1) 1320 set nocp 1321 au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>")) 1322 1323 " 1: Setting number option" 1324 let g:options = [['number', 0, 0, 0, 1, 'global', 'set']] 1325 set nu 1326 call assert_equal([], g:options) 1327 call assert_equal(g:opt[0], g:opt[1]) 1328 1329 " 2: Setting local number option" 1330 let g:options = [['number', 1, 1, '', 0, 'local', 'setlocal']] 1331 setlocal nonu 1332 call assert_equal([], g:options) 1333 call assert_equal(g:opt[0], g:opt[1]) 1334 1335 " 3: Setting global number option" 1336 let g:options = [['number', 1, '', 1, 0, 'global', 'setglobal']] 1337 setglobal nonu 1338 call assert_equal([], g:options) 1339 call assert_equal(g:opt[0], g:opt[1]) 1340 1341 " 4: Setting local autoindent option" 1342 let g:options = [['autoindent', 0, 0, '', 1, 'local', 'setlocal']] 1343 setlocal ai 1344 call assert_equal([], g:options) 1345 call assert_equal(g:opt[0], g:opt[1]) 1346 1347 " 5: Setting global autoindent option" 1348 let g:options = [['autoindent', 0, '', 0, 1, 'global', 'setglobal']] 1349 setglobal ai 1350 call assert_equal([], g:options) 1351 call assert_equal(g:opt[0], g:opt[1]) 1352 1353 " 6: Setting global autoindent option" 1354 let g:options = [['autoindent', 1, 1, 1, 0, 'global', 'set']] 1355 set ai! 1356 call assert_equal([], g:options) 1357 call assert_equal(g:opt[0], g:opt[1]) 1358 1359 " 6a: Setting global autoindent option" 1360 let g:options = [['autoindent', 1, 1, 0, 0, 'global', 'set']] 1361 noa setlocal ai 1362 noa setglobal noai 1363 set ai! 1364 call assert_equal([], g:options) 1365 call assert_equal(g:opt[0], g:opt[1]) 1366 1367 " Should not print anything, use :noa 1368 " 7: don't trigger OptionSet" 1369 let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']] 1370 noa set nonu 1371 call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options) 1372 call assert_equal(g:opt[0], g:opt[1]) 1373 1374 " 8: Setting several global list and number option" 1375 let g:options = [['list', 0, 0, 0, 1, 'global', 'set'], ['number', 0, 0, 0, 1, 'global', 'set']] 1376 set list nu 1377 call assert_equal([], g:options) 1378 call assert_equal(g:opt[0], g:opt[1]) 1379 1380 " 9: don't trigger OptionSet" 1381 let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']] 1382 noa set nolist nonu 1383 call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options) 1384 call assert_equal(g:opt[0], g:opt[1]) 1385 1386 " 10: Setting global acd" 1387 let g:options = [['autochdir', 0, 0, '', 1, 'local', 'setlocal']] 1388 setlocal acd 1389 call assert_equal([], g:options) 1390 call assert_equal(g:opt[0], g:opt[1]) 1391 1392 " 11: Setting global autoread (also sets local value)" 1393 let g:options = [['autoread', 0, 0, 0, 1, 'global', 'set']] 1394 set ar 1395 call assert_equal([], g:options) 1396 call assert_equal(g:opt[0], g:opt[1]) 1397 1398 " 12: Setting local autoread" 1399 let g:options = [['autoread', 1, 1, '', 1, 'local', 'setlocal']] 1400 setlocal ar 1401 call assert_equal([], g:options) 1402 call assert_equal(g:opt[0], g:opt[1]) 1403 1404 " 13: Setting global autoread" 1405 let g:options = [['autoread', 1, '', 1, 0, 'global', 'setglobal']] 1406 setglobal invar 1407 call assert_equal([], g:options) 1408 call assert_equal(g:opt[0], g:opt[1]) 1409 1410 " 14: Setting option backspace through :let" 1411 let g:options = [['backspace', 'indent,eol,start', 'indent,eol,start', 'indent,eol,start', '', 'global', 'set']] 1412 let &bs = '' 1413 call assert_equal([], g:options) 1414 call assert_equal(g:opt[0], g:opt[1]) 1415 1416 " 15: Setting option backspace through setbufvar()" 1417 let g:options = [['backup', 0, 0, '', 1, 'local', 'setlocal']] 1418 " try twice, first time, shouldn't trigger because option name is invalid, 1419 " second time, it should trigger 1420 let bnum = bufnr('%') 1421 call assert_fails("call setbufvar(bnum, '&l:bk', 1)", 'E355:') 1422 " should trigger, use correct option name 1423 call setbufvar(bnum, '&backup', 1) 1424 call assert_equal([], g:options) 1425 call assert_equal(g:opt[0], g:opt[1]) 1426 1427 " 16: Setting number option using setwinvar" 1428 let g:options = [['number', 0, 0, '', 1, 'local', 'setlocal']] 1429 call setwinvar(0, '&number', 1) 1430 call assert_equal([], g:options) 1431 call assert_equal(g:opt[0], g:opt[1]) 1432 1433 " 17: Setting key option, shouldn't trigger" 1434 let g:options = [['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']] 1435 setlocal key=blah 1436 setlocal key= 1437 call assert_equal([['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']], g:options) 1438 call assert_equal(g:opt[0], g:opt[1]) 1439 1440 1441 " 18a: Setting string global option" 1442 let oldval = &backupext 1443 let g:options = [['backupext', oldval, oldval, oldval, 'foo', 'global', 'set']] 1444 set backupext=foo 1445 call assert_equal([], g:options) 1446 call assert_equal(g:opt[0], g:opt[1]) 1447 1448 " 18b: Resetting string global option" 1449 let g:options = [['backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set']] 1450 set backupext& 1451 call assert_equal([], g:options) 1452 call assert_equal(g:opt[0], g:opt[1]) 1453 1454 " 18c: Setting global string global option" 1455 let g:options = [['backupext', oldval, '', oldval, 'bar', 'global', 'setglobal']] 1456 setglobal backupext=bar 1457 call assert_equal([], g:options) 1458 call assert_equal(g:opt[0], g:opt[1]) 1459 1460 " 18d: Setting local string global option" 1461 " As this is a global option this sets the global value even though 1462 " :setlocal is used! 1463 noa set backupext& " Reset global and local value (without triggering autocmd) 1464 let g:options = [['backupext', oldval, oldval, '', 'baz', 'local', 'setlocal']] 1465 setlocal backupext=baz 1466 call assert_equal([], g:options) 1467 call assert_equal(g:opt[0], g:opt[1]) 1468 1469 " 18e: Setting again string global option" 1470 noa setglobal backupext=ext_global " Reset global and local value (without triggering autocmd) 1471 noa setlocal backupext=ext_local " Sets the global(!) value! 1472 let g:options = [['backupext', 'ext_local', 'ext_local', 'ext_local', 'fuu', 'global', 'set']] 1473 set backupext=fuu 1474 call assert_equal([], g:options) 1475 call assert_equal(g:opt[0], g:opt[1]) 1476 1477 1478 " 19a: Setting string global-local (to buffer) option" 1479 let oldval = &tags 1480 let g:options = [['tags', oldval, oldval, oldval, 'tagpath', 'global', 'set']] 1481 set tags=tagpath 1482 call assert_equal([], g:options) 1483 call assert_equal(g:opt[0], g:opt[1]) 1484 1485 " 19b: Resetting string global-local (to buffer) option" 1486 let g:options = [['tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set']] 1487 set tags& 1488 call assert_equal([], g:options) 1489 call assert_equal(g:opt[0], g:opt[1]) 1490 1491 " 19c: Setting global string global-local (to buffer) option " 1492 let g:options = [['tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal']] 1493 setglobal tags=tagpath1 1494 call assert_equal([], g:options) 1495 call assert_equal(g:opt[0], g:opt[1]) 1496 1497 " 19d: Setting local string global-local (to buffer) option" 1498 let g:options = [['tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal']] 1499 setlocal tags=tagpath2 1500 call assert_equal([], g:options) 1501 call assert_equal(g:opt[0], g:opt[1]) 1502 1503 " 19e: Setting again string global-local (to buffer) option" 1504 " Note: v:option_old is the old global value for global-local string options 1505 " but the old local value for all other kinds of options. 1506 noa setglobal tags=tag_global " Reset global and local value (without triggering autocmd) 1507 noa setlocal tags=tag_local 1508 let g:options = [['tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set']] 1509 set tags=tagpath 1510 call assert_equal([], g:options) 1511 call assert_equal(g:opt[0], g:opt[1]) 1512 1513 " 19f: Setting string global-local (to buffer) option to an empty string" 1514 " Note: v:option_old is the old global value for global-local string options 1515 " but the old local value for all other kinds of options. 1516 noa set tags=tag_global " Reset global and local value (without triggering autocmd) 1517 noa setlocal tags= " empty string 1518 let g:options = [['tags', 'tag_global', '', 'tag_global', 'tagpath', 'global', 'set']] 1519 set tags=tagpath 1520 call assert_equal([], g:options) 1521 call assert_equal(g:opt[0], g:opt[1]) 1522 1523 1524 " 20a: Setting string local (to buffer) option" 1525 let oldval = &spelllang 1526 let g:options = [['spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set']] 1527 set spelllang=elvish,klingon 1528 call assert_equal([], g:options) 1529 call assert_equal(g:opt[0], g:opt[1]) 1530 1531 " 20b: Resetting string local (to buffer) option" 1532 let g:options = [['spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set']] 1533 set spelllang& 1534 call assert_equal([], g:options) 1535 call assert_equal(g:opt[0], g:opt[1]) 1536 1537 " 20c: Setting global string local (to buffer) option" 1538 let g:options = [['spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal']] 1539 setglobal spelllang=elvish 1540 call assert_equal([], g:options) 1541 call assert_equal(g:opt[0], g:opt[1]) 1542 1543 " 20d: Setting local string local (to buffer) option" 1544 noa set spelllang& " Reset global and local value (without triggering autocmd) 1545 let g:options = [['spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal']] 1546 setlocal spelllang=klingon 1547 call assert_equal([], g:options) 1548 call assert_equal(g:opt[0], g:opt[1]) 1549 1550 " 20e: Setting again string local (to buffer) option" 1551 " Note: v:option_old is the old global value for global-local string options 1552 " but the old local value for all other kinds of options. 1553 noa setglobal spelllang=spellglobal " Reset global and local value (without triggering autocmd) 1554 noa setlocal spelllang=spelllocal 1555 let g:options = [['spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set']] 1556 set spelllang=foo 1557 call assert_equal([], g:options) 1558 call assert_equal(g:opt[0], g:opt[1]) 1559 1560 1561 " 21a: Setting string global-local (to window) option" 1562 let oldval = &statusline 1563 let g:options = [['statusline', oldval, oldval, oldval, 'foo', 'global', 'set']] 1564 set statusline=foo 1565 call assert_equal([], g:options) 1566 call assert_equal(g:opt[0], g:opt[1]) 1567 1568 " 21b: Resetting string global-local (to window) option" 1569 " Note: v:option_old is the old global value for global-local string options 1570 " but the old local value for all other kinds of options. 1571 let g:options = [['statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set']] 1572 set statusline& 1573 call assert_equal([], g:options) 1574 call assert_equal(g:opt[0], g:opt[1]) 1575 1576 " 21c: Setting global string global-local (to window) option" 1577 let g:options = [['statusline', oldval, '', oldval, 'bar', 'global', 'setglobal']] 1578 setglobal statusline=bar 1579 call assert_equal([], g:options) 1580 call assert_equal(g:opt[0], g:opt[1]) 1581 1582 " 21d: Setting local string global-local (to window) option" 1583 noa set statusline& " Reset global and local value (without triggering autocmd) 1584 let g:options = [['statusline', oldval, oldval, '', 'baz', 'local', 'setlocal']] 1585 setlocal statusline=baz 1586 call assert_equal([], g:options) 1587 call assert_equal(g:opt[0], g:opt[1]) 1588 1589 " 21e: Setting again string global-local (to window) option" 1590 " Note: v:option_old is the old global value for global-local string options 1591 " but the old local value for all other kinds of options. 1592 noa setglobal statusline=bar " Reset global and local value (without triggering autocmd) 1593 noa setlocal statusline=baz 1594 let g:options = [['statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set']] 1595 set statusline=foo 1596 call assert_equal([], g:options) 1597 call assert_equal(g:opt[0], g:opt[1]) 1598 1599 1600 " 22a: Setting string local (to window) option" 1601 let oldval = &foldignore 1602 let g:options = [['foldignore', oldval, oldval, oldval, 'fo', 'global', 'set']] 1603 set foldignore=fo 1604 call assert_equal([], g:options) 1605 call assert_equal(g:opt[0], g:opt[1]) 1606 1607 " 22b: Resetting string local (to window) option" 1608 let g:options = [['foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set']] 1609 set foldignore& 1610 call assert_equal([], g:options) 1611 call assert_equal(g:opt[0], g:opt[1]) 1612 1613 " 22c: Setting global string local (to window) option" 1614 let g:options = [['foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal']] 1615 setglobal foldignore=bar 1616 call assert_equal([], g:options) 1617 call assert_equal(g:opt[0], g:opt[1]) 1618 1619 " 22d: Setting local string local (to window) option" 1620 noa set foldignore& " Reset global and local value (without triggering autocmd) 1621 let g:options = [['foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal']] 1622 setlocal foldignore=baz 1623 call assert_equal([], g:options) 1624 call assert_equal(g:opt[0], g:opt[1]) 1625 1626 " 22e: Setting again string local (to window) option" 1627 noa setglobal foldignore=glob " Reset global and local value (without triggering autocmd) 1628 noa setlocal foldignore=loc 1629 let g:options = [['foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set']] 1630 set foldignore=fo 1631 call assert_equal([], g:options) 1632 call assert_equal(g:opt[0], g:opt[1]) 1633 1634 1635 " 23a: Setting global number global option" 1636 noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd) 1637 noa setlocal cmdheight=1 " Sets the global(!) value! 1638 let g:options = [['cmdheight', '1', '', '1', '2', 'global', 'setglobal']] 1639 setglobal cmdheight=2 1640 call assert_equal([], g:options) 1641 call assert_equal(g:opt[0], g:opt[1]) 1642 1643 " 23b: Setting local number global option" 1644 noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd) 1645 noa setlocal cmdheight=1 " Sets the global(!) value! 1646 let g:options = [['cmdheight', '1', '1', '', '2', 'local', 'setlocal']] 1647 setlocal cmdheight=2 1648 call assert_equal([], g:options) 1649 call assert_equal(g:opt[0], g:opt[1]) 1650 1651 " 23c: Setting again number global option" 1652 noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd) 1653 noa setlocal cmdheight=1 " Sets the global(!) value! 1654 let g:options = [['cmdheight', '1', '1', '1', '2', 'global', 'set']] 1655 set cmdheight=2 1656 call assert_equal([], g:options) 1657 call assert_equal(g:opt[0], g:opt[1]) 1658 1659 " 23d: Setting again number global option" 1660 noa set cmdheight=8 " Reset global and local value (without triggering autocmd) 1661 let g:options = [['cmdheight', '8', '8', '8', '2', 'global', 'set']] 1662 set cmdheight=2 1663 call assert_equal([], g:options) 1664 call assert_equal(g:opt[0], g:opt[1]) 1665 1666 1667 " 24a: Setting global number global-local (to buffer) option" 1668 noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd) 1669 noa setlocal undolevels=1 1670 let g:options = [['undolevels', '8', '', '8', '2', 'global', 'setglobal']] 1671 setglobal undolevels=2 1672 call assert_equal([], g:options) 1673 call assert_equal(g:opt[0], g:opt[1]) 1674 1675 " 24b: Setting local number global-local (to buffer) option" 1676 noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd) 1677 noa setlocal undolevels=1 1678 let g:options = [['undolevels', '1', '1', '', '2', 'local', 'setlocal']] 1679 setlocal undolevels=2 1680 call assert_equal([], g:options) 1681 call assert_equal(g:opt[0], g:opt[1]) 1682 1683 " 24c: Setting again number global-local (to buffer) option" 1684 noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd) 1685 noa setlocal undolevels=1 1686 let g:options = [['undolevels', '1', '1', '8', '2', 'global', 'set']] 1687 set undolevels=2 1688 call assert_equal([], g:options) 1689 call assert_equal(g:opt[0], g:opt[1]) 1690 1691 " 24d: Setting again global number global-local (to buffer) option" 1692 noa set undolevels=8 " Reset global and local value (without triggering autocmd) 1693 let g:options = [['undolevels', '8', '8', '8', '2', 'global', 'set']] 1694 set undolevels=2 1695 call assert_equal([], g:options) 1696 call assert_equal(g:opt[0], g:opt[1]) 1697 1698 1699 " 25a: Setting global number local (to buffer) option" 1700 noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd) 1701 noa setlocal wrapmargin=1 1702 let g:options = [['wrapmargin', '8', '', '8', '2', 'global', 'setglobal']] 1703 setglobal wrapmargin=2 1704 call assert_equal([], g:options) 1705 call assert_equal(g:opt[0], g:opt[1]) 1706 1707 " 25b: Setting local number local (to buffer) option" 1708 noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd) 1709 noa setlocal wrapmargin=1 1710 let g:options = [['wrapmargin', '1', '1', '', '2', 'local', 'setlocal']] 1711 setlocal wrapmargin=2 1712 call assert_equal([], g:options) 1713 call assert_equal(g:opt[0], g:opt[1]) 1714 1715 " 25c: Setting again number local (to buffer) option" 1716 noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd) 1717 noa setlocal wrapmargin=1 1718 let g:options = [['wrapmargin', '1', '1', '8', '2', 'global', 'set']] 1719 set wrapmargin=2 1720 call assert_equal([], g:options) 1721 call assert_equal(g:opt[0], g:opt[1]) 1722 1723 " 25d: Setting again global number local (to buffer) option" 1724 noa set wrapmargin=8 " Reset global and local value (without triggering autocmd) 1725 let g:options = [['wrapmargin', '8', '8', '8', '2', 'global', 'set']] 1726 set wrapmargin=2 1727 call assert_equal([], g:options) 1728 call assert_equal(g:opt[0], g:opt[1]) 1729 1730 1731 " 26: Setting number global-local (to window) option. 1732 " Such option does currently not exist. 1733 1734 1735 " 27a: Setting global number local (to window) option" 1736 noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd) 1737 noa setlocal foldcolumn=1 1738 let g:options = [['foldcolumn', '8', '', '8', '2', 'global', 'setglobal']] 1739 setglobal foldcolumn=2 1740 call assert_equal([], g:options) 1741 call assert_equal(g:opt[0], g:opt[1]) 1742 1743 " 27b: Setting local number local (to window) option" 1744 noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd) 1745 noa setlocal foldcolumn=1 1746 let g:options = [['foldcolumn', '1', '1', '', '2', 'local', 'setlocal']] 1747 setlocal foldcolumn=2 1748 call assert_equal([], g:options) 1749 call assert_equal(g:opt[0], g:opt[1]) 1750 1751 " 27c: Setting again number local (to window) option" 1752 noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd) 1753 noa setlocal foldcolumn=1 1754 let g:options = [['foldcolumn', '1', '1', '8', '2', 'global', 'set']] 1755 set foldcolumn=2 1756 call assert_equal([], g:options) 1757 call assert_equal(g:opt[0], g:opt[1]) 1758 1759 " 27d: Setting again global number local (to window) option" 1760 noa set foldcolumn=8 " Reset global and local value (without triggering autocmd) 1761 let g:options = [['foldcolumn', '8', '8', '8', '2', 'global', 'set']] 1762 set foldcolumn=2 1763 call assert_equal([], g:options) 1764 call assert_equal(g:opt[0], g:opt[1]) 1765 1766 1767 " 28a: Setting global boolean global option" 1768 noa setglobal nowrapscan " Reset global and local value (without triggering autocmd) 1769 noa setlocal wrapscan " Sets the global(!) value! 1770 let g:options = [['wrapscan', '1', '', '1', '0', 'global', 'setglobal']] 1771 setglobal nowrapscan 1772 call assert_equal([], g:options) 1773 call assert_equal(g:opt[0], g:opt[1]) 1774 1775 " 28b: Setting local boolean global option" 1776 noa setglobal nowrapscan " Reset global and local value (without triggering autocmd) 1777 noa setlocal wrapscan " Sets the global(!) value! 1778 let g:options = [['wrapscan', '1', '1', '', '0', 'local', 'setlocal']] 1779 setlocal nowrapscan 1780 call assert_equal([], g:options) 1781 call assert_equal(g:opt[0], g:opt[1]) 1782 1783 " 28c: Setting again boolean global option" 1784 noa setglobal nowrapscan " Reset global and local value (without triggering autocmd) 1785 noa setlocal wrapscan " Sets the global(!) value! 1786 let g:options = [['wrapscan', '1', '1', '1', '0', 'global', 'set']] 1787 set nowrapscan 1788 call assert_equal([], g:options) 1789 call assert_equal(g:opt[0], g:opt[1]) 1790 1791 " 28d: Setting again global boolean global option" 1792 noa set nowrapscan " Reset global and local value (without triggering autocmd) 1793 let g:options = [['wrapscan', '0', '0', '0', '1', 'global', 'set']] 1794 set wrapscan 1795 call assert_equal([], g:options) 1796 call assert_equal(g:opt[0], g:opt[1]) 1797 1798 1799 " 29a: Setting global boolean global-local (to buffer) option" 1800 noa setglobal noautoread " Reset global and local value (without triggering autocmd) 1801 noa setlocal autoread 1802 let g:options = [['autoread', '0', '', '0', '1', 'global', 'setglobal']] 1803 setglobal autoread 1804 call assert_equal([], g:options) 1805 call assert_equal(g:opt[0], g:opt[1]) 1806 1807 " 29b: Setting local boolean global-local (to buffer) option" 1808 noa setglobal noautoread " Reset global and local value (without triggering autocmd) 1809 noa setlocal autoread 1810 let g:options = [['autoread', '1', '1', '', '0', 'local', 'setlocal']] 1811 setlocal noautoread 1812 call assert_equal([], g:options) 1813 call assert_equal(g:opt[0], g:opt[1]) 1814 1815 " 29c: Setting again boolean global-local (to buffer) option" 1816 noa setglobal noautoread " Reset global and local value (without triggering autocmd) 1817 noa setlocal autoread 1818 let g:options = [['autoread', '1', '1', '0', '1', 'global', 'set']] 1819 set autoread 1820 call assert_equal([], g:options) 1821 call assert_equal(g:opt[0], g:opt[1]) 1822 1823 " 29d: Setting again global boolean global-local (to buffer) option" 1824 noa set noautoread " Reset global and local value (without triggering autocmd) 1825 let g:options = [['autoread', '0', '0', '0', '1', 'global', 'set']] 1826 set autoread 1827 call assert_equal([], g:options) 1828 call assert_equal(g:opt[0], g:opt[1]) 1829 1830 1831 " 30a: Setting global boolean local (to buffer) option" 1832 noa setglobal nocindent " Reset global and local value (without triggering autocmd) 1833 noa setlocal cindent 1834 let g:options = [['cindent', '0', '', '0', '1', 'global', 'setglobal']] 1835 setglobal cindent 1836 call assert_equal([], g:options) 1837 call assert_equal(g:opt[0], g:opt[1]) 1838 1839 " 30b: Setting local boolean local (to buffer) option" 1840 noa setglobal nocindent " Reset global and local value (without triggering autocmd) 1841 noa setlocal cindent 1842 let g:options = [['cindent', '1', '1', '', '0', 'local', 'setlocal']] 1843 setlocal nocindent 1844 call assert_equal([], g:options) 1845 call assert_equal(g:opt[0], g:opt[1]) 1846 1847 " 30c: Setting again boolean local (to buffer) option" 1848 noa setglobal nocindent " Reset global and local value (without triggering autocmd) 1849 noa setlocal cindent 1850 let g:options = [['cindent', '1', '1', '0', '1', 'global', 'set']] 1851 set cindent 1852 call assert_equal([], g:options) 1853 call assert_equal(g:opt[0], g:opt[1]) 1854 1855 " 30d: Setting again global boolean local (to buffer) option" 1856 noa set nocindent " Reset global and local value (without triggering autocmd) 1857 let g:options = [['cindent', '0', '0', '0', '1', 'global', 'set']] 1858 set cindent 1859 call assert_equal([], g:options) 1860 call assert_equal(g:opt[0], g:opt[1]) 1861 1862 1863 " 31: Setting boolean global-local (to window) option 1864 " Currently no such option exists. 1865 1866 1867 " 32a: Setting global boolean local (to window) option" 1868 noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd) 1869 noa setlocal cursorcolumn 1870 let g:options = [['cursorcolumn', '0', '', '0', '1', 'global', 'setglobal']] 1871 setglobal cursorcolumn 1872 call assert_equal([], g:options) 1873 call assert_equal(g:opt[0], g:opt[1]) 1874 1875 " 32b: Setting local boolean local (to window) option" 1876 noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd) 1877 noa setlocal cursorcolumn 1878 let g:options = [['cursorcolumn', '1', '1', '', '0', 'local', 'setlocal']] 1879 setlocal nocursorcolumn 1880 call assert_equal([], g:options) 1881 call assert_equal(g:opt[0], g:opt[1]) 1882 1883 " 32c: Setting again boolean local (to window) option" 1884 noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd) 1885 noa setlocal cursorcolumn 1886 let g:options = [['cursorcolumn', '1', '1', '0', '1', 'global', 'set']] 1887 set cursorcolumn 1888 call assert_equal([], g:options) 1889 call assert_equal(g:opt[0], g:opt[1]) 1890 1891 " 32d: Setting again global boolean local (to window) option" 1892 noa set nocursorcolumn " Reset global and local value (without triggering autocmd) 1893 let g:options = [['cursorcolumn', '0', '0', '0', '1', 'global', 'set']] 1894 set cursorcolumn 1895 call assert_equal([], g:options) 1896 call assert_equal(g:opt[0], g:opt[1]) 1897 1898 1899 " 33: Test autocommands when an option value is converted internally. 1900 noa set backspace=1 " Reset global and local value (without triggering autocmd) 1901 let g:options = [['backspace', 'indent,eol', 'indent,eol', 'indent,eol', '2', 'global', 'set']] 1902 set backspace=2 1903 call assert_equal([], g:options) 1904 call assert_equal(g:opt[0], g:opt[1]) 1905 1906 1907 " Cleanup 1908 au! OptionSet 1909 " set tags& 1910 for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp', 'backupext', 'tags', 'spelllang', 'statusline', 'foldignore', 'cmdheight', 'undolevels', 'wrapmargin', 'foldcolumn', 'wrapscan', 'autoread', 'cindent', 'cursorcolumn'] 1911 exe printf(":set %s&vim", opt) 1912 endfor 1913 call test_override('starting', 0) 1914 delfunc! AutoCommandOptionSet 1915 endfunc 1916 1917 func Test_OptionSet_diffmode() 1918 call Ntest_override('starting', 1) 1919 " 18: Changing an option when entering diff mode 1920 new 1921 au OptionSet diff :let &l:cul = v:option_new 1922 1923 call setline(1, ['buffer 1', 'line2', 'line3', 'line4']) 1924 call assert_equal(0, &l:cul) 1925 diffthis 1926 call assert_equal(1, &l:cul) 1927 1928 vnew 1929 call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4']) 1930 call assert_equal(0, &l:cul) 1931 diffthis 1932 call assert_equal(1, &l:cul) 1933 1934 diffoff 1935 call assert_equal(0, &l:cul) 1936 call assert_equal(1, getwinvar(2, '&l:cul')) 1937 bw! 1938 1939 call assert_equal(1, &l:cul) 1940 diffoff! 1941 call assert_equal(0, &l:cul) 1942 call assert_equal(0, getwinvar(1, '&l:cul')) 1943 bw! 1944 1945 " Cleanup 1946 au! OptionSet 1947 call Ntest_override('starting', 0) 1948 endfunc 1949 1950 func Test_OptionSet_diffmode_close() 1951 call Ntest_override('starting', 1) 1952 " 19: Try to close the current window when entering diff mode 1953 " should not segfault 1954 new 1955 au OptionSet diff close 1956 1957 call setline(1, ['buffer 1', 'line2', 'line3', 'line4']) 1958 call assert_fails(':diffthis', 'E788') 1959 call assert_equal(1, &diff) 1960 vnew 1961 call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4']) 1962 call assert_fails(':diffthis', 'E788') 1963 call assert_equal(1, &diff) 1964 set diffopt-=closeoff 1965 bw! 1966 call assert_fails(':diffoff!', 'E788') 1967 bw! 1968 1969 " Cleanup 1970 au! OptionSet 1971 call Ntest_override('starting', 0) 1972 "delfunc! AutoCommandOptionSet 1973 endfunc 1974 1975 " Test for Bufleave autocommand that deletes the buffer we are about to edit. 1976 func Test_BufleaveWithDelete() 1977 new | edit XbufLeave1 1978 1979 augroup test_bufleavewithdelete 1980 autocmd! 1981 autocmd BufLeave XbufLeave1 bwipe XbufLeave2 1982 augroup END 1983 1984 call assert_fails('edit XbufLeave2', 'E143:') 1985 call assert_equal('XbufLeave1', bufname('%')) 1986 1987 autocmd! test_bufleavewithdelete BufLeave XbufLeave1 1988 augroup! test_bufleavewithdelete 1989 1990 new 1991 bwipe! XbufLeave1 1992 endfunc 1993 1994 " Test for autocommand that changes the buffer list, when doing ":ball". 1995 func Test_Acmd_BufAll() 1996 enew! 1997 %bwipe! 1998 call writefile(['Test file Xxx1'], 'Xxx1', 'D') 1999 call writefile(['Test file Xxx2'], 'Xxx2', 'D') 2000 call writefile(['Test file Xxx3'], 'Xxx3', 'D') 2001 2002 " Add three files to the buffer list 2003 split Xxx1 2004 close 2005 split Xxx2 2006 close 2007 split Xxx3 2008 close 2009 2010 " Wipe the buffer when the buffer is opened 2011 au BufReadPost Xxx2 bwipe 2012 2013 call append(0, 'Test file Xxx4') 2014 ball 2015 2016 call assert_equal(2, winnr('$')) 2017 call assert_equal('Xxx1', bufname(winbufnr(winnr('$')))) 2018 wincmd t 2019 2020 au! BufReadPost 2021 %bwipe! 2022 enew! | only 2023 endfunc 2024 2025 " Test for autocommand that changes current buffer on BufEnter event. 2026 " Check if modelines are interpreted for the correct buffer. 2027 func Test_Acmd_BufEnter() 2028 %bwipe! 2029 call writefile(['start of test file Xxx1', 2030 \ "\<Tab>this is a test", 2031 \ 'end of test file Xxx1'], 'Xxx1', 'D') 2032 call writefile(['start of test file Xxx2', 2033 \ 'vim: set noai :', 2034 \ "\<Tab>this is a test", 2035 \ 'end of test file Xxx2'], 'Xxx2', 'D') 2036 2037 au BufEnter Xxx2 brew 2038 set ai modeline modelines=3 2039 edit Xxx1 2040 " edit Xxx2, autocmd will do :brew 2041 edit Xxx2 2042 exe "normal G?this is a\<CR>" 2043 " Append text with autoindent to this file 2044 normal othis should be auto-indented 2045 call assert_equal("\<Tab>this should be auto-indented", getline('.')) 2046 call assert_equal(3, line('.')) 2047 " Remove autocmd and edit Xxx2 again 2048 au! BufEnter Xxx2 2049 buf! Xxx2 2050 exe "normal G?this is a\<CR>" 2051 " append text without autoindent to Xxx 2052 normal othis should be in column 1 2053 call assert_equal("this should be in column 1", getline('.')) 2054 call assert_equal(4, line('.')) 2055 2056 %bwipe! 2057 set ai&vim modeline&vim modelines&vim 2058 endfunc 2059 2060 " Test for issue #57 2061 " do not move cursor on <c-o> when autoindent is set 2062 func Test_ai_CTRL_O() 2063 enew! 2064 set ai 2065 let save_fo = &fo 2066 set fo+=r 2067 exe "normal o# abcdef\<Esc>2hi\<CR>\<C-O>d0\<Esc>" 2068 exe "normal o# abcdef\<Esc>2hi\<C-O>d0\<Esc>" 2069 call assert_equal(['# abc', 'def', 'def'], getline(2, 4)) 2070 2071 set ai&vim 2072 let &fo = save_fo 2073 enew! 2074 endfunc 2075 2076 " Test for autocommand that deletes the current buffer on BufLeave event. 2077 " Also test deleting the last buffer, should give a new, empty buffer. 2078 func Test_BufLeave_Wipe() 2079 %bwipe! 2080 let content = ['start of test file Xxx', 2081 \ 'this is a test', 2082 \ 'end of test file Xxx'] 2083 call writefile(content, 'Xxx1', 'D') 2084 call writefile(content, 'Xxx2', 'D') 2085 2086 au BufLeave Xxx2 bwipe 2087 edit Xxx1 2088 split Xxx2 2089 " delete buffer Xxx2, we should be back to Xxx1 2090 bwipe 2091 call assert_equal('Xxx1', bufname('%')) 2092 call assert_equal(1, winnr('$')) 2093 2094 " Create an alternate buffer 2095 %write! test.out 2096 call assert_equal('test.out', bufname('#')) 2097 " delete alternate buffer 2098 bwipe test.out 2099 call assert_equal('Xxx1', bufname('%')) 2100 call assert_equal('', bufname('#')) 2101 2102 au BufLeave Xxx1 bwipe 2103 " delete current buffer, get an empty one 2104 bwipe! 2105 call assert_equal(1, line('$')) 2106 call assert_equal('', bufname('%')) 2107 let g:bufinfo = getbufinfo() 2108 call assert_equal(1, len(g:bufinfo)) 2109 2110 call delete('test.out') 2111 %bwipe 2112 au! BufLeave 2113 2114 " check that bufinfo doesn't contain a pointer to freed memory 2115 call test_garbagecollect_now() 2116 endfunc 2117 2118 func Test_QuitPre() 2119 edit Xfoo 2120 let winid = win_getid(winnr()) 2121 split Xbar 2122 au! QuitPre * let g:afile = expand('<afile>') 2123 " Close the other window, <afile> should be correct. 2124 exe win_id2win(winid) . 'q' 2125 call assert_equal('Xfoo', g:afile) 2126 2127 unlet g:afile 2128 bwipe Xfoo 2129 bwipe Xbar 2130 endfunc 2131 2132 func Test_Cmdline_Trigger() 2133 autocmd CmdlineLeavePre : let g:log = "CmdlineLeavePre" 2134 autocmd CmdlineLeave : let g:log2 = "CmdlineLeave" 2135 new 2136 let g:log = '' 2137 let g:log2 = '' 2138 nnoremap <F1> <Cmd>echo "hello"<CR> 2139 call feedkeys("\<F1>", 'x') 2140 call assert_equal('', g:log) 2141 call assert_equal('', g:log2) 2142 nunmap <F1> 2143 2144 let g:log = '' 2145 let g:log2 = '' 2146 nnoremap <F1> :echo "hello"<CR> 2147 call feedkeys("\<F1>", 'x') 2148 call assert_equal('CmdlineLeavePre', g:log) 2149 call assert_equal('CmdlineLeave', g:log2) 2150 nunmap <F1> 2151 2152 let g:log = '' 2153 let g:log2 = '' 2154 call feedkeys(":\<bs>", "tx") 2155 call assert_equal('CmdlineLeavePre', g:log) 2156 call assert_equal('CmdlineLeave', g:log2) 2157 2158 let g:log = '' 2159 let g:log2 = '' 2160 split 2161 call assert_equal('', g:log) 2162 call feedkeys(":echo hello", "tx") 2163 call assert_equal('CmdlineLeavePre', g:log) 2164 call assert_equal('CmdlineLeave', g:log2) 2165 2166 let g:log = '' 2167 let g:log2 = '' 2168 close 2169 call assert_equal('', g:log) 2170 call feedkeys(":echo hello", "tx") 2171 call assert_equal('CmdlineLeavePre', g:log) 2172 call assert_equal('CmdlineLeave', g:log2) 2173 2174 let g:log = '' 2175 let g:log2 = '' 2176 tabnew 2177 call assert_equal('', g:log) 2178 call feedkeys(":echo hello", "tx") 2179 call assert_equal('CmdlineLeavePre', g:log) 2180 call assert_equal('CmdlineLeave', g:log2) 2181 2182 let g:log = '' 2183 let g:log2 = '' 2184 split 2185 call assert_equal('', g:log) 2186 call feedkeys(":echo hello", "tx") 2187 call assert_equal('CmdlineLeavePre', g:log) 2188 call assert_equal('CmdlineLeave', g:log2) 2189 2190 let g:log = '' 2191 let g:log2 = '' 2192 tabclose 2193 call assert_equal('', g:log) 2194 call feedkeys(":echo hello", "tx") 2195 call assert_equal('CmdlineLeavePre', g:log) 2196 call assert_equal('CmdlineLeave', g:log2) 2197 2198 autocmd CmdlineLeavePre * let g:cmdline += [getcmdline()] 2199 2200 for end_keys in ["\<CR>", "\<NL>", "\<kEnter>", "\<C-C>", "\<Esc>", 2201 \ "\<C-\>\<C-N>", "\<C-\>\<C-G>"] 2202 let g:cmdline = [] 2203 let g:log = '' 2204 let g:log2 = '' 2205 call assert_equal('', g:log) 2206 let keys = $':echo "hello"{end_keys}' 2207 let msg = keytrans(keys) 2208 call feedkeys(keys, "tx") 2209 call assert_equal(['echo "hello"'], g:cmdline, msg) 2210 call assert_equal('CmdlineLeavePre', g:log, msg) 2211 call assert_equal('CmdlineLeave', g:log2, msg) 2212 endfor 2213 2214 let g:cmdline = [] 2215 call feedkeys(":let c = input('? ')\<cr>ABCDE\<cr>", "tx") 2216 call assert_equal(["let c = input('? ')", 'ABCDE'], g:cmdline) 2217 2218 au! CmdlineLeavePre 2219 unlet! g:cmdline 2220 unlet! g:log 2221 unlet! g:log2 2222 bw! 2223 endfunc 2224 2225 " Ensure :cabbr does not cause a spurious CmdlineLeavePre. 2226 func Test_CmdlineLeavePre_cabbr() 2227 " For unknown reason this fails intermittently on MS-Windows 2228 CheckNotMSWindows 2229 CheckFeature terminal 2230 let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3}) 2231 call assert_equal('running', term_getstatus(buf)) 2232 call term_sendkeys(buf, ":let g:a=0\<cr>") 2233 call term_wait(buf, 50) 2234 call term_sendkeys(buf, ":cabbr v v\<cr>") 2235 call term_wait(buf, 50) 2236 call term_sendkeys(buf, ":command! -nargs=* Foo echo\<cr>") 2237 call term_wait(buf, 50) 2238 call term_sendkeys(buf, ":au! CmdlineLeavePre * :let g:a+=1\<cr>") 2239 call term_wait(buf, 50) 2240 call term_sendkeys(buf, ":Foo v\<cr>") 2241 call term_wait(buf, 50) 2242 call term_sendkeys(buf, ":echo g:a\<cr>") 2243 call term_wait(buf, 50) 2244 call WaitForAssert({-> assert_match('^2.*$', term_getline(buf, 3))}) 2245 bwipe! 2246 endfunc 2247 2248 func Test_Cmdline() 2249 au! CmdlineChanged : let g:text = getcmdline() 2250 let g:text = 0 2251 call feedkeys(":echom 'hello'\<CR>", 'xt') 2252 call assert_equal("echom 'hello'", g:text) 2253 au! CmdlineChanged 2254 2255 au! CmdlineChanged : let g:entered = expand('<afile>') 2256 let g:entered = 0 2257 call feedkeys(":echom 'hello'\<CR>", 'xt') 2258 call assert_equal(':', g:entered) 2259 au! CmdlineChanged 2260 2261 autocmd CmdlineChanged : let g:log += [getcmdline()] 2262 2263 let g:log = [] 2264 cnoremap <F1> <Cmd>call setcmdline('ls')<CR> 2265 call feedkeys(":\<F1>", 'xt') 2266 call assert_equal(['ls'], g:log) 2267 cunmap <F1> 2268 2269 let g:log = [] 2270 call feedkeys(":sign \<Tab>\<Tab>\<C-N>\<C-P>\<S-Tab>\<S-Tab>\<Esc>", 'xt') 2271 call assert_equal([ 2272 \ 's', 2273 \ 'si', 2274 \ 'sig', 2275 \ 'sign', 2276 \ 'sign ', 2277 \ 'sign define', 2278 \ 'sign jump', 2279 \ 'sign list', 2280 \ 'sign jump', 2281 \ 'sign define', 2282 \ 'sign ', 2283 \ ], g:log) 2284 let g:log = [] 2285 set wildmenu wildoptions+=pum 2286 call feedkeys(":sign \<S-Tab>\<PageUp>\<kPageUp>\<kPageDown>\<PageDown>\<Esc>", 'xt') 2287 call assert_equal([ 2288 \ 's', 2289 \ 'si', 2290 \ 'sig', 2291 \ 'sign', 2292 \ 'sign ', 2293 \ 'sign unplace', 2294 \ 'sign jump', 2295 \ 'sign define', 2296 \ 'sign undefine', 2297 \ 'sign unplace', 2298 \ ], g:log) 2299 set wildmenu& wildoptions& 2300 2301 let g:log = [] 2302 let @r = 'abc' 2303 call feedkeys(":0\<C-R>=@r\<CR>1\<C-R>\<C-O>r2\<C-R>\<C-R>r3\<Esc>", 'xt') 2304 call assert_equal([ 2305 \ '0', 2306 \ '0a', 2307 \ '0ab', 2308 \ '0abc', 2309 \ '0abc1', 2310 \ '0abc1abc', 2311 \ '0abc1abc2', 2312 \ '0abc1abc2abc', 2313 \ '0abc1abc2abc3', 2314 \ ], g:log) 2315 2316 " <Del> should trigger CmdlineChanged 2317 let g:log = [] 2318 call feedkeys(":foo\<Left>\<Left>\<Del>\<Del>\<Esc>", 'xt') 2319 call assert_equal([ 2320 \ 'f', 2321 \ 'fo', 2322 \ 'foo', 2323 \ 'fo', 2324 \ 'f', 2325 \ ], g:log) 2326 2327 unlet g:log 2328 au! CmdlineChanged 2329 2330 au! CmdlineEnter : let g:entered = expand('<afile>') 2331 au! CmdlineLeave : let g:left = expand('<afile>') 2332 au! CmdlineLeavePre : let g:leftpre = expand('<afile>') 2333 let g:entered = 0 2334 let g:left = 0 2335 let g:leftpre = 0 2336 call feedkeys(":echo 'hello'\<CR>", 'xt') 2337 call assert_equal(':', g:entered) 2338 call assert_equal(':', g:left) 2339 call assert_equal(':', g:leftpre) 2340 au! CmdlineEnter 2341 au! CmdlineLeave 2342 au! CmdlineLeavePre 2343 2344 let save_shellslash = &shellslash 2345 " Nvim doesn't allow setting value of a hidden option to non-default value 2346 if exists('+shellslash') 2347 set noshellslash 2348 endif 2349 au! CmdlineEnter / let g:entered = expand('<afile>') 2350 au! CmdlineLeave / let g:left = expand('<afile>') 2351 au! CmdlineLeavePre / let g:leftpre = expand('<afile>') 2352 let g:entered = 0 2353 let g:left = 0 2354 let g:leftpre = 0 2355 new 2356 call setline(1, 'hello') 2357 call feedkeys("/hello\<CR>", 'xt') 2358 call assert_equal('/', g:entered) 2359 call assert_equal('/', g:left) 2360 call assert_equal('/', g:leftpre) 2361 bwipe! 2362 au! CmdlineEnter 2363 au! CmdlineLeave 2364 au! CmdlineLeavePre 2365 let &shellslash = save_shellslash 2366 2367 let g:left = "cancelled" 2368 let g:leftpre = "cancelled" 2369 au! CmdlineLeave : let g:left = "triggered" 2370 au! CmdlineLeavePre : let g:leftpre = "triggered" 2371 call feedkeys(":echo 'hello'\<esc>", 'xt') 2372 call assert_equal('triggered', g:left) 2373 call assert_equal('triggered', g:leftpre) 2374 let g:left = "cancelled" 2375 let g:leftpre = "cancelled" 2376 au! CmdlineLeave : let g:left = "triggered" 2377 call feedkeys(":echo 'hello'\<c-c>", 'xt') 2378 call assert_equal('triggered', g:left) 2379 call assert_equal('triggered', g:leftpre) 2380 au! CmdlineLeave 2381 au! CmdlineLeavePre 2382 2383 au! CursorMovedC : let g:pos += [getcmdpos()] 2384 let g:pos = [] 2385 call feedkeys(":foo bar baz\<C-W>\<C-W>\<C-W>\<Esc>", 'xt') 2386 call assert_equal([2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 9, 5, 1], g:pos) 2387 let g:pos = [] 2388 call feedkeys(":hello\<C-B>\<Esc>", 'xt') 2389 call assert_equal([2, 3, 4, 5, 6, 1], g:pos) 2390 let g:pos = [] 2391 call feedkeys(":hello\<C-U>\<Esc>", 'xt') 2392 call assert_equal([2, 3, 4, 5, 6, 1], g:pos) 2393 let g:pos = [] 2394 call feedkeys(":hello\<Left>\<C-R>=''\<CR>\<Left>\<Right>\<Esc>", 'xt') 2395 call assert_equal([2, 3, 4, 5, 6, 5, 4, 5], g:pos) 2396 let g:pos = [] 2397 call feedkeys(":12345678\<C-R>=setcmdpos(3)??''\<CR>\<Esc>", 'xt') 2398 call assert_equal([2, 3, 4, 5, 6, 7, 8, 9, 3], g:pos) 2399 let g:pos = [] 2400 call feedkeys(":12345678\<C-R>=setcmdpos(3)??''\<CR>\<Left>\<Esc>", 'xt') 2401 call assert_equal([2, 3, 4, 5, 6, 7, 8, 9, 3, 2], g:pos) 2402 au! CursorMovedC 2403 2404 " setcmdpos() is no-op inside an autocommand 2405 au! CursorMovedC : let g:pos += [getcmdpos()] | call setcmdpos(1) 2406 let g:pos = [] 2407 call feedkeys(":hello\<Left>\<Left>\<Esc>", 'xt') 2408 call assert_equal([2, 3, 4, 5, 6, 5, 4], g:pos) 2409 au! CursorMovedC 2410 2411 unlet g:entered 2412 unlet g:left 2413 unlet g:pos 2414 endfunc 2415 2416 " Test for BufWritePre autocommand that deletes or unloads the buffer. 2417 func Test_BufWritePre() 2418 %bwipe 2419 au BufWritePre Xxx1 bunload 2420 au BufWritePre Xxx2 bwipe 2421 2422 call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1', 'D') 2423 call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2', 'D') 2424 2425 edit Xtest 2426 e! Xxx2 2427 bdel Xtest 2428 e Xxx1 2429 " write it, will unload it and give an error msg 2430 call assert_fails('w', 'E203:') 2431 call assert_equal('Xxx2', bufname('%')) 2432 edit Xtest 2433 e! Xxx2 2434 bwipe Xtest 2435 " write it, will delete the buffer and give an error msg 2436 call assert_fails('w', 'E203:') 2437 call assert_equal('Xxx1', bufname('%')) 2438 au! BufWritePre 2439 endfunc 2440 2441 " Test for BufUnload autocommand that unloads all the other buffers 2442 func Test_bufunload_all() 2443 let g:test_is_flaky = 1 2444 call writefile(['Test file Xxx1'], 'Xxx1', 'D') 2445 call writefile(['Test file Xxx2'], 'Xxx2', 'D') 2446 2447 let content =<< trim [CODE] 2448 func UnloadAllBufs() 2449 let i = 1 2450 while i <= bufnr('$') 2451 if i != bufnr('%') && bufloaded(i) 2452 exe i . 'bunload' 2453 endif 2454 let i += 1 2455 endwhile 2456 endfunc 2457 au BufUnload * call UnloadAllBufs() 2458 au VimLeave * call writefile(['Test Finished'], 'Xout') 2459 set nohidden " Accommodate Nvim default 2460 edit Xxx1 2461 split Xxx2 2462 q 2463 [CODE] 2464 2465 call writefile(content, 'Xbunloadtest', 'D') 2466 2467 call delete('Xout') 2468 call system(GetVimCommandClean() .. ' -N --headless -S Xbunloadtest') 2469 call assert_true(filereadable('Xout')) 2470 2471 call delete('Xout') 2472 endfunc 2473 2474 " Some tests for buffer-local autocommands 2475 func Test_buflocal_autocmd() 2476 let g:bname = '' 2477 edit xx 2478 au BufLeave <buffer> let g:bname = expand("%") 2479 " here, autocommand for xx should trigger. 2480 " but autocommand shall not apply to buffer named <buffer>. 2481 edit somefile 2482 call assert_equal('xx', g:bname) 2483 let g:bname = '' 2484 " here, autocommand shall be auto-deleted 2485 bwipe xx 2486 " autocmd should not trigger 2487 edit xx 2488 call assert_equal('', g:bname) 2489 " autocmd should not trigger 2490 edit somefile 2491 call assert_equal('', g:bname) 2492 enew 2493 unlet g:bname 2494 endfunc 2495 2496 " Test for "*Cmd" autocommands 2497 func Test_Cmd_Autocmds() 2498 call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx', 'D') 2499 2500 enew! 2501 au BufReadCmd XtestA 0r Xxx|$del 2502 edit XtestA " will read text of Xxd instead 2503 call assert_equal('start of Xxx', getline(1)) 2504 2505 au BufWriteCmd XtestA call append(line("$"), "write") 2506 write " will append a line to the file 2507 call assert_equal('write', getline('$')) 2508 call assert_fails('read XtestA', 'E484') " should not read anything 2509 call assert_equal('write', getline(4)) 2510 2511 " now we have: 2512 " 1 start of Xxx 2513 " 2 abc2 2514 " 3 end of Xxx 2515 " 4 write 2516 2517 au FileReadCmd XtestB '[r Xxx 2518 2r XtestB " will read Xxx below line 2 instead 2519 call assert_equal('start of Xxx', getline(3)) 2520 2521 " now we have: 2522 " 1 start of Xxx 2523 " 2 abc2 2524 " 3 start of Xxx 2525 " 4 abc2 2526 " 5 end of Xxx 2527 " 6 end of Xxx 2528 " 7 write 2529 2530 au FileWriteCmd XtestC '[,']copy $ 2531 normal 4GA1 2532 4,5w XtestC " will copy lines 4 and 5 to the end 2533 call assert_equal("\tabc21", getline(8)) 2534 call assert_fails('r XtestC', 'E484') " should not read anything 2535 call assert_equal("end of Xxx", getline(9)) 2536 2537 " now we have: 2538 " 1 start of Xxx 2539 " 2 abc2 2540 " 3 start of Xxx 2541 " 4 abc21 2542 " 5 end of Xxx 2543 " 6 end of Xxx 2544 " 7 write 2545 " 8 abc21 2546 " 9 end of Xxx 2547 2548 let g:lines = [] 2549 au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']"))) 2550 w >>XtestD " will add lines to 'lines' 2551 call assert_equal(9, len(g:lines)) 2552 call assert_fails('$r XtestD', 'E484') " should not read anything 2553 call assert_equal(9, line('$')) 2554 call assert_equal('end of Xxx', getline('$')) 2555 2556 au BufReadCmd XtestE 0r Xxx|$del 2557 sp XtestE " split window with test.out 2558 call assert_equal('end of Xxx', getline(3)) 2559 2560 let g:lines = [] 2561 exe "normal 2Goasdf\<Esc>\<C-W>\<C-W>" 2562 au BufWriteCmd XtestE call extend(g:lines, getline(0, '$')) 2563 wall " will write other window to 'lines' 2564 call assert_equal(4, len(g:lines), g:lines) 2565 call assert_equal("asdf", g:lines[2]) 2566 2567 au! BufReadCmd 2568 au! BufWriteCmd 2569 au! FileReadCmd 2570 au! FileWriteCmd 2571 au! FileAppendCmd 2572 %bwipe! 2573 enew! 2574 endfunc 2575 2576 func s:ReadFile() 2577 setl noswapfile nomodified 2578 let filename = resolve(expand("<afile>:p")) 2579 execute 'read' fnameescape(filename) 2580 1d_ 2581 exe 'file' fnameescape(filename) 2582 setl buftype=acwrite 2583 endfunc 2584 2585 func s:WriteFile() 2586 let filename = resolve(expand("<afile>:p")) 2587 setl buftype= 2588 noautocmd execute 'write' fnameescape(filename) 2589 setl buftype=acwrite 2590 setl nomodified 2591 endfunc 2592 2593 func Test_BufReadCmd() 2594 autocmd BufReadCmd *.test call s:ReadFile() 2595 autocmd BufWriteCmd *.test call s:WriteFile() 2596 2597 call writefile(['one', 'two', 'three'], 'Xcmd.test', 'D') 2598 edit Xcmd.test 2599 set noruler 2600 call assert_match('Xcmd.test" line 1 of 3', execute('file')) 2601 set ruler 2602 call assert_match('Xcmd.test" 3 lines --33%--', execute('file')) 2603 normal! Gofour 2604 write 2605 call assert_equal(['one', 'two', 'three', 'four'], readfile('Xcmd.test')) 2606 2607 bwipe! 2608 au! BufReadCmd 2609 au! BufWriteCmd 2610 endfunc 2611 2612 func Test_BufWriteCmd() 2613 autocmd BufWriteCmd Xbufwritecmd let g:written = 1 2614 new 2615 file Xbufwritecmd 2616 set buftype=acwrite 2617 call mkdir('Xbufwritecmd', 'D') 2618 write 2619 " BufWriteCmd should be triggered even if a directory has the same name 2620 call assert_equal(1, g:written) 2621 unlet g:written 2622 au! BufWriteCmd 2623 bwipe! 2624 endfunc 2625 2626 func SetChangeMarks(start, end) 2627 exe a:start .. 'mark [' 2628 exe a:end .. 'mark ]' 2629 endfunc 2630 2631 " Verify the effects of autocmds on '[ and '] 2632 func Test_change_mark_in_autocmds() 2633 edit! Xtest 2634 call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u\<Esc>", 'xtn') 2635 2636 call SetChangeMarks(2, 3) 2637 write 2638 call assert_equal([1, 4], [line("'["), line("']")]) 2639 2640 call SetChangeMarks(2, 3) 2641 au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")]) 2642 write 2643 au! BufWritePre 2644 2645 if has('unix') 2646 write XtestFilter 2647 write >> XtestFilter 2648 2649 call SetChangeMarks(2, 3) 2650 " Marks are set to the entire range of the write 2651 au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")]) 2652 " '[ is adjusted to just before the line that will receive the filtered 2653 " data 2654 au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")]) 2655 " The filtered data is read into the buffer, and the source lines are 2656 " still present, so the range is after the source lines 2657 au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")]) 2658 %!cat XtestFilter 2659 " After the filtered data is read, the original lines are deleted 2660 call assert_equal([1, 8], [line("'["), line("']")]) 2661 au! FilterWritePre,FilterReadPre,FilterReadPost 2662 undo 2663 2664 call SetChangeMarks(1, 4) 2665 au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")]) 2666 au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")]) 2667 au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")]) 2668 2,3!cat XtestFilter 2669 call assert_equal([2, 9], [line("'["), line("']")]) 2670 au! FilterWritePre,FilterReadPre,FilterReadPost 2671 undo 2672 2673 call delete('XtestFilter') 2674 endif 2675 2676 call SetChangeMarks(1, 4) 2677 au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")]) 2678 2,3write Xtest2 2679 au! FileWritePre 2680 2681 call SetChangeMarks(2, 3) 2682 au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")]) 2683 write >> Xtest2 2684 au! FileAppendPre 2685 2686 call SetChangeMarks(1, 4) 2687 au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")]) 2688 2,3write >> Xtest2 2689 au! FileAppendPre 2690 2691 call SetChangeMarks(1, 1) 2692 au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")]) 2693 au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")]) 2694 3read Xtest2 2695 au! FileReadPre,FileReadPost 2696 undo 2697 2698 call SetChangeMarks(4, 4) 2699 " When the line is 0, it's adjusted to 1 2700 au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")]) 2701 au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")]) 2702 0read Xtest2 2703 au! FileReadPre,FileReadPost 2704 undo 2705 2706 call SetChangeMarks(4, 4) 2707 " When the line is 0, it's adjusted to 1 2708 au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")]) 2709 au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")]) 2710 1read Xtest2 2711 au! FileReadPre,FileReadPost 2712 undo 2713 2714 bwipe! 2715 call delete('Xtest') 2716 call delete('Xtest2') 2717 endfunc 2718 2719 func Test_Filter_noshelltemp() 2720 CheckExecutable cat 2721 2722 enew! 2723 call setline(1, ['a', 'b', 'c', 'd']) 2724 2725 let shelltemp = &shelltemp 2726 set shelltemp 2727 2728 let g:filter_au = 0 2729 au FilterWritePre * let g:filter_au += 1 2730 au FilterReadPre * let g:filter_au += 1 2731 au FilterReadPost * let g:filter_au += 1 2732 %!cat 2733 call assert_equal(3, g:filter_au) 2734 2735 if has('filterpipe') 2736 set noshelltemp 2737 2738 let g:filter_au = 0 2739 au FilterWritePre * let g:filter_au += 1 2740 au FilterReadPre * let g:filter_au += 1 2741 au FilterReadPost * let g:filter_au += 1 2742 %!cat 2743 call assert_equal(0, g:filter_au) 2744 endif 2745 2746 au! FilterWritePre,FilterReadPre,FilterReadPost 2747 let &shelltemp = shelltemp 2748 bwipe! 2749 endfunc 2750 2751 func Test_TextYankPost() 2752 enew! 2753 call setline(1, ['foo']) 2754 2755 let g:event = [] 2756 au TextYankPost * let g:event = copy(v:event) 2757 2758 call assert_equal({}, v:event) 2759 call assert_fails('let v:event = {}', 'E46:') 2760 call assert_fails('let v:event.mykey = 0', 'E742:') 2761 2762 norm "ayiw 2763 call assert_equal( 2764 \{'regcontents': ['foo'], 'inclusive': v:true, 'regname': 'a', 'operator': 'y', 'visual': v:false, 'regtype': 'v'}, 2765 \g:event) 2766 norm y_ 2767 call assert_equal( 2768 \{'regcontents': ['foo'], 'inclusive': v:false, 'regname': '', 'operator': 'y', 'visual': v:false, 'regtype': 'V'}, 2769 \g:event) 2770 norm Vy 2771 call assert_equal( 2772 \{'regcontents': ['foo'], 'inclusive': v:true, 'regname': '', 'operator': 'y', 'visual': v:true, 'regtype': 'V'}, 2773 \g:event) 2774 call feedkeys("\<C-V>y", 'x') 2775 call assert_equal( 2776 \{'regcontents': ['f'], 'inclusive': v:true, 'regname': '', 'operator': 'y', 'visual': v:true, 'regtype': "\x161"}, 2777 \g:event) 2778 norm "xciwbar 2779 call assert_equal( 2780 \{'regcontents': ['foo'], 'inclusive': v:true, 'regname': 'x', 'operator': 'c', 'visual': v:false, 'regtype': 'v'}, 2781 \g:event) 2782 norm "bdiw 2783 call assert_equal( 2784 \{'regcontents': ['bar'], 'inclusive': v:true, 'regname': 'b', 'operator': 'd', 'visual': v:false, 'regtype': 'v'}, 2785 \g:event) 2786 2787 call assert_equal({}, v:event) 2788 2789 au! TextYankPost 2790 unlet g:event 2791 bwipe! 2792 endfunc 2793 2794 func Test_autocommand_all_events() 2795 call assert_fails('au * * bwipe', 'E1155:') 2796 call assert_fails('au * x bwipe', 'E1155:') 2797 call assert_fails('au! * x bwipe', 'E1155:') 2798 endfunc 2799 2800 func Test_autocmd_user() 2801 au User MyEvent let s:res = [expand("<afile>"), expand("<amatch>")] 2802 doautocmd User MyEvent 2803 call assert_equal(['MyEvent', 'MyEvent'], s:res) 2804 au! User 2805 unlet s:res 2806 endfunc 2807 2808 function s:Before_test_dirchanged() 2809 augroup test_dirchanged 2810 autocmd! 2811 augroup END 2812 let s:li = [] 2813 let s:dir_this = getcwd() 2814 let s:dir_foo = s:dir_this . '/Xfoo' 2815 call mkdir(s:dir_foo) 2816 let s:dir_bar = s:dir_this . '/Xbar' 2817 call mkdir(s:dir_bar) 2818 endfunc 2819 2820 function s:After_test_dirchanged() 2821 call chdir(s:dir_this) 2822 call delete(s:dir_foo, 'd') 2823 call delete(s:dir_bar, 'd') 2824 augroup test_dirchanged 2825 autocmd! 2826 augroup END 2827 endfunc 2828 2829 function Test_dirchanged_global() 2830 call s:Before_test_dirchanged() 2831 autocmd test_dirchanged DirChangedPre global call add(s:li, expand("<amatch>") .. " pre cd " .. v:event.directory) 2832 autocmd test_dirchanged DirChanged global call add(s:li, "cd:") 2833 autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>")) 2834 call chdir(s:dir_foo) 2835 let expected = ["global pre cd " .. s:dir_foo, "cd:", s:dir_foo] 2836 call assert_equal(expected, s:li) 2837 call chdir(s:dir_foo) 2838 call assert_equal(expected, s:li) 2839 exe 'lcd ' .. fnameescape(s:dir_bar) 2840 call assert_equal(expected, s:li) 2841 2842 exe 'cd ' .. s:dir_foo 2843 exe 'cd ' .. s:dir_bar 2844 autocmd! test_dirchanged DirChanged global let g:result = expand("<afile>") 2845 cd - 2846 call assert_equal(s:dir_foo, substitute(g:result, '\\', '/', 'g')) 2847 2848 call s:After_test_dirchanged() 2849 endfunc 2850 2851 function Test_dirchanged_local() 2852 call s:Before_test_dirchanged() 2853 autocmd test_dirchanged DirChanged window call add(s:li, "lcd:") 2854 autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>")) 2855 call chdir(s:dir_foo) 2856 call assert_equal([], s:li) 2857 exe 'lcd ' .. fnameescape(s:dir_bar) 2858 call assert_equal(["lcd:", s:dir_bar], s:li) 2859 exe 'lcd ' .. fnameescape(s:dir_bar) 2860 call assert_equal(["lcd:", s:dir_bar], s:li) 2861 call s:After_test_dirchanged() 2862 endfunc 2863 2864 function Test_dirchanged_auto() 2865 CheckFunction test_autochdir 2866 CheckOption autochdir 2867 call s:Before_test_dirchanged() 2868 call test_autochdir() 2869 autocmd test_dirchanged DirChangedPre auto call add(s:li, "pre cd " .. v:event.directory) 2870 autocmd test_dirchanged DirChanged auto call add(s:li, "auto:") 2871 autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>")) 2872 set acd 2873 cd .. 2874 call assert_equal([], s:li) 2875 exe 'edit ' . s:dir_foo . '/Xautofile' 2876 call assert_equal(s:dir_foo, getcwd()) 2877 let expected = ["pre cd " .. s:dir_foo, "auto:", s:dir_foo] 2878 call assert_equal(expected, s:li) 2879 set noacd 2880 bwipe! 2881 call s:After_test_dirchanged() 2882 endfunc 2883 2884 " Test TextChangedI and TextChangedP 2885 func Test_ChangedP() 2886 new 2887 call setline(1, ['foo', 'bar', 'foobar']) 2888 call Ntest_override("char_avail", 1) 2889 set complete=. completeopt=menuone 2890 2891 func! TextChangedAutocmd(char) 2892 let g:autocmd .= a:char 2893 endfunc 2894 2895 " TextChanged will not be triggered, only check that it isn't. 2896 au! TextChanged <buffer> :call TextChangedAutocmd('N') 2897 au! TextChangedI <buffer> :call TextChangedAutocmd('I') 2898 au! TextChangedP <buffer> :call TextChangedAutocmd('P') 2899 2900 call cursor(3, 1) 2901 let g:autocmd = '' 2902 call feedkeys("o\<esc>", 'tnix') 2903 call assert_equal('I', g:autocmd) 2904 2905 let g:autocmd = '' 2906 call feedkeys("Sf", 'tnix') 2907 call assert_equal('II', g:autocmd) 2908 2909 let g:autocmd = '' 2910 call feedkeys("Sf\<C-N>", 'tnix') 2911 call assert_equal('IIP', g:autocmd) 2912 2913 let g:autocmd = '' 2914 call feedkeys("Sf\<C-N>\<C-N>", 'tnix') 2915 call assert_equal('IIPP', g:autocmd) 2916 2917 let g:autocmd = '' 2918 call feedkeys("Sf\<C-N>\<C-N>\<C-N>", 'tnix') 2919 call assert_equal('IIPPP', g:autocmd) 2920 2921 let g:autocmd = '' 2922 call feedkeys("Sf\<C-N>\<C-N>\<C-N>\<C-N>", 'tnix') 2923 call assert_equal('IIPPPP', g:autocmd) 2924 2925 call assert_equal(['foo', 'bar', 'foobar', 'foo'], getline(1, '$')) 2926 " TODO: how should it handle completeopt=noinsert,noselect? 2927 2928 " CleanUp 2929 call Ntest_override("char_avail", 0) 2930 au! TextChanged 2931 au! TextChangedI 2932 au! TextChangedP 2933 delfu TextChangedAutocmd 2934 unlet! g:autocmd 2935 set complete&vim completeopt&vim 2936 2937 bw! 2938 endfunc 2939 2940 let g:setline_handled = v:false 2941 func SetLineOne() 2942 if !g:setline_handled 2943 call setline(1, "(x)") 2944 let g:setline_handled = v:true 2945 endif 2946 endfunc 2947 2948 func Test_TextChangedI_with_setline() 2949 new 2950 call Ntest_override('char_avail', 1) 2951 autocmd TextChangedI <buffer> call SetLineOne() 2952 call feedkeys("i(\<CR>\<Esc>", 'tx') 2953 call assert_equal('(', getline(1)) 2954 call assert_equal('x)', getline(2)) 2955 undo 2956 call assert_equal('', getline(1)) 2957 call assert_equal('', getline(2)) 2958 2959 call Ntest_override('char_avail', 0) 2960 bwipe! 2961 endfunc 2962 2963 func Test_TextChanged_with_norm() 2964 " For unknown reason this fails on MS-Windows 2965 CheckNotMSWindows 2966 CheckFeature terminal 2967 let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3}) 2968 call assert_equal('running', term_getstatus(buf)) 2969 call term_sendkeys(buf, ":let g:a=0\<cr>") 2970 call term_wait(buf, 50) 2971 call term_sendkeys(buf, ":au! TextChanged * :let g:a+=1\<cr>") 2972 call term_wait(buf, 50) 2973 call term_sendkeys(buf, ":norm! ia\<cr>") 2974 call term_wait(buf, 50) 2975 call term_sendkeys(buf, ":echo g:a\<cr>") 2976 call term_wait(buf, 50) 2977 call WaitForAssert({-> assert_match('^1.*$', term_getline(buf, 3))}) 2978 bwipe! 2979 endfunc 2980 2981 func Test_Changed_FirstTime() 2982 CheckFeature terminal 2983 CheckNotGui 2984 " Starting a terminal to run Vim is always considered flaky. 2985 let g:test_is_flaky = 1 2986 2987 " Prepare file for TextChanged event. 2988 call writefile([''], 'Xchanged.txt', 'D') 2989 let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3}) 2990 call assert_equal('running', term_getstatus(buf)) 2991 " Wait for the ruler (in the status line) to be shown. 2992 " In ConPTY, there is additional character which is drawn up to the width of 2993 " the screen. 2994 if has('conpty') 2995 call WaitForAssert({-> assert_match('\<All.*$', term_getline(buf, 3))}) 2996 else 2997 call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))}) 2998 endif 2999 " It's only adding autocmd, so that no event occurs. 3000 call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>") 3001 call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>") 3002 call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))}) 3003 call assert_equal([''], readfile('Xchanged.txt')) 3004 3005 " clean up 3006 bwipe! 3007 endfunc 3008 3009 func Test_autocmd_nested() 3010 let g:did_nested = 0 3011 defer CleanUpTestAuGroup() 3012 augroup testing 3013 au WinNew * edit somefile 3014 au BufNew * let g:did_nested = 1 3015 augroup END 3016 split 3017 call assert_equal(0, g:did_nested) 3018 close 3019 bwipe! somefile 3020 3021 " old nested argument still works 3022 augroup testing 3023 au! 3024 au WinNew * nested edit somefile 3025 au BufNew * let g:did_nested = 1 3026 augroup END 3027 split 3028 call assert_equal(1, g:did_nested) 3029 close 3030 bwipe! somefile 3031 3032 " New ++nested argument works 3033 augroup Testing 3034 au! 3035 au WinNew * ++nested edit somefile 3036 au BufNew * let g:did_nested = 1 3037 augroup END 3038 split 3039 call assert_equal(1, g:did_nested) 3040 close 3041 bwipe! somefile 3042 3043 augroup Testing 3044 au! 3045 augroup END 3046 3047 call assert_fails('au WinNew * ++nested ++nested echo bad', 'E983:') 3048 call assert_fails('au WinNew * nested nested echo bad', 'E983:') 3049 endfunc 3050 3051 func Test_autocmd_nested_cursor_invalid() 3052 set laststatus=0 3053 copen 3054 cclose 3055 call setline(1, ['foo', 'bar', 'baz']) 3056 3 3057 augroup nested_inv 3058 autocmd User foo ++nested copen 3059 autocmd BufAdd * let &laststatus = 2 - &laststatus 3060 augroup END 3061 doautocmd User foo 3062 3063 augroup nested_inv 3064 au! 3065 augroup END 3066 set laststatus& 3067 cclose 3068 bwipe! 3069 endfunc 3070 3071 func Test_autocmd_nested_keeps_cursor_pos() 3072 enew 3073 call setline(1, 'foo') 3074 autocmd User foo ++nested normal! $a 3075 autocmd InsertLeave * : 3076 doautocmd User foo 3077 call assert_equal([0, 1, 3, 0], getpos('.')) 3078 3079 bwipe! 3080 endfunc 3081 3082 func Test_autocmd_nested_switch_window() 3083 " run this in a separate Vim so that SafeState works 3084 CheckRunVimInTerminal 3085 CheckScreendump 3086 3087 let lines =<< trim END 3088 vim9script 3089 ['()']->writefile('Xautofile') 3090 autocmd VimEnter * ++nested edit Xautofile | split 3091 autocmd BufReadPost * autocmd SafeState * ++once foldclosed('.') 3092 autocmd WinEnter * matchadd('ErrorMsg', 'pat') 3093 END 3094 call writefile(lines, 'Xautoscript', 'D') 3095 let buf = RunVimInTerminal('-S Xautoscript', {'rows': 10}) 3096 call VerifyScreenDump(buf, 'Test_autocmd_nested_switch', {}) 3097 3098 call StopVimInTerminal(buf) 3099 call delete('Xautofile') 3100 endfunc 3101 3102 func Test_autocmd_once() 3103 " Without ++once WinNew triggers twice 3104 let g:did_split = 0 3105 augroup Testing 3106 au WinNew * let g:did_split += 1 3107 augroup END 3108 split 3109 split 3110 call assert_equal(2, g:did_split) 3111 call assert_true(exists('#WinNew')) 3112 close 3113 close 3114 3115 " With ++once WinNew triggers once 3116 let g:did_split = 0 3117 augroup Testing 3118 au! 3119 au WinNew * ++once let g:did_split += 1 3120 augroup END 3121 split 3122 split 3123 call assert_equal(1, g:did_split) 3124 call assert_false(exists('#WinNew')) 3125 close 3126 close 3127 3128 call assert_fails('au WinNew * ++once ++once echo bad', 'E983:') 3129 endfunc 3130 3131 func Test_autocmd_bufreadpre() 3132 new 3133 let b:bufreadpre = 1 3134 call append(0, range(100)) 3135 w! XAutocmdBufReadPre.txt 3136 autocmd BufReadPre <buffer> :let b:bufreadpre += 1 3137 norm! 50gg 3138 sp 3139 norm! 100gg 3140 wincmd p 3141 let g:wsv1 = winsaveview() 3142 wincmd p 3143 let g:wsv2 = winsaveview() 3144 " triggers BufReadPre, should not move the cursor in either window 3145 " The topline may change one line in a large window. 3146 edit 3147 call assert_inrange(g:wsv2.topline - 1, g:wsv2.topline + 1, winsaveview().topline) 3148 call assert_equal(g:wsv2.lnum, winsaveview().lnum) 3149 call assert_equal(2, b:bufreadpre) 3150 wincmd p 3151 call assert_equal(g:wsv1.topline, winsaveview().topline) 3152 call assert_equal(g:wsv1.lnum, winsaveview().lnum) 3153 call assert_equal(2, b:bufreadpre) 3154 " Now set the cursor position in an BufReadPre autocommand 3155 " (even though the position will be invalid, this should make Vim reset the 3156 " cursor position in the other window. 3157 wincmd p 3158 1 " set cpo+=g 3159 " won't do anything, but try to set the cursor on an invalid lnum 3160 autocmd BufReadPre <buffer> :norm! 70gg 3161 " triggers BufReadPre, should not move the cursor in either window 3162 e 3163 call assert_equal(1, winsaveview().topline) 3164 call assert_equal(1, winsaveview().lnum) 3165 call assert_equal(3, b:bufreadpre) 3166 wincmd p 3167 call assert_equal(g:wsv1.topline, winsaveview().topline) 3168 call assert_equal(g:wsv1.lnum, winsaveview().lnum) 3169 call assert_equal(3, b:bufreadpre) 3170 close 3171 close 3172 call delete('XAutocmdBufReadPre.txt') 3173 set cpo-=g 3174 endfunc 3175 3176 " FileChangedShell tested in test_filechanged.vim 3177 3178 " Tests for the following autocommands: 3179 " - FileWritePre writing a compressed file 3180 " - FileReadPost reading a compressed file 3181 " - BufNewFile reading a file template 3182 " - BufReadPre decompressing the file to be read 3183 " - FilterReadPre substituting characters in the temp file 3184 " - FilterReadPost substituting characters after filtering 3185 " - FileReadPre set options for decompression 3186 " - FileReadPost decompress the file 3187 func Test_ReadWrite_Autocmds() 3188 " Run this test only on Unix-like systems and if gzip is available 3189 if !has('unix') || !executable("gzip") 3190 return 3191 endif 3192 3193 " Make $GZIP empty, "-v" would cause trouble. 3194 let $GZIP = "" 3195 3196 " Use a FileChangedShell autocommand to avoid a prompt for 'Xtestfile.gz' 3197 " being modified outside of Vim (noticed on Solaris). 3198 au FileChangedShell * echo 'caught FileChangedShell' 3199 3200 " Test for the FileReadPost, FileWritePre and FileWritePost autocmds 3201 augroup Test1 3202 au! 3203 au FileWritePre *.gz '[,']!gzip 3204 au FileWritePost *.gz undo 3205 au FileReadPost *.gz '[,']!gzip -d 3206 augroup END 3207 3208 new 3209 set bin 3210 call append(0, [ 3211 \ 'line 2 Abcdefghijklmnopqrstuvwxyz', 3212 \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3213 \ 'line 4 Abcdefghijklmnopqrstuvwxyz', 3214 \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3215 \ 'line 6 Abcdefghijklmnopqrstuvwxyz', 3216 \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3217 \ 'line 8 Abcdefghijklmnopqrstuvwxyz', 3218 \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3219 \ 'line 10 Abcdefghijklmnopqrstuvwxyz' 3220 \ ]) 3221 1,9write! Xtestfile.gz 3222 enew! | close 3223 3224 new 3225 " Read and decompress the testfile 3226 0read Xtestfile.gz 3227 call assert_equal([ 3228 \ 'line 2 Abcdefghijklmnopqrstuvwxyz', 3229 \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3230 \ 'line 4 Abcdefghijklmnopqrstuvwxyz', 3231 \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3232 \ 'line 6 Abcdefghijklmnopqrstuvwxyz', 3233 \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3234 \ 'line 8 Abcdefghijklmnopqrstuvwxyz', 3235 \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3236 \ 'line 10 Abcdefghijklmnopqrstuvwxyz' 3237 \ ], getline(1, 9)) 3238 enew! | close 3239 3240 augroup Test1 3241 au! 3242 augroup END 3243 3244 " Test for the FileAppendPre and FileAppendPost autocmds 3245 augroup Test2 3246 au! 3247 au BufNewFile *.c read Xtest.c 3248 au FileAppendPre *.out '[,']s/new/NEW/ 3249 au FileAppendPost *.out !cat Xtest.c >> test.out 3250 augroup END 3251 3252 call writefile(['/*', ' * Here is a new .c file', ' */'], 'Xtest.c', 'D') 3253 new foo.c " should load Xtest.c 3254 call assert_equal(['/*', ' * Here is a new .c file', ' */'], getline(2, 4)) 3255 w! >> test.out " append it to the output file 3256 3257 let contents = readfile('test.out') 3258 call assert_equal(' * Here is a NEW .c file', contents[2]) 3259 call assert_equal(' * Here is a new .c file', contents[5]) 3260 3261 call delete('test.out') 3262 enew! | close 3263 augroup Test2 3264 au! 3265 augroup END 3266 3267 " Test for the BufReadPre and BufReadPost autocmds 3268 augroup Test3 3269 au! 3270 " setup autocommands to decompress before reading and re-compress 3271 " afterwards 3272 au BufReadPre *.gz exe '!gzip -d ' . shellescape(expand("<afile>")) 3273 au BufReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>")) 3274 au BufReadPost *.gz call rename(expand("<afile>"), expand("<afile>:r")) 3275 au BufReadPost *.gz exe '!gzip ' . shellescape(expand("<afile>:r")) 3276 augroup END 3277 3278 e! Xtestfile.gz " Edit compressed file 3279 call assert_equal([ 3280 \ 'line 2 Abcdefghijklmnopqrstuvwxyz', 3281 \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3282 \ 'line 4 Abcdefghijklmnopqrstuvwxyz', 3283 \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3284 \ 'line 6 Abcdefghijklmnopqrstuvwxyz', 3285 \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3286 \ 'line 8 Abcdefghijklmnopqrstuvwxyz', 3287 \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3288 \ 'line 10 Abcdefghijklmnopqrstuvwxyz' 3289 \ ], getline(1, 9)) 3290 3291 w! >> test.out " Append it to the output file 3292 3293 augroup Test3 3294 au! 3295 augroup END 3296 3297 " Test for the FilterReadPre and FilterReadPost autocmds. 3298 set shelltemp " need temp files here 3299 augroup Test4 3300 au! 3301 au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t") 3302 au FilterReadPre *.out exe 'silent !sed s/e/E/ ' . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>")) 3303 au FilterReadPre *.out exe 'silent !rm ' . shellescape(expand("<afile>")) . '.t' 3304 au FilterReadPost *.out '[,']s/x/X/g 3305 augroup END 3306 3307 e! test.out " Edit the output file 3308 1,$!cat 3309 call assert_equal([ 3310 \ 'linE 2 AbcdefghijklmnopqrstuvwXyz', 3311 \ 'linE 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 3312 \ 'linE 4 AbcdefghijklmnopqrstuvwXyz', 3313 \ 'linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 3314 \ 'linE 6 AbcdefghijklmnopqrstuvwXyz', 3315 \ 'linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 3316 \ 'linE 8 AbcdefghijklmnopqrstuvwXyz', 3317 \ 'linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 3318 \ 'linE 10 AbcdefghijklmnopqrstuvwXyz' 3319 \ ], getline(1, 9)) 3320 call assert_equal([ 3321 \ 'line 2 Abcdefghijklmnopqrstuvwxyz', 3322 \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3323 \ 'line 4 Abcdefghijklmnopqrstuvwxyz', 3324 \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3325 \ 'line 6 Abcdefghijklmnopqrstuvwxyz', 3326 \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3327 \ 'line 8 Abcdefghijklmnopqrstuvwxyz', 3328 \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3329 \ 'line 10 Abcdefghijklmnopqrstuvwxyz' 3330 \ ], readfile('test.out')) 3331 3332 augroup Test4 3333 au! 3334 augroup END 3335 set shelltemp&vim 3336 3337 " Test for the FileReadPre and FileReadPost autocmds. 3338 augroup Test5 3339 au! 3340 au FileReadPre *.gz exe 'silent !gzip -d ' . shellescape(expand("<afile>")) 3341 au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>")) 3342 au FileReadPost *.gz '[,']s/l/L/ 3343 augroup END 3344 3345 new 3346 0r Xtestfile.gz " Read compressed file 3347 call assert_equal([ 3348 \ 'Line 2 Abcdefghijklmnopqrstuvwxyz', 3349 \ 'Line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3350 \ 'Line 4 Abcdefghijklmnopqrstuvwxyz', 3351 \ 'Line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3352 \ 'Line 6 Abcdefghijklmnopqrstuvwxyz', 3353 \ 'Line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3354 \ 'Line 8 Abcdefghijklmnopqrstuvwxyz', 3355 \ 'Line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3356 \ 'Line 10 Abcdefghijklmnopqrstuvwxyz' 3357 \ ], getline(1, 9)) 3358 call assert_equal([ 3359 \ 'line 2 Abcdefghijklmnopqrstuvwxyz', 3360 \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3361 \ 'line 4 Abcdefghijklmnopqrstuvwxyz', 3362 \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3363 \ 'line 6 Abcdefghijklmnopqrstuvwxyz', 3364 \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3365 \ 'line 8 Abcdefghijklmnopqrstuvwxyz', 3366 \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 3367 \ 'line 10 Abcdefghijklmnopqrstuvwxyz' 3368 \ ], readfile('Xtestfile.gz')) 3369 3370 augroup Test5 3371 au! 3372 augroup END 3373 3374 au! FileChangedShell 3375 call delete('Xtestfile.gz') 3376 call delete('test.out') 3377 endfunc 3378 3379 func Test_throw_in_BufWritePre() 3380 new 3381 call setline(1, ['one', 'two', 'three']) 3382 call assert_false(filereadable('Xthefile')) 3383 augroup throwing 3384 au BufWritePre X* throw 'do not write' 3385 augroup END 3386 try 3387 w Xthefile 3388 catch 3389 let caught = 1 3390 endtry 3391 call assert_equal(1, caught) 3392 call assert_false(filereadable('Xthefile')) 3393 3394 bwipe! 3395 au! throwing 3396 endfunc 3397 3398 func Test_autocmd_in_try_block() 3399 call mkdir('Xintrydir', 'R') 3400 au BufEnter * let g:fname = expand('%') 3401 try 3402 edit Xintrydir/ 3403 endtry 3404 call assert_match('Xintrydir', g:fname) 3405 3406 unlet g:fname 3407 au! BufEnter 3408 endfunc 3409 3410 func Test_autocmd_SafeState() 3411 CheckRunVimInTerminal 3412 3413 let lines =<< trim END 3414 let g:safe = 0 3415 let g:again = '' 3416 au SafeState * let g:safe += 1 3417 au SafeStateAgain * let g:again ..= 'x' 3418 func CallTimer() 3419 call timer_start(10, {id -> execute('let g:again ..= "t"')}) 3420 endfunc 3421 END 3422 call writefile(lines, 'XSafeState', 'D') 3423 let buf = RunVimInTerminal('-S XSafeState', #{rows: 6}) 3424 3425 " Sometimes we loop to handle a K_IGNORE, SafeState may be triggered once or 3426 " more often. 3427 call term_sendkeys(buf, ":echo g:safe\<CR>") 3428 call WaitForAssert({-> assert_match('^\d ', term_getline(buf, 6))}, 1000) 3429 3430 " SafeStateAgain should be invoked at least three times 3431 call term_sendkeys(buf, ":echo g:again\<CR>") 3432 call WaitForAssert({-> assert_match('^xxx', term_getline(buf, 6))}, 1000) 3433 3434 call term_sendkeys(buf, ":let g:again = ''\<CR>:call CallTimer()\<CR>") 3435 call TermWait(buf, 50) 3436 call term_sendkeys(buf, ":\<CR>") 3437 call TermWait(buf, 50) 3438 call term_sendkeys(buf, ":echo g:again\<CR>") 3439 call WaitForAssert({-> assert_match('xtx', term_getline(buf, 6))}, 1000) 3440 3441 call StopVimInTerminal(buf) 3442 endfunc 3443 3444 func Test_autocmd_CmdWinEnter() 3445 CheckRunVimInTerminal 3446 " There is not cmdwin switch, so 3447 " test for cmdline_hist 3448 " (both are available with small builds) 3449 CheckFeature cmdline_hist 3450 let lines =<< trim END 3451 let b:dummy_var = 'This is a dummy' 3452 autocmd CmdWinEnter * quit 3453 let winnr = winnr('$') 3454 END 3455 let filename = 'XCmdWinEnter' 3456 call writefile(lines, filename) 3457 let buf = RunVimInTerminal('-S '.filename, #{rows: 6}) 3458 3459 call term_sendkeys(buf, "q:") 3460 call TermWait(buf) 3461 call term_sendkeys(buf, ":echo b:dummy_var\<cr>") 3462 call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000) 3463 call term_sendkeys(buf, ":echo &buftype\<cr>") 3464 call WaitForAssert({-> assert_notmatch('^nofile', term_getline(buf, 6))}, 1000) 3465 call term_sendkeys(buf, ":echo winnr\<cr>") 3466 call WaitForAssert({-> assert_match('^1', term_getline(buf, 6))}, 1000) 3467 3468 " clean up 3469 call StopVimInTerminal(buf) 3470 call delete(filename) 3471 endfunc 3472 3473 func Test_autocmd_was_using_freed_memory() 3474 CheckFeature quickfix 3475 3476 pedit xx 3477 n x 3478 augroup winenter 3479 au WinEnter * if winnr('$') > 2 | quit | endif 3480 augroup END 3481 " Nvim needs large 'winwidth' and 'nowinfixwidth' to crash 3482 set winwidth=99999 nowinfixwidth 3483 split 3484 3485 augroup winenter 3486 au! WinEnter 3487 augroup END 3488 3489 set winwidth& winfixwidth& 3490 bwipe xx 3491 bwipe x 3492 pclose 3493 endfunc 3494 3495 func Test_BufWrite_lockmarks() 3496 let g:test_is_flaky = 1 3497 edit! Xtest 3498 call setline(1, ['a', 'b', 'c', 'd']) 3499 3500 " :lockmarks preserves the marks 3501 call SetChangeMarks(2, 3) 3502 lockmarks write 3503 call assert_equal([2, 3], [line("'["), line("']")]) 3504 3505 " *WritePre autocmds get the correct line range, but lockmarks preserves the 3506 " original values for the user 3507 augroup lockmarks 3508 au! 3509 au BufWritePre,FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")]) 3510 au FileWritePre * call assert_equal([3, 4], [line("'["), line("']")]) 3511 augroup END 3512 3513 lockmarks write 3514 call assert_equal([2, 3], [line("'["), line("']")]) 3515 3516 if executable('cat') 3517 lockmarks %!cat 3518 call assert_equal([2, 3], [line("'["), line("']")]) 3519 endif 3520 3521 lockmarks 3,4write Xtest2 3522 call assert_equal([2, 3], [line("'["), line("']")]) 3523 3524 au! lockmarks 3525 augroup! lockmarks 3526 call delete('Xtest') 3527 call delete('Xtest2') 3528 endfunc 3529 3530 func Test_FileType_spell() 3531 if !isdirectory('/tmp') 3532 throw "Skipped: requires /tmp directory" 3533 endif 3534 3535 " this was crashing with an invalid free() 3536 setglobal spellfile=/tmp/en.utf-8.add 3537 augroup crash 3538 autocmd! 3539 autocmd BufNewFile,BufReadPost crashfile setf somefiletype 3540 autocmd BufNewFile,BufReadPost crashfile set ft=anotherfiletype 3541 autocmd FileType anotherfiletype setlocal spell 3542 augroup END 3543 func! NoCrash() abort 3544 edit /tmp/crashfile 3545 endfunc 3546 call NoCrash() 3547 3548 au! crash 3549 setglobal spellfile= 3550 endfunc 3551 3552 " this was wiping out the current buffer and using freed memory 3553 func Test_SpellFileMissing_bwipe() 3554 next 0 3555 au SpellFileMissing 0 bwipe 3556 call assert_fails('set spell spelllang=0', 'E937:') 3557 3558 au! SpellFileMissing 3559 set nospell spelllang=en 3560 bwipe 3561 endfunc 3562 3563 " Test closing a window or editing another buffer from a FileChangedRO handler 3564 " in a readonly buffer 3565 func Test_FileChangedRO_winclose() 3566 augroup FileChangedROTest 3567 au! 3568 autocmd FileChangedRO * quit 3569 augroup END 3570 new 3571 set readonly 3572 call assert_fails('normal i', 'E788:') 3573 close 3574 augroup! FileChangedROTest 3575 3576 augroup FileChangedROTest 3577 au! 3578 autocmd FileChangedRO * edit Xrofile 3579 augroup END 3580 new 3581 set readonly 3582 call assert_fails('normal i', 'E788:') 3583 close 3584 augroup! FileChangedROTest 3585 endfunc 3586 3587 func LogACmd() 3588 call add(g:logged, line('$')) 3589 endfunc 3590 3591 func Test_TermChanged() 3592 throw 'skipped: Nvim does not support TermChanged event' 3593 CheckNotGui 3594 3595 enew! 3596 tabnew 3597 call setline(1, ['a', 'b', 'c', 'd']) 3598 $ 3599 au TermChanged * call LogACmd() 3600 let g:logged = [] 3601 let term_save = &term 3602 set term=xterm 3603 call assert_equal([1, 4], g:logged) 3604 3605 au! TermChanged 3606 let &term = term_save 3607 bwipe! 3608 endfunc 3609 3610 " Test for FileReadCmd autocmd 3611 func Test_autocmd_FileReadCmd() 3612 func ReadFileCmd() 3613 call append(line('$'), "v:cmdarg = " .. v:cmdarg) 3614 endfunc 3615 augroup FileReadCmdTest 3616 au! 3617 au FileReadCmd Xtest call ReadFileCmd() 3618 augroup END 3619 3620 new 3621 read ++bin Xtest 3622 read ++nobin Xtest 3623 read ++edit Xtest 3624 read ++bad=keep Xtest 3625 read ++bad=drop Xtest 3626 read ++bad=- Xtest 3627 read ++ff=unix Xtest 3628 read ++ff=dos Xtest 3629 read ++ff=mac Xtest 3630 read ++enc=utf-8 Xtest 3631 3632 call assert_equal(['', 3633 \ 'v:cmdarg = ++bin', 3634 \ 'v:cmdarg = ++nobin', 3635 \ 'v:cmdarg = ++edit', 3636 \ 'v:cmdarg = ++bad=keep', 3637 \ 'v:cmdarg = ++bad=drop', 3638 \ 'v:cmdarg = ++bad=-', 3639 \ 'v:cmdarg = ++ff=unix', 3640 \ 'v:cmdarg = ++ff=dos', 3641 \ 'v:cmdarg = ++ff=mac', 3642 \ 'v:cmdarg = ++enc=utf-8'], getline(1, '$')) 3643 3644 bwipe! 3645 augroup FileReadCmdTest 3646 au! 3647 augroup END 3648 delfunc ReadFileCmd 3649 endfunc 3650 3651 " Test for passing invalid arguments to autocmd 3652 func Test_autocmd_invalid_args() 3653 " Additional character after * for event 3654 call assert_fails('autocmd *a Xinvfile set ff=unix', 'E215:') 3655 augroup Test 3656 augroup END 3657 " Invalid autocmd event 3658 call assert_fails('autocmd Bufabc Xinvfile set ft=vim', 'E216:') 3659 " Invalid autocmd event in a autocmd group 3660 call assert_fails('autocmd Test Bufabc Xinvfile set ft=vim', 'E216:') 3661 augroup! Test 3662 " Execute all autocmds 3663 call assert_fails('doautocmd * BufEnter', 'E217:') 3664 call assert_fails('augroup! x1a2b3', 'E367:') 3665 call assert_fails('autocmd BufNew <buffer=999> pwd', 'E680:') 3666 call assert_fails('autocmd BufNew \) set ff=unix', 'E55:') 3667 endfunc 3668 3669 " Test for deep nesting of autocmds 3670 func Test_autocmd_deep_nesting() 3671 autocmd BufEnter Xdeepfile doautocmd BufEnter Xdeepfile 3672 call assert_fails('doautocmd BufEnter Xdeepfile', 'E218:') 3673 autocmd! BufEnter Xdeepfile 3674 endfunc 3675 3676 " Tests for SigUSR1 autocmd event, which is only available on posix systems. 3677 func Test_autocmd_sigusr1() 3678 CheckUnix 3679 3680 let g:sigusr1_passed = 0 3681 au Signal SIGUSR1 let g:sigusr1_passed = 1 3682 call system('kill -s usr1 ' . getpid()) 3683 call WaitForAssert({-> assert_true(g:sigusr1_passed)}) 3684 3685 au! Signal 3686 unlet g:sigusr1_passed 3687 endfunc 3688 3689 " Test for BufReadPre autocmd deleting the file 3690 func Test_BufReadPre_delfile() 3691 augroup TestAuCmd 3692 au! 3693 autocmd BufReadPre XbufreadPre call delete('XbufreadPre') 3694 augroup END 3695 call writefile([], 'XbufreadPre', 'D') 3696 call assert_fails('new XbufreadPre', 'E200:') 3697 call assert_equal('XbufreadPre', @%) 3698 call assert_equal(1, &readonly) 3699 3700 augroup TestAuCmd 3701 au! 3702 augroup END 3703 close! 3704 endfunc 3705 3706 " Test for BufReadPre autocmd changing the current buffer 3707 func Test_BufReadPre_changebuf() 3708 augroup TestAuCmd 3709 au! 3710 autocmd BufReadPre Xchangebuf edit Xsomeotherfile 3711 augroup END 3712 call writefile([], 'Xchangebuf', 'D') 3713 call assert_fails('new Xchangebuf', 'E201:') 3714 call assert_equal('Xsomeotherfile', @%) 3715 call assert_equal(1, &readonly) 3716 3717 augroup TestAuCmd 3718 au! 3719 augroup END 3720 close! 3721 endfunc 3722 3723 " Test for BufWipeout autocmd changing the current buffer when reading a file 3724 " in an empty buffer with 'f' flag in 'cpo' 3725 func Test_BufDelete_changebuf() 3726 new 3727 augroup TestAuCmd 3728 au! 3729 autocmd BufWipeout * let bufnr = bufadd('somefile') | exe "b " .. bufnr 3730 augroup END 3731 let save_cpo = &cpo 3732 set cpo+=f 3733 call assert_fails('r Xfile', ['E812:', 'E484:']) 3734 call assert_equal('somefile', @%) 3735 let &cpo = save_cpo 3736 augroup TestAuCmd 3737 au! 3738 augroup END 3739 close! 3740 endfunc 3741 3742 " Test for the temporary internal window used to execute autocmds 3743 func Test_autocmd_window() 3744 %bw! 3745 edit one.txt 3746 tabnew two.txt 3747 vnew three.txt 3748 tabnew four.txt 3749 tabprevious 3750 let g:blist = [] 3751 augroup aucmd_win_test1 3752 au! 3753 au BufEnter * call add(g:blist, [expand('<afile>'), 3754 \ win_gettype(bufwinnr(expand('<afile>')))]) 3755 augroup END 3756 3757 doautoall BufEnter 3758 call assert_equal([ 3759 \ ['one.txt', 'autocmd'], 3760 \ ['two.txt', ''], 3761 \ ['four.txt', 'autocmd'], 3762 \ ['three.txt', ''], 3763 \ ], g:blist) 3764 3765 augroup aucmd_win_test1 3766 au! 3767 augroup END 3768 augroup! aucmd_win_test1 3769 %bw! 3770 endfunc 3771 3772 " Test for trying to close the temporary window used for executing an autocmd 3773 func Test_close_autocmd_window() 3774 %bw! 3775 edit one.txt 3776 tabnew two.txt 3777 augroup aucmd_win_test2 3778 au! 3779 " Nvim makes aucmd_win the last window 3780 " au BufEnter * if expand('<afile>') == 'one.txt' | 1close | endif 3781 au BufEnter * if expand('<afile>') == 'one.txt' | close | endif 3782 augroup END 3783 3784 call assert_fails('doautoall BufEnter', 'E813:') 3785 3786 augroup aucmd_win_test2 3787 au! 3788 augroup END 3789 augroup! aucmd_win_test2 3790 %bw! 3791 endfunc 3792 3793 " Test for trying to close the tab that has the temporary window for exeucing 3794 " an autocmd. 3795 func Test_close_autocmd_tab() 3796 edit one.txt 3797 tabnew two.txt 3798 augroup aucmd_win_test 3799 au! 3800 au BufEnter * if expand('<afile>') == 'one.txt' | tabfirst | tabonly | endif 3801 augroup END 3802 3803 call assert_fails('doautoall BufEnter', 'E813:') 3804 3805 tabonly 3806 augroup aucmd_win_test 3807 au! 3808 augroup END 3809 augroup! aucmd_win_test 3810 %bwipe! 3811 endfunc 3812 3813 func Test_Visual_doautoall_redraw() 3814 call setline(1, ['a', 'b']) 3815 new 3816 wincmd p 3817 call feedkeys("G\<C-V>", 'txn') 3818 autocmd User Explode ++once redraw 3819 doautoall User Explode 3820 %bwipe! 3821 endfunc 3822 3823 func Test_get_Visual_selection_in_curbuf_autocmd() 3824 call Ntest_override('starting', 1) 3825 new 3826 autocmd OptionSet list let b:text = getregion(getpos('.'), getpos('v')) 3827 call setline(1, 'foo bar baz') 3828 3829 normal! gg0fbvtb 3830 setlocal list 3831 call assert_equal(['bar '], b:text) 3832 exe "normal! \<Esc>" 3833 3834 normal! v0 3835 call setbufvar('%', '&list', v:false) 3836 call assert_equal(['foo bar '], b:text) 3837 exe "normal! \<Esc>" 3838 3839 autocmd! OptionSet list 3840 bwipe! 3841 call Ntest_override('starting', 0) 3842 endfunc 3843 3844 " This was using freed memory. 3845 func Test_BufNew_arglocal() 3846 arglocal 3847 au BufNew * arglocal 3848 call assert_fails('drop xx', 'E1156:') 3849 3850 au! BufNew 3851 endfunc 3852 3853 func Test_autocmd_closes_window() 3854 au BufNew,BufWinLeave * e %e 3855 file yyy 3856 au BufNew,BufWinLeave * ball 3857 n xxx 3858 3859 %bwipe 3860 au! BufNew 3861 au! BufWinLeave 3862 endfunc 3863 3864 func Test_autocmd_quit_psearch() 3865 sn aa bb 3866 augroup aucmd_win_test 3867 au! 3868 au BufEnter,BufLeave,BufNew,WinEnter,WinLeave,WinNew * if winnr('$') > 1 | q | endif 3869 augroup END 3870 ps / 3871 3872 augroup aucmd_win_test 3873 au! 3874 augroup END 3875 new 3876 pclose 3877 endfunc 3878 3879 " Fuzzer found some strange combination that caused a crash. 3880 func Test_autocmd_normal_mess() 3881 " For unknown reason this hangs on MS-Windows 3882 CheckNotMSWindows 3883 3884 augroup aucmd_normal_test 3885 au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc 3886 augroup END 3887 " Nvim has removed :open 3888 " call assert_fails('o4', 'E1159:') 3889 call assert_fails('e4', 'E1159:') 3890 silent! H 3891 call assert_fails('e xx', 'E1159:') 3892 normal G 3893 3894 augroup aucmd_normal_test 3895 au! 3896 augroup END 3897 endfunc 3898 3899 func Test_autocmd_closing_cmdwin() 3900 " For unknown reason this hangs on MS-Windows 3901 CheckNotMSWindows 3902 3903 au BufWinLeave * nested q 3904 call assert_fails("norm 7q?\n", 'E855:') 3905 3906 au! BufWinLeave 3907 new 3908 only 3909 endfunc 3910 3911 func Test_autocmd_vimgrep() 3912 augroup aucmd_vimgrep 3913 au QuickfixCmdPre,BufNew,BufReadCmd * sb 3914 " Nvim makes aucmd_win the last window 3915 " au QuickfixCmdPre,BufNew,BufReadCmd * q9 3916 au QuickfixCmdPre,BufNew,BufReadCmd * exe 'q' .. (winnr('$') - (win_gettype(winnr('$')) == 'autocmd')) 3917 augroup END 3918 call assert_fails('lv ?a? foo', 'E926:') 3919 3920 augroup aucmd_vimgrep 3921 au! 3922 augroup END 3923 endfunc 3924 3925 func Test_closing_autocmd_window() 3926 let lines =<< trim END 3927 edit Xa.txt 3928 tabnew Xb.txt 3929 autocmd BufEnter Xa.txt unhide 1 3930 doautoall BufEnter 3931 END 3932 call CheckScriptFailure(lines, 'E814:') 3933 au! BufEnter 3934 bwipe Xa.txt 3935 bwipe Xb.txt 3936 endfunc 3937 3938 func Test_switch_window_in_autocmd_window() 3939 edit Xa.txt 3940 tabnew Xb.txt 3941 autocmd BufEnter Xa.txt wincmd w 3942 doautoall BufEnter 3943 au! BufEnter 3944 bwipe Xa.txt 3945 call assert_false(bufexists('Xa.txt')) 3946 bwipe Xb.txt 3947 call assert_false(bufexists('Xb.txt')) 3948 endfunc 3949 3950 " Test that using the autocommand window doesn't change current directory. 3951 func Test_autocmd_window_cwd() 3952 let saveddir = getcwd() 3953 call mkdir('Xcwd/a/b/c/d', 'pR') 3954 3955 new Xa.txt 3956 tabnew 3957 new Xb.txt 3958 3959 tabprev 3960 cd Xcwd 3961 call assert_match('/Xcwd$', getcwd()) 3962 call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd'))) 3963 3964 autocmd BufEnter Xb.txt lcd ./a/b/c/d 3965 doautoall BufEnter 3966 au! BufEnter 3967 call assert_match('/Xcwd$', getcwd()) 3968 call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd'))) 3969 3970 tabnext 3971 cd ./a 3972 tcd ./b 3973 lcd ./c 3974 call assert_match('/Xcwd/a/b/c$', getcwd()) 3975 call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd'))) 3976 3977 autocmd BufEnter Xa.txt call assert_match('Xcwd/a/b/c$', getcwd()) 3978 doautoall BufEnter 3979 au! BufEnter 3980 call assert_match('/Xcwd/a/b/c$', getcwd()) 3981 call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd'))) 3982 bwipe! 3983 call assert_match('/Xcwd/a/b$', getcwd()) 3984 call assert_match('\[tabpage\] .*/Xcwd/a/b$', trim(execute('verbose pwd'))) 3985 bwipe! 3986 call assert_match('/Xcwd/a$', getcwd()) 3987 call assert_match('\[global\] .*/Xcwd/a$', trim(execute('verbose pwd'))) 3988 bwipe! 3989 3990 call chdir(saveddir) 3991 endfunc 3992 3993 func Test_bufwipeout_changes_window() 3994 " This should not crash, but we don't have any expectations about what 3995 " happens, changing window in BufWipeout has unpredictable results. 3996 tabedit 3997 let g:window_id = win_getid() 3998 topleft new 3999 setlocal bufhidden=wipe 4000 autocmd BufWipeout <buffer> call win_gotoid(g:window_id) 4001 tabprevious 4002 +tabclose 4003 4004 unlet g:window_id 4005 au! BufWipeout 4006 %bwipe! 4007 endfunc 4008 4009 func Test_autocmd_prevent_buf_wipe() 4010 " Xa must be the first buffer so that win_close_othertab() puts it in 4011 " another window, which causes wiping the buffer to fail. 4012 %bwipe! 4013 4014 file Xa 4015 call setline(1, 'foo') 4016 setlocal bufhidden=wipe 4017 tabnew Xb 4018 setlocal bufhidden=wipe 4019 autocmd BufUnload Xa ++once ++nested tabonly 4020 autocmd BufWinLeave Xb ++once tabnext 4021 tabfirst 4022 4023 edit! Xc 4024 call assert_equal('Xc', bufname('%')) 4025 tabnext 4026 call assert_equal('Xa', bufname('%')) 4027 call assert_equal("\n\"Xa\" --No lines in buffer--", execute('file')) 4028 4029 %bwipe! 4030 endfunc 4031 4032 func Test_v_event_readonly() 4033 autocmd CompleteChanged * let v:event.width = 0 4034 call assert_fails("normal! i\<C-X>\<C-V>", 'E46:') 4035 au! CompleteChanged 4036 4037 autocmd DirChangedPre * let v:event.directory = '' 4038 call assert_fails('cd .', 'E46:') 4039 au! DirChangedPre 4040 4041 autocmd ModeChanged * let v:event.new_mode = '' 4042 call assert_fails('normal! cc', 'E46:') 4043 au! ModeChanged 4044 4045 autocmd TextYankPost * let v:event.operator = '' 4046 call assert_fails('normal! yy', 'E46:') 4047 au! TextYankPost 4048 endfunc 4049 4050 " Test for ModeChanged pattern 4051 func Test_mode_changes() 4052 let g:index = 0 4053 let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'i', 'ix', 'i', 'ic', 'i', 'n', 'no', 'noV', 'n', 'V', 'v', 's', 'n'] 4054 func! TestMode() 4055 call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode")) 4056 call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode")) 4057 call assert_equal(mode(1), get(v:event, "new_mode")) 4058 let g:index += 1 4059 endfunc 4060 4061 au ModeChanged * :call TestMode() 4062 let g:n_to_any = 0 4063 au ModeChanged n:* let g:n_to_any += 1 4064 call feedkeys("i\<esc>vVca\<CR>\<C-X>\<C-L>\<esc>ggdV\<MouseMove>G", 'tnix') 4065 4066 let g:V_to_v = 0 4067 au ModeChanged V:v let g:V_to_v += 1 4068 call feedkeys("Vv\<C-G>\<esc>", 'tnix') 4069 call assert_equal(len(filter(g:mode_seq[1:], {idx, val -> val == 'n'})), g:n_to_any) 4070 call assert_equal(1, g:V_to_v) 4071 call assert_equal(len(g:mode_seq) - 1, g:index) 4072 4073 let g:n_to_i = 0 4074 au ModeChanged n:i let g:n_to_i += 1 4075 let g:n_to_niI = 0 4076 au ModeChanged i:niI let g:n_to_niI += 1 4077 let g:niI_to_i = 0 4078 au ModeChanged niI:i let g:niI_to_i += 1 4079 let g:nany_to_i = 0 4080 au ModeChanged n*:i let g:nany_to_i += 1 4081 let g:i_to_n = 0 4082 au ModeChanged i:n let g:i_to_n += 1 4083 let g:nori_to_any = 0 4084 au ModeChanged [ni]:* let g:nori_to_any += 1 4085 let g:i_to_any = 0 4086 au ModeChanged i:* let g:i_to_any += 1 4087 let g:index = 0 4088 let g:mode_seq = ['n', 'i', 'niI', 'i', 'n'] 4089 call feedkeys("a\<C-O>l\<esc>", 'tnix') 4090 call assert_equal(len(g:mode_seq) - 1, g:index) 4091 call assert_equal(1, g:n_to_i) 4092 call assert_equal(1, g:n_to_niI) 4093 call assert_equal(1, g:niI_to_i) 4094 call assert_equal(2, g:nany_to_i) 4095 call assert_equal(1, g:i_to_n) 4096 call assert_equal(2, g:i_to_any) 4097 call assert_equal(3, g:nori_to_any) 4098 4099 if has('terminal') 4100 let g:mode_seq += ['c', 'n', 't', 'nt', 'c', 'nt', 'n'] 4101 call feedkeys(":term\<CR>\<C-W>N:bd!\<CR>", 'tnix') 4102 call assert_equal(len(g:mode_seq) - 1, g:index) 4103 call assert_equal(1, g:n_to_i) 4104 call assert_equal(1, g:n_to_niI) 4105 call assert_equal(1, g:niI_to_i) 4106 call assert_equal(2, g:nany_to_i) 4107 call assert_equal(1, g:i_to_n) 4108 call assert_equal(2, g:i_to_any) 4109 call assert_equal(5, g:nori_to_any) 4110 endif 4111 4112 let g:n_to_c = 0 4113 au ModeChanged n:c let g:n_to_c += 1 4114 let g:c_to_n = 0 4115 au ModeChanged c:n let g:c_to_n += 1 4116 let g:mode_seq += ['c', 'n', 'c', 'n'] 4117 call feedkeys("q:\<C-C>\<Esc>", 'tnix') 4118 call assert_equal(len(g:mode_seq) - 1, g:index) 4119 call assert_equal(2, g:n_to_c) 4120 call assert_equal(2, g:c_to_n) 4121 4122 let g:n_to_v = 0 4123 au ModeChanged n:v let g:n_to_v += 1 4124 let g:v_to_n = 0 4125 au ModeChanged v:n let g:v_to_n += 1 4126 let g:mode_seq += ['v', 'n'] 4127 call feedkeys("v\<C-C>", 'tnix') 4128 call assert_equal(len(g:mode_seq) - 1, g:index) 4129 call assert_equal(1, g:n_to_v) 4130 call assert_equal(1, g:v_to_n) 4131 4132 let g:mode_seq += ['c', 'cr', 'c', 'cr', 'n'] 4133 call feedkeys(":\<Insert>\<Insert>\<Insert>\<CR>", 'tnix') 4134 call assert_equal(len(g:mode_seq) - 1, g:index) 4135 4136 au! ModeChanged 4137 delfunc TestMode 4138 unlet! g:mode_seq 4139 unlet! g:index 4140 unlet! g:n_to_any 4141 unlet! g:V_to_v 4142 unlet! g:n_to_i 4143 unlet! g:n_to_niI 4144 unlet! g:niI_to_i 4145 unlet! g:nany_to_i 4146 unlet! g:i_to_n 4147 unlet! g:nori_to_any 4148 unlet! g:i_to_any 4149 unlet! g:n_to_c 4150 unlet! g:c_to_n 4151 unlet! g:n_to_v 4152 unlet! g:v_to_n 4153 endfunc 4154 4155 func Test_recursive_ModeChanged() 4156 au! ModeChanged * norm 0u 4157 sil! norm 4158 au! ModeChanged 4159 endfunc 4160 4161 func Test_ModeChanged_starts_visual() 4162 " This was triggering ModeChanged before setting VIsual, causing a crash. 4163 au! ModeChanged * norm 0u 4164 sil! norm 4165 4166 au! ModeChanged 4167 endfunc 4168 4169 func Test_noname_autocmd() 4170 augroup test_noname_autocmd_group 4171 autocmd! 4172 autocmd BufEnter * call add(s:li, ["BufEnter", expand("<afile>")]) 4173 autocmd BufDelete * call add(s:li, ["BufDelete", expand("<afile>")]) 4174 autocmd BufLeave * call add(s:li, ["BufLeave", expand("<afile>")]) 4175 autocmd BufUnload * call add(s:li, ["BufUnload", expand("<afile>")]) 4176 autocmd BufWipeout * call add(s:li, ["BufWipeout", expand("<afile>")]) 4177 augroup END 4178 4179 let s:li = [] 4180 edit foo 4181 call assert_equal([['BufUnload', ''], ['BufDelete', ''], ['BufWipeout', ''], ['BufEnter', 'foo']], s:li) 4182 4183 au! test_noname_autocmd_group 4184 augroup! test_noname_autocmd_group 4185 endfunc 4186 4187 func Test_autocmd_split_dummy() 4188 " Autocommand trying to split a window containing a dummy buffer. 4189 auto BufReadPre * exe "sbuf " .. expand("<abuf>") 4190 " Avoid the "W11" prompt 4191 au FileChangedShell * let v:fcs_choice = 'reload' 4192 func Xautocmd_changelist() 4193 cal writefile(['Xtestfile2:4:4'], 'Xerr') 4194 edit Xerr 4195 lex 'Xtestfile2:4:4' 4196 endfunc 4197 call Xautocmd_changelist() 4198 " Should get E86, but it doesn't always happen (timing?) 4199 silent! call Xautocmd_changelist() 4200 4201 au! BufReadPre 4202 au! FileChangedShell 4203 delfunc Xautocmd_changelist 4204 bwipe! Xerr 4205 call delete('Xerr') 4206 endfunc 4207 4208 " This was crashing because there was only one window to execute autocommands 4209 " in. 4210 func Test_autocmd_nested_setbufvar() 4211 CheckFeature python3 4212 4213 set hidden 4214 edit Xaaa 4215 edit Xbbb 4216 call setline(1, 'bar') 4217 enew 4218 au BufWriteCmd Xbbb ++nested call setbufvar('Xaaa', '&ft', 'foo') | bw! Xaaa 4219 au FileType foo call py3eval('vim.current.buffer.options["cindent"]') 4220 wall 4221 4222 au! BufWriteCmd 4223 au! FileType foo 4224 set nohidden 4225 call delete('Xaaa') 4226 call delete('Xbbb') 4227 %bwipe! 4228 endfunc 4229 4230 func SetupVimTest_shm() 4231 let g:bwe = [] 4232 let g:brp = [] 4233 set shortmess-=l 4234 messages clear 4235 4236 let dirname='XVimTestSHM' 4237 call mkdir(dirname, 'R') 4238 call writefile(['test'], dirname .. '/1') 4239 call writefile(['test'], dirname .. '/2') 4240 call writefile(['test'], dirname .. '/3') 4241 4242 augroup test 4243 autocmd! 4244 autocmd BufWinEnter * call add(g:bwe, $'BufWinEnter: {expand('<amatch>')}') 4245 autocmd BufReadPost * call add(g:brp, $'BufReadPost: {expand('<amatch>')}') 4246 augroup END 4247 4248 call setqflist([ 4249 \ {'filename': dirname .. '/1', 'lnum': 1, 'col': 1, 'text': 'test', 'vcol': 0}, 4250 \ {'filename': dirname .. '/2', 'lnum': 1, 'col': 1, 'text': 'test', 'vcol': 0}, 4251 \ {'filename': dirname .. '/3', 'lnum': 1, 'col': 1, 'text': 'test', 'vcol': 0} 4252 \ ]) 4253 cdo! substitute/test/TEST 4254 4255 " clean up 4256 noa enew! 4257 set shortmess&vim 4258 augroup test 4259 autocmd! 4260 augroup END 4261 augroup! test 4262 endfunc 4263 4264 func Test_autocmd_shortmess() 4265 CheckNotMSWindows 4266 4267 call SetupVimTest_shm() 4268 let output = execute(':mess')->split('\n') 4269 4270 let info = copy(output)->filter({idx, val -> val =~# '\d of 3'} ) 4271 let bytes = copy(output)->filter({idx, val -> val =~# 'bytes'} ) 4272 4273 " We test the following here: 4274 " BufReadPost should have been triggered 3 times, once per file 4275 " BufWinEnter should have been triggered 3 times, once per file 4276 " FileInfoMessage should have been shown 3 times, regardless of shm option 4277 " "(x of 3)" message from :cnext has been shown 3 times 4278 4279 call assert_equal(3, g:brp->len()) 4280 call assert_equal(3, g:bwe->len()) 4281 call assert_equal(3, info->len()) 4282 call assert_equal(3, bytes->len()) 4283 4284 delfunc SetupVimTest_shm 4285 endfunc 4286 4287 func Test_autocmd_invalidates_undo_on_textchanged() 4288 CheckRunVimInTerminal 4289 let script =<< trim END 4290 set hidden 4291 " create quickfix list (at least 2 lines to move line) 4292 vimgrep /u/j % 4293 4294 " enter quickfix window 4295 cwindow 4296 4297 " set modifiable 4298 setlocal modifiable 4299 4300 " set autocmd to clear quickfix list 4301 4302 autocmd! TextChanged <buffer> call setqflist([]) 4303 " move line 4304 move+1 4305 END 4306 call writefile(script, 'XTest_autocmd_invalidates_undo_on_textchanged', 'D') 4307 let buf = RunVimInTerminal('XTest_autocmd_invalidates_undo_on_textchanged', {'rows': 20}) 4308 call term_sendkeys(buf, ":so %\<cr>") 4309 call term_sendkeys(buf, "G") 4310 call WaitForAssert({-> assert_match('^XTest_autocmd_invalidates_undo_on_textchanged\s*$', term_getline(buf, 20))}, 1000) 4311 4312 call StopVimInTerminal(buf) 4313 endfunc 4314 4315 func Test_autocmd_creates_new_window_on_bufleave() 4316 e a.txt 4317 e b.txt 4318 setlocal bufhidden=wipe 4319 autocmd BufLeave <buffer> diffsplit c.txt 4320 bn 4321 call assert_equal(1, winnr('$')) 4322 call assert_equal('a.txt', bufname('%')) 4323 bw a.txt 4324 bw c.txt 4325 endfunc 4326 4327 " Ensure `expected` was just recently written as a Vim session 4328 func s:assert_session_path(expected) 4329 call assert_equal(a:expected, v:this_session) 4330 endfunc 4331 4332 " Check for `expected` after a session is written to-disk. 4333 func s:watch_for_session_path(expected) 4334 execute 'autocmd SessionWritePost * ++once execute "call s:assert_session_path(\"' 4335 \ . a:expected 4336 \ . '\")"' 4337 endfunc 4338 4339 " Ensure v:this_session gets the full session path, if explicitly stated 4340 func Test_explicit_session_absolute_path() 4341 %bwipeout! 4342 4343 let directory = getcwd() 4344 4345 let v:this_session = "" 4346 let name = "some_file.vim" 4347 let expected = fnamemodify(name, ":p") 4348 call s:watch_for_session_path(expected) 4349 execute "mksession! " .. expected 4350 4351 call delete(expected) 4352 endfunc 4353 4354 " Ensure v:this_session gets the full session path, if explicitly stated 4355 func Test_explicit_session_relative_path() 4356 %bwipeout! 4357 4358 let directory = getcwd() 4359 4360 let v:this_session = "" 4361 let name = "some_file.vim" 4362 let expected = fnamemodify(name, ":p") 4363 call s:watch_for_session_path(expected) 4364 execute "mksession! " .. name 4365 4366 call delete(expected) 4367 endfunc 4368 4369 " Ensure v:this_session gets the full session path, if not specified 4370 func Test_implicit_session() 4371 %bwipeout! 4372 4373 let directory = getcwd() 4374 4375 let v:this_session = "" 4376 let expected = fnamemodify("Session.vim", ":p") 4377 call s:watch_for_session_path(expected) 4378 mksession! 4379 4380 call delete(expected) 4381 endfunc 4382 4383 " Test TextChangedI and TextChanged 4384 func Test_Changed_ChangedI() 4385 " Run this test in a terminal because it requires running the main loop. 4386 " Don't use CheckRunVimInTerminal as that will skip the test on Windows. 4387 CheckFeature terminal 4388 CheckNotGui 4389 " Starting a terminal to run Vim is always considered flaky. 4390 let g:test_is_flaky = 1 4391 4392 call writefile(['one', 'two', 'three'], 'XTextChangedI2', 'D') 4393 let before =<< trim END 4394 set ttimeout ttimeoutlen=10 4395 let [g:autocmd_n, g:autocmd_i] = ['',''] 4396 4397 func TextChangedAutocmd(char) 4398 let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick 4399 call writefile([$'{g:autocmd_n},{g:autocmd_i}'], 'XTextChangedI3') 4400 endfunc 4401 4402 au TextChanged <buffer> :call TextChangedAutocmd('N') 4403 au TextChangedI <buffer> :call TextChangedAutocmd('I') 4404 4405 nnoremap <CR> o<Esc> 4406 autocmd SafeState * ++once call writefile([''], 'XTextChangedI3') 4407 END 4408 4409 call writefile(before, 'Xinit', 'D') 4410 let buf = term_start( 4411 \ GetVimCommandCleanTerm() .. '-n -S Xinit XTextChangedI2', 4412 \ {'term_rows': 10}) 4413 call assert_equal('running', term_getstatus(buf)) 4414 call WaitForAssert({-> assert_true(filereadable('XTextChangedI3'))}) 4415 defer delete('XTextChangedI3') 4416 call WaitForAssert({-> assert_equal([''], readfile('XTextChangedI3'))}) 4417 4418 " TextChanged should trigger if a mapping enters and leaves Insert mode. 4419 call term_sendkeys(buf, "\<CR>") 4420 call WaitForAssert({-> assert_equal('N4,', readfile('XTextChangedI3')->join("\n"))}) 4421 4422 call term_sendkeys(buf, "i") 4423 call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) 4424 call WaitForAssert({-> assert_equal('N4,', readfile('XTextChangedI3')->join("\n"))}) 4425 " TextChangedI should trigger if change is done in Insert mode. 4426 call term_sendkeys(buf, "f") 4427 call WaitForAssert({-> assert_equal('N4,I5', readfile('XTextChangedI3')->join("\n"))}) 4428 call term_sendkeys(buf, "o") 4429 call WaitForAssert({-> assert_equal('N4,I6', readfile('XTextChangedI3')->join("\n"))}) 4430 call term_sendkeys(buf, "o") 4431 call WaitForAssert({-> assert_equal('N4,I7', readfile('XTextChangedI3')->join("\n"))}) 4432 " TextChanged shouldn't trigger when leaving Insert mode and TextChangedI 4433 " has been triggered. 4434 call term_sendkeys(buf, "\<Esc>") 4435 call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) 4436 call WaitForAssert({-> assert_equal('N4,I7', readfile('XTextChangedI3')->join("\n"))}) 4437 4438 " TextChanged should trigger if change is done in Normal mode. 4439 call term_sendkeys(buf, "yyp") 4440 call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) 4441 4442 " TextChangedI shouldn't trigger if change isn't done in Insert mode. 4443 call term_sendkeys(buf, "i") 4444 call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) 4445 call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) 4446 call term_sendkeys(buf, "\<Esc>") 4447 call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) 4448 call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) 4449 4450 " TextChangedI should trigger if change is a mix of Normal and Insert modes. 4451 func! s:validate_mixed_textchangedi(buf, keys) 4452 let buf = a:buf 4453 call term_sendkeys(buf, "ifoo") 4454 call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) 4455 call term_sendkeys(buf, "\<Esc>") 4456 call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) 4457 call term_sendkeys(buf, ":let [g:autocmd_n, g:autocmd_i] = ['', '']\<CR>") 4458 call writefile([], 'XTextChangedI3') 4459 call term_sendkeys(buf, a:keys) 4460 call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) 4461 call WaitForAssert({-> assert_match('^,I\d\+', readfile('XTextChangedI3')->join("\n"))}) 4462 call term_sendkeys(buf, "\<Esc>") 4463 call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) 4464 call WaitForAssert({-> assert_match('^,I\d\+', readfile('XTextChangedI3')->join("\n"))}) 4465 endfunc 4466 4467 call s:validate_mixed_textchangedi(buf, "o") 4468 call s:validate_mixed_textchangedi(buf, "O") 4469 call s:validate_mixed_textchangedi(buf, "ciw") 4470 call s:validate_mixed_textchangedi(buf, "cc") 4471 call s:validate_mixed_textchangedi(buf, "C") 4472 call s:validate_mixed_textchangedi(buf, "s") 4473 call s:validate_mixed_textchangedi(buf, "S") 4474 4475 " clean up 4476 bwipe! 4477 endfunc 4478 4479 " Test that filetype detection still works when SwapExists autocommand sets 4480 " filetype in another buffer. 4481 func Test_SwapExists_set_other_buf_filetype() 4482 let lines =<< trim END 4483 set nocompatible directory=. 4484 filetype on 4485 4486 let g:buf = bufnr() 4487 new 4488 4489 func SwapExists() 4490 let v:swapchoice = 'o' 4491 call setbufvar(g:buf, '&filetype', 'text') 4492 endfunc 4493 4494 func SafeState() 4495 edit <script> 4496 redir! > XftSwapExists.out 4497 set readonly? filetype? 4498 redir END 4499 qall! 4500 endfunc 4501 4502 autocmd SwapExists * ++nested call SwapExists() 4503 autocmd SafeState * ++nested ++once call SafeState() 4504 END 4505 call writefile(lines, 'XftSwapExists.vim', 'D') 4506 4507 new XftSwapExists.vim 4508 if RunVim('', '', ' -S XftSwapExists.vim') 4509 call assert_equal( 4510 \ ['', ' readonly', ' filetype=vim'], 4511 \ readfile('XftSwapExists.out')) 4512 call delete('XftSwapExists.out') 4513 endif 4514 4515 bwipe! 4516 endfunc 4517 4518 " Test that file is not marked as modified when SwapExists autocommand sets 4519 " 'modified' in another buffer. 4520 func Test_SwapExists_set_other_buf_modified() 4521 let lines =<< trim END 4522 set nocompatible directory=. 4523 4524 let g:buf = bufnr() 4525 new 4526 4527 func SwapExists() 4528 let v:swapchoice = 'o' 4529 call setbufvar(g:buf, '&modified', 1) 4530 endfunc 4531 4532 func SafeState() 4533 edit <script> 4534 redir! > XmodSwapExists.out 4535 set readonly? modified? 4536 redir END 4537 qall! 4538 endfunc 4539 4540 autocmd SwapExists * ++nested call SwapExists() 4541 autocmd SafeState * ++nested ++once call SafeState() 4542 END 4543 call writefile(lines, 'XmodSwapExists.vim', 'D') 4544 4545 new XmodSwapExists.vim 4546 if RunVim('', '', ' -S XmodSwapExists.vim') 4547 call assert_equal( 4548 \ ['', ' readonly', 'nomodified'], 4549 \ readfile('XmodSwapExists.out')) 4550 call delete('XmodSwapExists.out') 4551 endif 4552 4553 bwipe! 4554 endfunc 4555 4556 func Test_BufEnter_botline() 4557 set hidden 4558 call writefile(range(10), 'Xxx1', 'D') 4559 call writefile(range(20), 'Xxx2', 'D') 4560 edit Xxx1 4561 edit Xxx2 4562 au BufEnter Xxx1 call assert_true(line('w$') > 1) 4563 edit Xxx1 4564 4565 bwipe! Xxx1 4566 bwipe! Xxx2 4567 au! BufEnter Xxx1 4568 set hidden&vim 4569 endfunc 4570 4571 " those commands caused null pointer access, see #15464 4572 func Test_WinNewPre_crash() 4573 defer CleanUpTestAuGroup() 4574 let _cmdheight=&cmdheight 4575 augroup testing 4576 au! 4577 autocmd WinNewPre * redraw 4578 augroup END 4579 tabnew 4580 tabclose 4581 augroup testing 4582 au! 4583 autocmd WinNewPre * wincmd t 4584 augroup END 4585 tabnew 4586 tabclose 4587 augroup testing 4588 au! 4589 autocmd WinNewPre * wincmd b 4590 augroup END 4591 tabnew 4592 tabclose 4593 augroup testing 4594 au! 4595 autocmd WinNewPre * set cmdheight+=1 4596 augroup END 4597 tabnew 4598 tabclose 4599 let &cmdheight=_cmdheight 4600 endfunc 4601 4602 4603 " This was using freed memory 4604 func Test_autocmd_BufWinLeave_with_vsp() 4605 new 4606 let fname = 'XXXBufWinLeaveUAF.txt' 4607 let dummy = 'XXXDummy.txt' 4608 call writefile([], fname) 4609 call writefile([], dummy) 4610 defer delete(fname) 4611 defer delete(dummy) 4612 exe "e " fname 4613 vsp 4614 augroup testing 4615 exe 'au BufWinLeave' fname 'e' dummy 4616 \ '| call assert_fails(''vsp' fname ''', ''E1546:'')' 4617 augroup END 4618 bw 4619 call CleanUpTestAuGroup() 4620 exe "bw! " .. dummy 4621 endfunc 4622 4623 func Test_OptionSet_cmdheight() 4624 set mouse=a laststatus=2 4625 au OptionSet cmdheight :let &l:ch = v:option_new 4626 4627 resize -1 4628 call assert_equal(2, &l:ch) 4629 resize +1 4630 call assert_equal(1, &l:ch) 4631 4632 call Ntest_setmouse(&lines - 1, 1) 4633 call feedkeys("\<LeftMouse>", 'xt') 4634 call Ntest_setmouse(&lines - 2, 1) 4635 call feedkeys("\<LeftDrag>", 'xt') 4636 call assert_equal(2, &l:ch) 4637 call feedkeys("\<LeftRelease>", 'xt') 4638 4639 tabnew | resize +1 4640 call assert_equal(1, &l:ch) 4641 tabfirst 4642 call assert_equal(2, &l:ch) 4643 4644 tabonly 4645 set cmdheight& mouse& laststatus& 4646 endfunc 4647 4648 func Test_eventignorewin() 4649 defer CleanUpTestAuGroup() 4650 augroup testing 4651 au WinEnter * :call add(g:evs, ["WinEnter", expand("<afile>")]) 4652 au WinLeave * :call add(g:evs, ["WinLeave", expand("<afile>")]) 4653 au BufWinEnter * :call add(g:evs, ["BufWinEnter", expand("<afile>")]) 4654 augroup END 4655 4656 let g:evs = [] 4657 set eventignorewin=WinLeave,WinEnter 4658 split foo 4659 call assert_equal([['BufWinEnter', 'foo']], g:evs) 4660 set eventignorewin=all 4661 edit bar 4662 call assert_equal([['BufWinEnter', 'foo']], g:evs) 4663 set eventignorewin= 4664 wincmd w 4665 call assert_equal([['BufWinEnter', 'foo'], ['WinLeave', 'bar']], g:evs) 4666 4667 only! 4668 %bwipe! 4669 set eventignorewin& 4670 unlet g:evs 4671 endfunc 4672 4673 func Test_WinScrolled_Resized_eiw() 4674 CheckRunVimInTerminal 4675 4676 let lines =<< trim END 4677 call setline(1, ['foo']->repeat(32)) 4678 set eventignorewin=WinScrolled,WinResized 4679 split 4680 let [g:afile,g:resized,g:scrolled] = ['none',0,0] 4681 au WinScrolled * let [g:afile,g:scrolled] = [expand('<afile>'),g:scrolled+1] 4682 au WinResized * let [g:afile,g:resized] = [expand('<afile>'),g:resized+1] 4683 END 4684 call writefile(lines, 'Xtest_winscrolled_eiw', 'D') 4685 let buf = RunVimInTerminal('-S Xtest_winscrolled_eiw', {'rows': 10}) 4686 4687 " Both windows are ignoring resize events 4688 call term_sendkeys(buf, "\<C-W>-") 4689 call TermWait(buf) 4690 call term_sendkeys(buf, ":echo g:afile g:resized g:scrolled\<CR>") 4691 call WaitForAssert({-> assert_equal('none 0 0', term_getline(buf, 10))}, 1000) 4692 4693 " And scroll events 4694 call term_sendkeys(buf, "Ggg") 4695 call TermWait(buf) 4696 call term_sendkeys(buf, ":echo g:afile g:resized g:scrolled\<CR>") 4697 call WaitForAssert({-> assert_equal('none 0 0', term_getline(buf, 10))}, 1000) 4698 4699 " Un-ignore events in second window, make first window current and resize 4700 call term_sendkeys(buf, ":set eventignorewin=\<CR>\<C-W>w\<C-W>+") 4701 call TermWait(buf) 4702 call term_sendkeys(buf, ":echo win_getid() g:afile g:resized g:scrolled\<CR>") 4703 call WaitForAssert({-> assert_equal('1000 1001 1 1', term_getline(buf, 10))}, 1000) 4704 4705 call StopVimInTerminal(buf) 4706 endfunc 4707 4708 " Test that TabClosedPre and TabClosed are triggered when closing a tab. 4709 func Test_autocmd_TabClosedPre() 4710 augroup testing 4711 au TabClosedPre * call add(g:tabpagenr_pre, t:testvar) 4712 au TabClosed * call add(g:tabpagenr_post, t:testvar) 4713 augroup END 4714 4715 " Test 'tabclose' triggering 4716 let g:tabpagenr_pre = [] 4717 let g:tabpagenr_post = [] 4718 let t:testvar = 1 4719 tabnew 4720 let t:testvar = 2 4721 tabnew 4722 let t:testvar = 3 4723 tabnew 4724 let t:testvar = 4 4725 tabnext 4726 tabclose 4727 tabclose 4728 tabclose 4729 call assert_equal([1, 2, 3], g:tabpagenr_pre) 4730 call assert_equal([2, 3, 4], g:tabpagenr_post) 4731 4732 " Test 'tabclose {count}' triggering 4733 let g:tabpagenr_pre = [] 4734 let g:tabpagenr_post = [] 4735 let t:testvar = 1 4736 tabnew 4737 let t:testvar = 2 4738 tabnew 4739 let t:testvar = 3 4740 tabclose 2 4741 tabclose 2 4742 call assert_equal([2, 3], g:tabpagenr_pre) 4743 call assert_equal([3, 1], g:tabpagenr_post) 4744 4745 " Test 'tabonly' triggering 4746 let g:tabpagenr_pre = [] 4747 let g:tabpagenr_post = [] 4748 let t:testvar = 1 4749 tabnew 4750 let t:testvar = 2 4751 tabonly 4752 call assert_equal([1], g:tabpagenr_pre) 4753 call assert_equal([2], g:tabpagenr_post) 4754 4755 " Test 'q' and 'close' triggering (closing the last window in a tab) 4756 let g:tabpagenr_pre = [] 4757 let g:tabpagenr_post = [] 4758 split 4759 let t:testvar = 1 4760 tabnew 4761 let t:testvar = 2 4762 split 4763 vsplit 4764 tabnew 4765 let t:testvar = 3 4766 tabnext 4767 only 4768 quit 4769 quit 4770 close 4771 close 4772 call assert_equal([1, 2], g:tabpagenr_pre) 4773 call assert_equal([2, 3], g:tabpagenr_post) 4774 4775 " Test failing to close tab page 4776 let g:tabpagenr_pre = [] 4777 let g:tabpagenr_post = [] 4778 let t:testvar = 1 4779 call setline(1, 'foo') 4780 setlocal bufhidden=wipe 4781 tabnew 4782 let t:testvar = 2 4783 tabnew 4784 let t:testvar = 3 4785 call setline(1, 'bar') 4786 setlocal bufhidden=wipe 4787 tabnew 4788 let t:testvar = 4 4789 call setline(1, 'baz') 4790 setlocal bufhidden=wipe 4791 new 4792 call assert_fails('tabclose', 'E445:') 4793 call assert_equal([4], g:tabpagenr_pre) 4794 call assert_equal([], g:tabpagenr_post) 4795 " :tabclose! after failed :tabclose should trigger TabClosedPre again. 4796 tabclose! 4797 call assert_equal([4, 4], g:tabpagenr_pre) 4798 call assert_equal([3], g:tabpagenr_post) 4799 call assert_fails('tabclose', 'E37:') 4800 call assert_equal([4, 4, 3], g:tabpagenr_pre) 4801 call assert_equal([3], g:tabpagenr_post) 4802 " The same for :close! if the tab page only has one window. 4803 close! 4804 call assert_equal([4, 4, 3, 3], g:tabpagenr_pre) 4805 call assert_equal([3, 2], g:tabpagenr_post) 4806 " Also test with :close! after failed :tabonly. 4807 call assert_fails('tabonly', 'E37:') 4808 call assert_equal([4, 4, 3, 3, 1], g:tabpagenr_pre) 4809 call assert_equal([3, 2], g:tabpagenr_post) 4810 tabprevious | close! 4811 call assert_equal([4, 4, 3, 3, 1, 1], g:tabpagenr_pre) 4812 call assert_equal([3, 2, 2], g:tabpagenr_post) 4813 %bwipe! 4814 4815 " Test closing another tab page in BufWinLeave 4816 let g:tabpagenr_pre = [] 4817 let g:tabpagenr_post = [] 4818 split 4819 let t:testvar = 1 4820 tabnew 4821 let t:testvar = 2 4822 tabnew Xsomebuf 4823 let t:testvar = 3 4824 new 4825 autocmd BufWinLeave Xsomebuf ++once ++nested tabclose 1 4826 tabclose 4827 " TabClosedPre should not be triggered for tab page 3 twice. 4828 call assert_equal([3, 1], g:tabpagenr_pre) 4829 " When tab page 1 was closed, tab page 3 was still the current tab page. 4830 call assert_equal([3, 2], g:tabpagenr_post) 4831 %bwipe! 4832 4833 func ClearAutocmdAndCreateTabs() 4834 au! TabClosedPre 4835 bw! 4836 e Z 4837 tabonly 4838 tabnew A 4839 tabnew B 4840 tabnew C 4841 endfunc 4842 4843 func GetTabs() 4844 redir => tabsout 4845 tabs 4846 redir END 4847 let tabsout = substitute(tabsout, '\n', '', 'g') 4848 let tabsout = substitute(tabsout, 'Tab page ', '', 'g') 4849 let tabsout = substitute(tabsout, '#', '', 'g') " Nvim: remove '#' 4850 let tabsout = substitute(tabsout, ' ', '', 'g') 4851 return tabsout 4852 endfunc 4853 4854 call CleanUpTestAuGroup() 4855 4856 " Close tab in TabClosedPre autocmd 4857 call ClearAutocmdAndCreateTabs() 4858 au TabClosedPre * tabclose 4859 call assert_fails('tabclose', 'E1312:') 4860 call ClearAutocmdAndCreateTabs() 4861 au TabClosedPre * tabclose 4862 call assert_fails('tabclose 2', 'E1312:') 4863 call ClearAutocmdAndCreateTabs() 4864 au TabClosedPre * tabclose 1 4865 call assert_fails('tabclose', 'E1312:') 4866 4867 " Close other (all) tabs in TabClosedPre autocmd 4868 call ClearAutocmdAndCreateTabs() 4869 au TabClosedPre * tabonly 4870 call assert_fails('tabclose', 'E1312:') 4871 call ClearAutocmdAndCreateTabs() 4872 au TabClosedPre * tabonly 4873 call assert_fails('tabclose 2', 'E1312:') 4874 call ClearAutocmdAndCreateTabs() 4875 au TabClosedPre * tabclose 4 4876 call assert_fails('tabclose 2', 'E1312:') 4877 4878 " Open new tabs in TabClosedPre autocmd 4879 call ClearAutocmdAndCreateTabs() 4880 au TabClosedPre * tabnew D 4881 call assert_fails('tabclose', 'E1312:') 4882 call ClearAutocmdAndCreateTabs() 4883 au TabClosedPre * tabnew D 4884 call assert_fails('tabclose 1', 'E1312:') 4885 4886 " Moving the tab page in TabClosedPre autocmd 4887 call ClearAutocmdAndCreateTabs() 4888 au TabClosedPre * tabmove 0 4889 tabclose 4890 call assert_equal('1>Z2A3B', GetTabs()) 4891 call ClearAutocmdAndCreateTabs() 4892 au TabClosedPre * tabmove 0 4893 tabclose 1 4894 call assert_equal('1A2B3>C', GetTabs()) 4895 tabonly 4896 call assert_equal('1>C', GetTabs()) 4897 4898 " Switching tab page in TabClosedPre autocmd 4899 call ClearAutocmdAndCreateTabs() 4900 au TabClosedPre * tabnext | e Y 4901 tabclose 4902 call assert_equal('1Y2A3>B', GetTabs()) 4903 call ClearAutocmdAndCreateTabs() 4904 au TabClosedPre * tabnext | e Y 4905 tabclose 1 4906 call assert_equal('1Y2B3>C', GetTabs()) 4907 tabonly 4908 call assert_equal('1>Y', GetTabs()) 4909 4910 " Create new windows in TabClosedPre autocmd 4911 call ClearAutocmdAndCreateTabs() 4912 au TabClosedPre * split | e X| vsplit | e Y | split | e Z 4913 call assert_fails('tabclose', 'E242:') 4914 call ClearAutocmdAndCreateTabs() 4915 au TabClosedPre * new X | new Y | new Z 4916 call assert_fails('tabclose 1', 'E242:') 4917 4918 " Test directly closing the tab page with ':tabclose' 4919 au! 4920 tabonly 4921 bw! 4922 e Z 4923 au TabClosedPre * mksession! 4924 tabnew A 4925 sp 4926 tabclose 4927 source Session.vim 4928 call assert_equal('1Z2>AA', GetTabs()) 4929 4930 " Test directly closing the tab page with ':tabonly' 4931 " Z is closed before A. Hence A overwrites the session. 4932 au! 4933 tabonly 4934 bw! 4935 e Z 4936 au TabClosedPre * mksession! 4937 tabnew A 4938 tabnew B 4939 tabonly 4940 source Session.vim 4941 call assert_equal('1>A2B', GetTabs()) 4942 4943 " Clean up 4944 call delete('Session.vim') 4945 au! 4946 only 4947 tabonly 4948 bw! 4949 delfunc ClearAutocmdAndCreateTabs 4950 delfunc GetTabs 4951 endfunc 4952 4953 " This used to cause heap-use-after-free. 4954 func Run_test_TabClosedPre_wipe_buffer(split_cmds) 4955 file Xa 4956 exe a:split_cmds 4957 autocmd TabClosedPre * ++once tabnext | bwipe! Xa 4958 " Closing window inside TabClosedPre is not allowed. 4959 call assert_fails('tabonly', 'E1312:') 4960 4961 %bwipe! 4962 endfunc 4963 4964 func Test_TabClosedPre_wipe_buffer() 4965 " Test with Xa only in other tab pages. 4966 call Run_test_TabClosedPre_wipe_buffer('split | tab split | tabnew Xb') 4967 " Test with Xa in both current and other tab pages. 4968 call Run_test_TabClosedPre_wipe_buffer('split | tab split | new Xb') 4969 endfunc 4970 4971 func Test_TabClosedPre_mouse() 4972 func MyTabline() 4973 let cnt = tabpagenr('$') 4974 return range(1, cnt)->mapnew({_, n -> $'%{n}X|Close{n}|%X'})->join('') 4975 endfunc 4976 4977 let save_mouse = &mouse 4978 if has('gui') 4979 set guioptions-=e 4980 endif 4981 set mouse=a tabline=%!MyTabline() 4982 4983 func OpenTwoTabPages() 4984 %bwipe! 4985 file Xa | split | split 4986 let g:Xa_bufnr = bufnr() 4987 tabnew Xb | split 4988 let g:Xb_bufnr = bufnr() 4989 redraw! 4990 call assert_match('^|Close1||Close2| *$', Screenline(1)) 4991 call assert_equal(2, tabpagenr('$')) 4992 endfunc 4993 4994 autocmd! TabClosedPre 4995 call OpenTwoTabPages() 4996 let g:autocmd_bufnrs = [] 4997 autocmd TabClosedPre * let g:autocmd_bufnrs += [tabpagebuflist()] 4998 call Ntest_setmouse(1, 2) 4999 call feedkeys("\<LeftMouse>\<LeftRelease>", 'tx') 5000 call assert_equal(1, tabpagenr('$')) 5001 call assert_equal([[g:Xa_bufnr]->repeat(3)], g:autocmd_bufnrs) 5002 call assert_equal([g:Xb_bufnr]->repeat(2), tabpagebuflist()) 5003 5004 call OpenTwoTabPages() 5005 let g:autocmd_bufnrs = [] 5006 autocmd TabClosedPre * call feedkeys("\<LeftRelease>\<LeftMouse>", 'tx') 5007 call Ntest_setmouse(1, 2) 5008 " Closing tab page inside TabClosedPre is not allowed. 5009 call assert_fails('call feedkeys("\<LeftMouse>", "tx")', 'E1312:') 5010 call feedkeys("\<LeftRelease>", 'tx') 5011 5012 autocmd! TabClosedPre 5013 call OpenTwoTabPages() 5014 let g:autocmd_bufnrs = [] 5015 autocmd TabClosedPre * let g:autocmd_bufnrs += [tabpagebuflist()] 5016 call Ntest_setmouse(1, 10) 5017 call feedkeys("\<LeftMouse>\<LeftRelease>", 'tx') 5018 call assert_equal(1, tabpagenr('$')) 5019 call assert_equal([[g:Xb_bufnr]->repeat(2)], g:autocmd_bufnrs) 5020 call assert_equal([g:Xa_bufnr]->repeat(3), tabpagebuflist()) 5021 5022 call OpenTwoTabPages() 5023 let g:autocmd_bufnrs = [] 5024 autocmd TabClosedPre * call feedkeys("\<LeftRelease>\<LeftMouse>", 'tx') 5025 call Ntest_setmouse(1, 10) 5026 " Closing tab page inside TabClosedPre is not allowed. 5027 call assert_fails('call feedkeys("\<LeftMouse>", "tx")', 'E1312:') 5028 call feedkeys("\<LeftRelease>", 'tx') 5029 5030 autocmd! TabClosedPre 5031 %bwipe! 5032 unlet g:Xa_bufnr g:Xb_bufnr g:autocmd_bufnrs 5033 let &mouse = save_mouse 5034 set tabline& guioptions& 5035 delfunc MyTabline 5036 delfunc OpenTwoTabPages 5037 endfunc 5038 5039 func Test_eventignorewin_non_current() 5040 defer CleanUpTestAuGroup() 5041 let s:triggered = '' 5042 augroup testing 5043 " Will set <abuf> to the buffer of the closing window. 5044 autocmd WinClosed * let s:triggered = 'WinClosed' 5045 augroup END 5046 let initial_win = win_getid() 5047 5048 new 5049 let new_buf = bufnr() 5050 " Only set for one of the windows into the new buffer. 5051 setlocal eventignorewin=all 5052 split 5053 setlocal eventignorewin= 5054 let close_winnr = winnr() 5055 5056 " Return to the window where the buffer is non-current. WinClosed should 5057 " trigger as not all windows into new_buf have 'eventignorewin' set for it. 5058 call win_gotoid(initial_win) 5059 call assert_notequal(new_buf, bufnr()) 5060 execute close_winnr 'close' 5061 call assert_equal('WinClosed', s:triggered) 5062 5063 wincmd w 5064 call assert_equal(new_buf, bufnr()) 5065 tab split 5066 setlocal eventignorewin= 5067 let close_winnr = win_getid() 5068 5069 " Ensure that new_buf's window in the other tabpage with 'eventignorewin' 5070 " unset allows WinClosed to run when new_buf is non-current. 5071 call win_gotoid(initial_win) 5072 call assert_notequal(new_buf, bufnr()) 5073 let s:triggered = '' 5074 only! 5075 call assert_equal('WinClosed', s:triggered) 5076 call assert_equal(1, win_findbuf(new_buf)->len()) 5077 5078 " Create an only window to new_buf with 'eventignorewin' set. 5079 tabonly! 5080 execute new_buf 'sbuffer' 5081 setlocal eventignorewin=all 5082 wincmd p 5083 call assert_equal(1, win_findbuf(new_buf)->len()) 5084 call assert_notequal(new_buf, bufnr()) 5085 5086 " Closing a window unrelated to new_buf should not block WinClosed. 5087 split 5088 let s:triggered = '' 5089 close 5090 call assert_equal('WinClosed', s:triggered) 5091 call assert_equal(1, win_findbuf(new_buf)->len()) 5092 5093 " Check WinClosed is blocked when we close the only window to new_buf (that 5094 " has 'eventignorewin' set) while new_buf is non-current. 5095 call assert_notequal(new_buf, bufnr()) 5096 let s:triggered = '' 5097 only! 5098 call assert_equal('', s:triggered) 5099 call assert_equal(0, win_findbuf(new_buf)->len()) 5100 5101 augroup testing 5102 autocmd! 5103 autocmd BufNew * ++once let s:triggered = 'BufNew' 5104 augroup END 5105 5106 " Buffer not shown in a window, 'eventignorewin' should not block (and 5107 " can't even be set for it anyway in this case). 5108 badd foo 5109 call assert_equal('BufNew', s:triggered) 5110 5111 unlet! s:triggered 5112 %bw! 5113 endfunc 5114 5115 func Test_reuse_curbuf_leak() 5116 new bar 5117 let s:bar_buf = bufnr() 5118 augroup testing 5119 autocmd! 5120 autocmd BufDelete * ++once let s:triggered = 1 | execute s:bar_buf 'buffer' 5121 augroup END 5122 enew 5123 let empty_buf = bufnr() 5124 5125 " Old curbuf should be reused, firing BufDelete. As BufDelete changes curbuf, 5126 " reusing the buffer would fail and leak the ffname. 5127 edit foo 5128 call assert_equal(1, s:triggered) 5129 " Wasn't reused because the buffer changed, but buffer "foo" is still created. 5130 call assert_equal(1, bufexists(empty_buf)) 5131 call assert_notequal(empty_buf, bufnr()) 5132 call assert_equal('foo', bufname()) 5133 call assert_equal('bar', bufname(s:bar_buf)) 5134 5135 unlet! s:bar_buf s:triggered 5136 call CleanUpTestAuGroup() 5137 %bw! 5138 endfunc 5139 5140 func Test_reuse_curbuf_switch() 5141 edit asdf 5142 let s:asdf_win = win_getid() 5143 new 5144 let other_buf = bufnr() 5145 let other_win = win_getid() 5146 augroup testing 5147 autocmd! 5148 autocmd BufUnload * ++once let s:triggered = 1 5149 \| call assert_fails('split', 'E1159:') 5150 \| call win_gotoid(s:asdf_win) 5151 augroup END 5152 5153 " Check BufUnload changing curbuf does not cause buflist_new to create a new 5154 " buffer while leaving "other_buf" unloaded in a window. 5155 enew 5156 call assert_equal(1, s:triggered) 5157 call assert_equal(other_buf, bufnr()) 5158 call assert_equal(other_win, win_getid()) 5159 call assert_equal(1, win_findbuf(other_buf)->len()) 5160 call assert_equal(1, bufloaded(other_buf)) 5161 5162 unlet! s:asdf_win s:triggered 5163 call CleanUpTestAuGroup() 5164 %bw! 5165 endfunc 5166 5167 func Test_eventignore_subtract() 5168 set eventignore=all,-WinEnter 5169 augroup testing 5170 autocmd! 5171 autocmd WinEnter * ++once let s:triggered = 1 5172 augroup END 5173 5174 new 5175 call assert_equal(1, s:triggered) 5176 5177 set eventignore& 5178 unlet! s:triggered 5179 call CleanUpTestAuGroup() 5180 %bw! 5181 endfunc 5182 5183 func Test_win_tabclose_autocmd() 5184 5185 defer CleanUpTestAuGroup() 5186 new 5187 augroup testing 5188 au WinClosed * wincmd p 5189 augroup END 5190 5191 tabnew 5192 new 5193 new 5194 5195 call assert_equal(2, tabpagenr('$')) 5196 try 5197 tabclose 5198 catch 5199 " should not happen 5200 call assert_report("closing tabpage failed") 5201 endtry 5202 call assert_equal(1, tabpagenr('$')) 5203 bw! 5204 endfunc 5205 5206 " vim: shiftwidth=2 sts=2 expandtab