test_winfixbuf.vim (80453B)
1 " Test 'winfixbuf' 2 3 source check.vim 4 source shared.vim 5 6 " Find the number of open windows in the current tab 7 func s:get_windows_count() 8 return tabpagewinnr(tabpagenr(), '$') 9 endfunc 10 11 " Create some unnamed buffers. 12 func s:make_buffers_list() 13 enew 14 file first 15 let l:first = bufnr() 16 17 enew 18 file middle 19 let l:middle = bufnr() 20 21 enew 22 file last 23 let l:last = bufnr() 24 25 set winfixbuf 26 27 return [l:first, l:last] 28 endfunc 29 30 " Create some unnamed buffers and add them to an args list 31 func s:make_args_list() 32 let [l:first, l:last] = s:make_buffers_list() 33 34 args! first middle last 35 36 return [l:first, l:last] 37 endfunc 38 39 " Create two buffers and then set the window to 'winfixbuf' 40 func s:make_buffer_pairs(...) 41 let l:reversed = get(a:, 1, 0) 42 43 if l:reversed == 1 44 enew 45 file original 46 47 set winfixbuf 48 49 enew! 50 file other 51 let l:other = bufnr() 52 53 return l:other 54 endif 55 56 enew 57 file other 58 let l:other = bufnr() 59 60 enew 61 file current 62 63 set winfixbuf 64 65 return l:other 66 endfunc 67 68 " Create 3 quick buffers and set the window to 'winfixbuf' 69 func s:make_buffer_trio() 70 edit first 71 let l:first = bufnr() 72 edit second 73 let l:second = bufnr() 74 75 set winfixbuf 76 77 edit! third 78 let l:third = bufnr() 79 80 exe $":buffer! {l:second}" 81 82 return [l:first, l:second, l:third] 83 endfunc 84 85 " Create a location list with at least 2 entries + a 'winfixbuf' window. 86 func s:make_simple_location_list() 87 enew 88 file middle 89 let l:middle = bufnr() 90 call append(0, ["winfix search-term", "another line"]) 91 92 enew! 93 file first 94 let l:first = bufnr() 95 call append(0, "first search-term") 96 97 enew! 98 file last 99 let l:last = bufnr() 100 call append(0, "last search-term") 101 102 call setloclist( 103 \ 0, 104 \ [ 105 \ { 106 \ "filename": "first", 107 \ "bufnr": l:first, 108 \ "lnum": 1, 109 \ }, 110 \ { 111 \ "filename": "middle", 112 \ "bufnr": l:middle, 113 \ "lnum": 1, 114 \ }, 115 \ { 116 \ "filename": "middle", 117 \ "bufnr": l:middle, 118 \ "lnum": 2, 119 \ }, 120 \ { 121 \ "filename": "last", 122 \ "bufnr": l:last, 123 \ "lnum": 1, 124 \ }, 125 \ ] 126 \) 127 128 set winfixbuf 129 130 return [l:first, l:middle, l:last] 131 endfunc 132 133 " Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window. 134 func s:make_simple_quickfix() 135 enew 136 file current 137 let l:current = bufnr() 138 call append(0, ["winfix search-term", "another line"]) 139 140 enew! 141 file first 142 let l:first = bufnr() 143 call append(0, "first search-term") 144 145 enew! 146 file last 147 let l:last = bufnr() 148 call append(0, "last search-term") 149 150 call setqflist( 151 \ [ 152 \ { 153 \ "filename": "first", 154 \ "bufnr": l:first, 155 \ "lnum": 1, 156 \ }, 157 \ { 158 \ "filename": "current", 159 \ "bufnr": l:current, 160 \ "lnum": 1, 161 \ }, 162 \ { 163 \ "filename": "current", 164 \ "bufnr": l:current, 165 \ "lnum": 2, 166 \ }, 167 \ { 168 \ "filename": "last", 169 \ "bufnr": l:last, 170 \ "lnum": 1, 171 \ }, 172 \ ] 173 \) 174 175 set winfixbuf 176 177 return [l:current, l:last] 178 endfunc 179 180 " Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window. 181 func s:make_quickfix_windows() 182 let [l:current, _] = s:make_simple_quickfix() 183 exe $"buffer! {l:current}" 184 185 split 186 let l:first_window = win_getid() 187 exe "normal \<C-w>j" 188 let l:winfix_window = win_getid() 189 190 " Open the quickfix in a separate split and go to it 191 copen 192 let l:quickfix_window = win_getid() 193 194 return [l:first_window, l:winfix_window, l:quickfix_window] 195 endfunc 196 197 " Revert all changes that occurred in any past test 198 func s:reset_all_buffers() 199 %bwipeout! 200 set nowinfixbuf 201 202 call setqflist([]) 203 call setloclist(0, [], 'f') 204 205 delmarks A-Z0-9 206 endfunc 207 208 " Find and set the first quickfix entry that points to `buffer` 209 func s:set_quickfix_by_buffer(buffer) 210 let l:index = 1 " quickfix indices start at 1 211 for l:entry in getqflist() 212 if l:entry["bufnr"] == a:buffer 213 exe $"{l:index} cc" 214 215 return 216 endif 217 218 let l:index += 1 219 endfor 220 221 echoerr $'No quickfix entry matching {a:buffer} could be found.' 222 endfunc 223 224 " Fail to call :Next on a 'winfixbuf' window unless :Next! is used. 225 func Test_Next() 226 call s:reset_all_buffers() 227 228 let [l:first, _] = s:make_args_list() 229 next! 230 231 call assert_fails("Next", "E1513:") 232 call assert_notequal(l:first, bufnr()) 233 234 Next! 235 call assert_equal(l:first, bufnr()) 236 endfunc 237 238 " Call :argdo and choose the next available 'nowinfixbuf' window. 239 func Test_argdo_choose_available_window() 240 call s:reset_all_buffers() 241 242 let [_, l:last] = s:make_args_list() 243 244 " Make a split window that is 'nowinfixbuf' but make it the second-to-last 245 " window so that :argdo will first try the 'winfixbuf' window, pass over it, 246 " and prefer the other 'nowinfixbuf' window, instead. 247 " 248 " +-------------------+ 249 " | 'nowinfixbuf' | 250 " +-------------------+ 251 " | 'winfixbuf' | <-- Cursor is here 252 " +-------------------+ 253 split 254 let l:nowinfixbuf_window = win_getid() 255 " Move to the 'winfixbuf' window now 256 exe "normal \<C-w>j" 257 let l:winfixbuf_window = win_getid() 258 let l:expected_windows = s:get_windows_count() 259 260 argdo echo '' 261 call assert_equal(l:nowinfixbuf_window, win_getid()) 262 call assert_equal(l:last, bufnr()) 263 call assert_equal(l:expected_windows, s:get_windows_count()) 264 endfunc 265 266 " Call :argdo and create a new split window if all available windows are 'winfixbuf'. 267 func Test_argdo_make_new_window() 268 call s:reset_all_buffers() 269 270 let [l:first, l:last] = s:make_args_list() 271 let l:current = win_getid() 272 let l:current_windows = s:get_windows_count() 273 274 argdo echo '' 275 call assert_notequal(l:current, win_getid()) 276 call assert_equal(l:last, bufnr()) 277 exe "normal \<C-w>j" 278 call assert_equal(l:first, bufnr()) 279 call assert_equal(l:current_windows + 1, s:get_windows_count()) 280 endfunc 281 282 " Fail :argedit but :argedit! is allowed 283 func Test_argedit() 284 call s:reset_all_buffers() 285 286 args! first middle last 287 enew 288 file first 289 let l:first = bufnr() 290 291 enew 292 file middle 293 let l:middle = bufnr() 294 295 enew 296 file last 297 let l:last = bufnr() 298 299 set winfixbuf 300 301 let l:current = bufnr() 302 call assert_fails("argedit first middle last", "E1513:") 303 call assert_equal(l:current, bufnr()) 304 305 argedit! first middle last 306 call assert_equal(l:first, bufnr()) 307 endfunc 308 309 " Fail :arglocal but :arglocal! is allowed 310 func Test_arglocal() 311 call s:reset_all_buffers() 312 313 let l:other = s:make_buffer_pairs() 314 let l:current = bufnr() 315 argglobal! other 316 exe $"buffer! {l:current}" 317 318 call assert_fails("arglocal other", "E1513:") 319 call assert_equal(l:current, bufnr()) 320 321 arglocal! other 322 call assert_equal(l:other, bufnr()) 323 endfunc 324 325 " Fail :argglobal but :argglobal! is allowed 326 func Test_argglobal() 327 call s:reset_all_buffers() 328 329 let l:other = s:make_buffer_pairs() 330 let l:current = bufnr() 331 332 call assert_fails("argglobal other", "E1513:") 333 call assert_equal(l:current, bufnr()) 334 335 argglobal! other 336 call assert_equal(l:other, bufnr()) 337 endfunc 338 339 " Fail :args but :args! is allowed 340 func Test_args() 341 call s:reset_all_buffers() 342 343 let [l:first, _] = s:make_buffers_list() 344 let l:current = bufnr() 345 346 call assert_fails("args first middle last", "E1513:") 347 call assert_equal(l:current, bufnr()) 348 349 args! first middle last 350 call assert_equal(l:first, bufnr()) 351 endfunc 352 353 " Fail :bNext but :bNext! is allowed 354 func Test_bNext() 355 call s:reset_all_buffers() 356 357 let l:other = s:make_buffer_pairs() 358 call assert_fails("bNext", "E1513:") 359 let l:current = bufnr() 360 361 call assert_equal(l:current, bufnr()) 362 363 bNext! 364 call assert_equal(l:other, bufnr()) 365 endfunc 366 367 " Allow :badd because it doesn't actually change the current window's buffer 368 func Test_badd() 369 call s:reset_all_buffers() 370 371 call s:make_buffer_pairs() 372 let l:current = bufnr() 373 374 badd other 375 call assert_equal(l:current, bufnr()) 376 endfunc 377 378 " Allow :balt because it doesn't actually change the current window's buffer 379 func Test_balt() 380 call s:reset_all_buffers() 381 382 call s:make_buffer_pairs() 383 let l:current = bufnr() 384 385 balt other 386 call assert_equal(l:current, bufnr()) 387 endfunc 388 389 " Fail :bfirst but :bfirst! is allowed 390 func Test_bfirst() 391 call s:reset_all_buffers() 392 393 let l:other = s:make_buffer_pairs() 394 let l:current = bufnr() 395 396 call assert_fails("bfirst", "E1513:") 397 call assert_equal(l:current, bufnr()) 398 399 bfirst! 400 call assert_equal(l:other, bufnr()) 401 endfunc 402 403 " Fail :blast but :blast! is allowed 404 func Test_blast() 405 call s:reset_all_buffers() 406 407 let l:other = s:make_buffer_pairs(1) 408 bfirst! 409 let l:current = bufnr() 410 411 call assert_fails("blast", "E1513:") 412 call assert_equal(l:current, bufnr()) 413 414 blast! 415 call assert_equal(l:other, bufnr()) 416 endfunc 417 418 " Fail :bmodified but :bmodified! is allowed 419 func Test_bmodified() 420 call s:reset_all_buffers() 421 422 let l:other = s:make_buffer_pairs() 423 let l:current = bufnr() 424 425 exe $"buffer! {l:other}" 426 set modified 427 exe $"buffer! {l:current}" 428 429 call assert_fails("bmodified", "E1513:") 430 call assert_equal(l:current, bufnr()) 431 432 bmodified! 433 call assert_equal(l:other, bufnr()) 434 endfunc 435 436 " Fail :bnext but :bnext! is allowed 437 func Test_bnext() 438 call s:reset_all_buffers() 439 440 let l:other = s:make_buffer_pairs() 441 let l:current = bufnr() 442 443 call assert_fails("bnext", "E1513:") 444 call assert_equal(l:current, bufnr()) 445 446 bnext! 447 call assert_equal(l:other, bufnr()) 448 endfunc 449 450 " Fail :bprevious but :bprevious! is allowed 451 func Test_bprevious() 452 call s:reset_all_buffers() 453 454 let l:other = s:make_buffer_pairs() 455 let l:current = bufnr() 456 457 call assert_fails("bprevious", "E1513:") 458 call assert_equal(l:current, bufnr()) 459 460 bprevious! 461 call assert_equal(l:other, bufnr()) 462 endfunc 463 464 " Fail :brewind but :brewind! is allowed 465 func Test_brewind() 466 call s:reset_all_buffers() 467 468 let l:other = s:make_buffer_pairs() 469 let l:current = bufnr() 470 471 call assert_fails("brewind", "E1513:") 472 call assert_equal(l:current, bufnr()) 473 474 brewind! 475 call assert_equal(l:other, bufnr()) 476 endfunc 477 478 " Fail :browse edit but :browse edit! is allowed 479 func Test_browse_edit_fail() 480 " A GUI dialog may stall the test. 481 CheckNotGui 482 483 call s:reset_all_buffers() 484 485 let l:other = s:make_buffer_pairs() 486 let l:current = bufnr() 487 488 call assert_fails("browse edit other", "E1513:") 489 call assert_equal(l:current, bufnr()) 490 491 try 492 browse edit! other 493 call assert_equal(l:other, bufnr()) 494 catch /^Vim\%((\a\+)\)\=:E338:/ 495 " Ignore E338, which occurs if console Vim is built with +browse. 496 " Console Vim without +browse will treat this as a regular :edit. 497 endtry 498 endfunc 499 500 " Allow :browse w because it doesn't change the buffer in the current file 501 func Test_browse_edit_pass() 502 " A GUI dialog may stall the test. 503 CheckNotGui 504 505 call s:reset_all_buffers() 506 507 let l:other = s:make_buffer_pairs() 508 let l:current = bufnr() 509 510 try 511 browse write other 512 catch /^Vim\%((\a\+)\)\=:E338:/ 513 " Ignore E338, which occurs if console Vim is built with +browse. 514 " Console Vim without +browse will treat this as a regular :write. 515 endtry 516 517 call delete("other") 518 endfunc 519 520 " Call :bufdo and choose the next available 'nowinfixbuf' window. 521 func Test_bufdo_choose_available_window() 522 call s:reset_all_buffers() 523 524 let l:other = s:make_buffer_pairs() 525 526 " Make a split window that is 'nowinfixbuf' but make it the second-to-last 527 " window so that :bufdo will first try the 'winfixbuf' window, pass over it, 528 " and prefer the other 'nowinfixbuf' window, instead. 529 " 530 " +-------------------+ 531 " | 'nowinfixbuf' | 532 " +-------------------+ 533 " | 'winfixbuf' | <-- Cursor is here 534 " +-------------------+ 535 split 536 let l:nowinfixbuf_window = win_getid() 537 " Move to the 'winfixbuf' window now 538 exe "normal \<C-w>j" 539 let l:winfixbuf_window = win_getid() 540 541 let l:current = bufnr() 542 let l:expected_windows = s:get_windows_count() 543 544 call assert_notequal(l:current, l:other) 545 546 bufdo echo '' 547 call assert_equal(l:nowinfixbuf_window, win_getid()) 548 call assert_notequal(l:other, bufnr()) 549 call assert_equal(l:expected_windows, s:get_windows_count()) 550 endfunc 551 552 " Call :bufdo and create a new split window if all available windows are 'winfixbuf'. 553 func Test_bufdo_make_new_window() 554 call s:reset_all_buffers() 555 556 let [l:first, l:last] = s:make_buffers_list() 557 exe $"buffer! {l:first}" 558 let l:current = win_getid() 559 let l:current_windows = s:get_windows_count() 560 561 bufdo echo '' 562 call assert_notequal(l:current, win_getid()) 563 call assert_equal(l:last, bufnr()) 564 exe "normal \<C-w>j" 565 call assert_equal(l:first, bufnr()) 566 call assert_equal(l:current_windows + 1, s:get_windows_count()) 567 endfunc 568 569 " Fail :buffer but :buffer! is allowed 570 func Test_buffer() 571 call s:reset_all_buffers() 572 573 let l:other = s:make_buffer_pairs() 574 let l:current = bufnr() 575 576 call assert_fails($"buffer {l:other}", "E1513:") 577 call assert_equal(l:current, bufnr()) 578 579 exe $"buffer! {l:other}" 580 call assert_equal(l:other, bufnr()) 581 endfunc 582 583 " Allow :buffer on a 'winfixbuf' window if there is no change in buffer 584 func Test_buffer_same_buffer() 585 call s:reset_all_buffers() 586 587 call s:make_buffer_pairs() 588 let l:current = bufnr() 589 590 exe $"buffer {l:current}" 591 call assert_equal(l:current, bufnr()) 592 593 exe $"buffer! {l:current}" 594 call assert_equal(l:current, bufnr()) 595 endfunc 596 597 " Allow :cNext but the 'nowinfixbuf' window is selected, instead 598 func Test_cNext() 599 CheckFeature quickfix 600 call s:reset_all_buffers() 601 602 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 603 604 " The call to `:cNext` succeeds but it selects the window with 'nowinfixbuf' instead 605 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 606 607 " Make sure the previous window has 'winfixbuf' so we can test that our 608 " "skip 'winfixbuf' window" logic works. 609 call win_gotoid(l:winfix_window) 610 call win_gotoid(l:quickfix_window) 611 612 cNext 613 call assert_equal(l:first_window, win_getid()) 614 endfunc 615 616 " Allow :cNfile but the 'nowinfixbuf' window is selected, instead 617 func Test_cNfile() 618 CheckFeature quickfix 619 call s:reset_all_buffers() 620 621 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 622 623 " The call to `:cNfile` succeeds but it selects the window with 'nowinfixbuf' instead 624 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 625 cnext! 626 627 " Make sure the previous window has 'winfixbuf' so we can test that our 628 " "skip 'winfixbuf' window" logic works. 629 call win_gotoid(l:winfix_window) 630 call win_gotoid(l:quickfix_window) 631 632 cNfile 633 call assert_equal(l:first_window, win_getid()) 634 endfunc 635 636 " Allow :caddexpr because it doesn't change the current buffer 637 func Test_caddexpr() 638 CheckFeature quickfix 639 call s:reset_all_buffers() 640 641 let l:file_path = tempname() 642 call writefile(["Error - bad-thing-found"], l:file_path, 'D') 643 exe $"edit {l:file_path}" 644 let l:file_buffer = bufnr() 645 let l:current = bufnr() 646 647 edit first.unittest 648 call append(0, ["some-search-term bad-thing-found"]) 649 650 edit! other.unittest 651 652 set winfixbuf 653 654 exe $"buffer! {l:file_buffer}" 655 656 exe 'caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' 657 call assert_equal(l:current, bufnr()) 658 endfunc 659 660 " Fail :cbuffer but :cbuffer! is allowed 661 func Test_cbuffer() 662 CheckFeature quickfix 663 call s:reset_all_buffers() 664 665 let l:file_path = tempname() 666 call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path, 'D') 667 exe $"edit {l:file_path}" 668 let l:file_buffer = bufnr() 669 let l:current = bufnr() 670 671 edit first.unittest 672 call append(0, ["some-search-term bad-thing-found"]) 673 674 edit! other.unittest 675 676 set winfixbuf 677 678 exe $"buffer! {file_buffer}" 679 680 call assert_fails($"cbuffer {file_buffer}", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 681 call assert_equal(current, bufnr()) 682 683 exe $"cbuffer! {file_buffer}" 684 call assert_equal("first.unittest", expand("%:t")) 685 endfunc 686 687 " Allow :cc but the 'nowinfixbuf' window is selected, instead 688 func Test_cc() 689 CheckFeature quickfix 690 call s:reset_all_buffers() 691 692 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 693 694 " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead 695 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 696 697 " Make sure the previous window has 'winfixbuf' so we can test that our 698 " "skip 'winfixbuf' window" logic works. 699 call win_gotoid(l:winfix_window) 700 call win_gotoid(l:quickfix_window) 701 " Go up one line in the quickfix window to an quickfix entry that doesn't 702 " point to a winfixbuf buffer 703 normal k 704 " Attempt to make the previous window, winfixbuf buffer, to go to the 705 " non-winfixbuf quickfix entry 706 .cc 707 708 " Confirm that :.cc did not change the winfixbuf-enabled window 709 call assert_equal(l:first_window, win_getid()) 710 endfunc 711 712 " Call :cdo and choose the next available 'nowinfixbuf' window. 713 func Test_cdo_choose_available_window() 714 CheckFeature quickfix 715 call s:reset_all_buffers() 716 717 let [l:current, l:last] = s:make_simple_quickfix() 718 exe $"buffer! {l:current}" 719 720 " Make a split window that is 'nowinfixbuf' but make it the second-to-last 721 " window so that :cdo will first try the 'winfixbuf' window, pass over it, 722 " and prefer the other 'nowinfixbuf' window, instead. 723 " 724 " +-------------------+ 725 " | 'nowinfixbuf' | 726 " +-------------------+ 727 " | 'winfixbuf' | <-- Cursor is here 728 " +-------------------+ 729 split 730 let l:nowinfixbuf_window = win_getid() 731 " Move to the 'winfixbuf' window now 732 exe "normal \<C-w>j" 733 let l:winfixbuf_window = win_getid() 734 let l:expected_windows = s:get_windows_count() 735 736 cdo echo '' 737 738 call assert_equal(l:nowinfixbuf_window, win_getid()) 739 call assert_equal(l:last, bufnr()) 740 exe "normal \<C-w>j" 741 call assert_equal(l:current, bufnr()) 742 call assert_equal(l:expected_windows, s:get_windows_count()) 743 endfunc 744 745 " Call :cdo and create a new split window if all available windows are 'winfixbuf'. 746 func Test_cdo_make_new_window() 747 CheckFeature quickfix 748 call s:reset_all_buffers() 749 750 let [l:current_buffer, l:last] = s:make_simple_quickfix() 751 exe $"buffer! {l:current_buffer}" 752 753 let l:current_window = win_getid() 754 let l:current_windows = s:get_windows_count() 755 756 cdo echo '' 757 call assert_notequal(l:current_window, win_getid()) 758 call assert_equal(l:last, bufnr()) 759 exe "normal \<C-w>j" 760 call assert_equal(l:current_buffer, bufnr()) 761 call assert_equal(l:current_windows + 1, s:get_windows_count()) 762 endfunc 763 764 " Fail :cexpr but :cexpr! is allowed 765 func Test_cexpr() 766 CheckFeature quickfix 767 call s:reset_all_buffers() 768 769 let file = tempname() 770 let entry = $'["{file}:1:bar"]' 771 let current = bufnr() 772 773 set winfixbuf 774 775 call assert_fails($"cexpr {entry}", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 776 call assert_equal(current, bufnr()) 777 778 exe $"cexpr! {entry}" 779 call assert_equal(fnamemodify(file, ":t"), expand("%:t")) 780 endfunc 781 782 " Call :cfdo and choose the next available 'nowinfixbuf' window. 783 func Test_cfdo_choose_available_window() 784 CheckFeature quickfix 785 call s:reset_all_buffers() 786 787 let [l:current, l:last] = s:make_simple_quickfix() 788 exe $"buffer! {l:current}" 789 790 " Make a split window that is 'nowinfixbuf' but make it the second-to-last 791 " window so that :cfdo will first try the 'winfixbuf' window, pass over it, 792 " and prefer the other 'nowinfixbuf' window, instead. 793 " 794 " +-------------------+ 795 " | 'nowinfixbuf' | 796 " +-------------------+ 797 " | 'winfixbuf' | <-- Cursor is here 798 " +-------------------+ 799 split 800 let l:nowinfixbuf_window = win_getid() 801 " Move to the 'winfixbuf' window now 802 exe "normal \<C-w>j" 803 let l:winfixbuf_window = win_getid() 804 let l:expected_windows = s:get_windows_count() 805 806 cfdo echo '' 807 808 call assert_equal(l:nowinfixbuf_window, win_getid()) 809 call assert_equal(l:last, bufnr()) 810 exe "normal \<C-w>j" 811 call assert_equal(l:current, bufnr()) 812 call assert_equal(l:expected_windows, s:get_windows_count()) 813 endfunc 814 815 " Call :cfdo and create a new split window if all available windows are 'winfixbuf'. 816 func Test_cfdo_make_new_window() 817 CheckFeature quickfix 818 call s:reset_all_buffers() 819 820 let [l:current_buffer, l:last] = s:make_simple_quickfix() 821 exe $"buffer! {l:current_buffer}" 822 823 let l:current_window = win_getid() 824 let l:current_windows = s:get_windows_count() 825 826 cfdo echo '' 827 call assert_notequal(l:current_window, win_getid()) 828 call assert_equal(l:last, bufnr()) 829 exe "normal \<C-w>j" 830 call assert_equal(l:current_buffer, bufnr()) 831 call assert_equal(l:current_windows + 1, s:get_windows_count()) 832 endfunc 833 834 " Fail :cfile but :cfile! is allowed 835 func Test_cfile() 836 CheckFeature quickfix 837 call s:reset_all_buffers() 838 839 edit first.unittest 840 call append(0, ["some-search-term bad-thing-found"]) 841 write 842 let first = bufnr() 843 844 edit! second.unittest 845 call append(0, ["some-search-term"]) 846 write 847 848 let file = tempname() 849 call writefile(["first.unittest:1:Error - bad-thing-found was detected"], file) 850 851 let current = bufnr() 852 853 set winfixbuf 854 855 call assert_fails($":cfile {file}", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 856 call assert_equal(current, bufnr()) 857 858 exe $":cfile! {file}" 859 call assert_equal(first, bufnr()) 860 861 call delete(file) 862 call delete("first.unittest") 863 call delete("second.unittest") 864 endfunc 865 866 " Allow :cfirst but the 'nowinfixbuf' window is selected, instead 867 func Test_cfirst() 868 CheckFeature quickfix 869 call s:reset_all_buffers() 870 871 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 872 873 " The call to `:cfirst` succeeds but it selects the window with 'nowinfixbuf' instead 874 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 875 876 " Make sure the previous window has 'winfixbuf' so we can test that our 877 " "skip 'winfixbuf' window" logic works. 878 call win_gotoid(l:winfix_window) 879 call win_gotoid(l:quickfix_window) 880 881 cfirst 882 call assert_equal(l:first_window, win_getid()) 883 endfunc 884 885 " Allow :clast but the 'nowinfixbuf' window is selected, instead 886 func Test_clast() 887 CheckFeature quickfix 888 call s:reset_all_buffers() 889 890 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 891 892 " The call to `:clast` succeeds but it selects the window with 'nowinfixbuf' instead 893 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 894 895 " Make sure the previous window has 'winfixbuf' so we can test that our 896 " "skip 'winfixbuf' window" logic works. 897 call win_gotoid(l:winfix_window) 898 call win_gotoid(l:quickfix_window) 899 900 clast 901 call assert_equal(l:first_window, win_getid()) 902 endfunc 903 904 " Allow :cnext but the 'nowinfixbuf' window is selected, instead 905 " Make sure no new windows are created and previous windows are reused 906 func Test_cnext() 907 CheckFeature quickfix 908 call s:reset_all_buffers() 909 910 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 911 let l:expected = s:get_windows_count() 912 913 " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead 914 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 915 916 cnext! 917 call assert_equal(l:expected, s:get_windows_count()) 918 919 " Make sure the previous window has 'winfixbuf' so we can test that our 920 " "skip 'winfixbuf' window" logic works. 921 call win_gotoid(l:winfix_window) 922 call win_gotoid(l:quickfix_window) 923 924 cnext 925 call assert_equal(l:first_window, win_getid()) 926 call assert_equal(l:expected, s:get_windows_count()) 927 endfunc 928 929 " Make sure :cnext creates a split window if no previous window exists 930 func Test_cnext_no_previous_window() 931 CheckFeature quickfix 932 call s:reset_all_buffers() 933 934 let [l:current, _] = s:make_simple_quickfix() 935 exe $"buffer! {l:current}" 936 937 let l:expected = s:get_windows_count() 938 939 " Open the quickfix in a separate split and go to it 940 copen 941 942 call assert_equal(l:expected + 1, s:get_windows_count()) 943 endfunc 944 945 " Allow :cnext and create a 'nowinfixbuf' window if none exists 946 func Test_cnext_make_new_window() 947 CheckFeature quickfix 948 call s:reset_all_buffers() 949 950 let [l:current, _] = s:make_simple_quickfix() 951 let l:current = win_getid() 952 953 cfirst! 954 955 let l:windows = s:get_windows_count() 956 let l:expected = l:windows + 1 " We're about to create a new split window 957 958 cnext 959 call assert_equal(l:expected, s:get_windows_count()) 960 961 cnext! 962 call assert_equal(l:expected, s:get_windows_count()) 963 endfunc 964 965 " Allow :cprevious but the 'nowinfixbuf' window is selected, instead 966 func Test_cprevious() 967 CheckFeature quickfix 968 call s:reset_all_buffers() 969 970 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 971 972 " The call to `:cprevious` succeeds but it selects the window with 'nowinfixbuf' instead 973 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 974 975 " Make sure the previous window has 'winfixbuf' so we can test that our 976 " "skip 'winfixbuf' window" logic works. 977 call win_gotoid(l:winfix_window) 978 call win_gotoid(l:quickfix_window) 979 980 cprevious 981 call assert_equal(l:first_window, win_getid()) 982 endfunc 983 984 " Allow :cnfile but the 'nowinfixbuf' window is selected, instead 985 func Test_cnfile() 986 CheckFeature quickfix 987 call s:reset_all_buffers() 988 989 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 990 991 " The call to `:cnfile` succeeds but it selects the window with 'nowinfixbuf' instead 992 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 993 cnext! 994 995 " Make sure the previous window has 'winfixbuf' so we can test that our 996 " "skip 'winfixbuf' window" logic works. 997 call win_gotoid(l:winfix_window) 998 call win_gotoid(l:quickfix_window) 999 1000 cnfile 1001 call assert_equal(l:first_window, win_getid()) 1002 endfunc 1003 1004 " Allow :cpfile but the 'nowinfixbuf' window is selected, instead 1005 func Test_cpfile() 1006 CheckFeature quickfix 1007 call s:reset_all_buffers() 1008 1009 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 1010 1011 " The call to `:cpfile` succeeds but it selects the window with 'nowinfixbuf' instead 1012 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 1013 cnext! 1014 1015 " Make sure the previous window has 'winfixbuf' so we can test that our 1016 " "skip 'winfixbuf' window" logic works. 1017 call win_gotoid(l:winfix_window) 1018 call win_gotoid(l:quickfix_window) 1019 1020 cpfile 1021 call assert_equal(l:first_window, win_getid()) 1022 endfunc 1023 1024 " Allow :crewind but the 'nowinfixbuf' window is selected, instead 1025 func Test_crewind() 1026 CheckFeature quickfix 1027 call s:reset_all_buffers() 1028 1029 let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows() 1030 1031 " The call to `:crewind` succeeds but it selects the window with 'nowinfixbuf' instead 1032 call s:set_quickfix_by_buffer(winbufnr(l:winfix_window)) 1033 cnext! 1034 1035 " Make sure the previous window has 'winfixbuf' so we can test that our 1036 " "skip 'winfixbuf' window" logic works. 1037 call win_gotoid(l:winfix_window) 1038 call win_gotoid(l:quickfix_window) 1039 1040 crewind 1041 call assert_equal(l:first_window, win_getid()) 1042 endfunc 1043 1044 " Allow <C-w>f because it opens in a new split 1045 func Test_ctrl_w_f() 1046 call s:reset_all_buffers() 1047 1048 enew 1049 let l:file_name = tempname() 1050 call writefile([], l:file_name) 1051 let l:file_buffer = bufnr() 1052 1053 enew 1054 file other 1055 let l:other_buffer = bufnr() 1056 1057 set winfixbuf 1058 1059 call setline(1, l:file_name) 1060 let l:current_windows = s:get_windows_count() 1061 exe "normal \<C-w>f" 1062 1063 call assert_equal(l:current_windows + 1, s:get_windows_count()) 1064 1065 call delete(l:file_name) 1066 endfunc 1067 1068 " Fail :djump but :djump! is allowed 1069 func Test_djump() 1070 call s:reset_all_buffers() 1071 1072 let l:include_file = tempname() .. ".h" 1073 call writefile(["min(1, 12);", 1074 \ $'#include "{l:include_file}"' 1075 \ ], 1076 \ "main.c") 1077 call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) 1078 edit main.c 1079 1080 set winfixbuf 1081 1082 let l:current = bufnr() 1083 1084 call assert_fails("djump 1 /min/", "E1513:") 1085 call assert_equal(l:current, bufnr()) 1086 1087 djump! 1 /min/ 1088 call assert_notequal(l:current, bufnr()) 1089 1090 call delete("main.c") 1091 call delete(l:include_file) 1092 endfunc 1093 1094 " Fail :drop but :drop! is allowed 1095 func Test_drop() 1096 call s:reset_all_buffers() 1097 1098 let l:other = s:make_buffer_pairs() 1099 let l:current = bufnr() 1100 1101 call assert_fails("drop other", "E1513:") 1102 call assert_equal(l:current, bufnr()) 1103 1104 drop! other 1105 call assert_equal(l:other, bufnr()) 1106 endfunc 1107 1108 " Fail :edit but :edit! is allowed 1109 func Test_edit() 1110 call s:reset_all_buffers() 1111 1112 let l:other = s:make_buffer_pairs() 1113 let l:current = bufnr() 1114 1115 call assert_fails("edit other", "E1513:") 1116 call assert_equal(l:current, bufnr()) 1117 1118 edit! other 1119 call assert_equal(l:other, bufnr()) 1120 endfunc 1121 1122 " Fail :e when selecting a buffer from a relative path if in a different folder 1123 " 1124 " In this tests there's 2 buffers 1125 " 1126 " foo - lives on disk, in some folder. e.g. /tmp/foo 1127 " foo - an in-memory buffer that has not been saved to disk. If saved, it 1128 " would live in a different folder, /other/foo. 1129 " 1130 " The 'winfixbuf' is looking at the in-memory buffer and trying to switch to 1131 " the buffer on-disk (and fails, because it's a different buffer) 1132 func Test_edit_different_buffer_on_disk_and_relative_path_to_disk() 1133 call s:reset_all_buffers() 1134 1135 let l:file_on_disk = tempname() 1136 let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h") 1137 let l:name = fnamemodify(l:file_on_disk, ":t") 1138 exe $"edit {l:file_on_disk}" 1139 write! 1140 1141 let l:directory_on_disk2 = l:directory_on_disk1 .. "_something_else" 1142 1143 if !isdirectory(l:directory_on_disk2) 1144 call mkdir(l:directory_on_disk2) 1145 endif 1146 1147 exe $"cd {l:directory_on_disk2}" 1148 exe $"edit {l:name}" 1149 1150 let l:current = bufnr() 1151 1152 call assert_equal(l:current, bufnr()) 1153 set winfixbuf 1154 call assert_fails($"edit {l:file_on_disk}", "E1513:") 1155 call assert_equal(l:current, bufnr()) 1156 1157 call delete(l:directory_on_disk1) 1158 call delete(l:directory_on_disk2) 1159 endfunc 1160 1161 " Fail :e when selecting a buffer from a relative path if in a different folder 1162 " 1163 " In this tests there's 2 buffers 1164 " 1165 " foo - lives on disk, in some folder. e.g. /tmp/foo 1166 " foo - an in-memory buffer that has not been saved to disk. If saved, it 1167 " would live in a different folder, /other/foo. 1168 " 1169 " The 'winfixbuf' is looking at the on-disk buffer and trying to switch to 1170 " the in-memory buffer (and fails, because it's a different buffer) 1171 func Test_edit_different_buffer_on_disk_and_relative_path_to_memory() 1172 call s:reset_all_buffers() 1173 1174 let l:file_on_disk = tempname() 1175 let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h") 1176 let l:name = fnamemodify(l:file_on_disk, ":t") 1177 exe $"edit {l:file_on_disk}" 1178 write! 1179 1180 let l:directory_on_disk2 = l:directory_on_disk1 .. "_something_else" 1181 1182 if !isdirectory(l:directory_on_disk2) 1183 call mkdir(l:directory_on_disk2) 1184 endif 1185 1186 exe $"cd {l:directory_on_disk2}" 1187 exe $"edit {l:name}" 1188 exe $"cd {l:directory_on_disk1}" 1189 exe $"edit {l:file_on_disk}" 1190 exe $"cd {l:directory_on_disk2}" 1191 1192 let l:current = bufnr() 1193 1194 call assert_equal(l:current, bufnr()) 1195 set winfixbuf 1196 call assert_fails($"edit {l:name}", "E1513:") 1197 call assert_equal(l:current, bufnr()) 1198 1199 call delete(l:directory_on_disk1) 1200 call delete(l:directory_on_disk2) 1201 endfunc 1202 1203 " Fail to call `:e first` if called from a starting, in-memory buffer 1204 func Test_edit_first_buffer() 1205 call s:reset_all_buffers() 1206 1207 set winfixbuf 1208 let l:current = bufnr() 1209 1210 call assert_fails("edit first", "E1513:") 1211 call assert_equal(l:current, bufnr()) 1212 1213 edit! first 1214 call assert_equal(l:current, bufnr()) 1215 edit! somewhere_else 1216 call assert_notequal(l:current, bufnr()) 1217 endfunc 1218 1219 " Allow reloading a buffer using :e 1220 func Test_edit_no_arguments() 1221 call s:reset_all_buffers() 1222 1223 let l:current = bufnr() 1224 file some_buffer 1225 1226 call assert_equal(l:current, bufnr()) 1227 set winfixbuf 1228 edit 1229 call assert_equal(l:current, bufnr()) 1230 endfunc 1231 1232 " Allow :e selecting the current buffer 1233 func Test_edit_same_buffer_in_memory() 1234 call s:reset_all_buffers() 1235 1236 let current = bufnr() 1237 file same_buffer 1238 1239 call assert_equal(current, bufnr()) 1240 set winfixbuf 1241 edit same_buffer 1242 call assert_equal(current, bufnr()) 1243 set nowinfixbuf 1244 endfunc 1245 1246 " Allow :e selecting the current buffer as a full path 1247 func Test_edit_same_buffer_on_disk_absolute_path() 1248 call s:reset_all_buffers() 1249 1250 let file = tempname() 1251 " file must exist for expansion of 8.3 paths to succeed 1252 call writefile([], file, 'D') 1253 let file = fnamemodify(file, ':p') 1254 let current = bufnr() 1255 exe $"edit {file}" 1256 write! 1257 1258 call assert_equal(current, bufnr()) 1259 set winfixbuf 1260 exe $"edit {file}" 1261 call assert_equal(current, bufnr()) 1262 1263 set nowinfixbuf 1264 endfunc 1265 1266 " Fail :enew but :enew! is allowed 1267 func Test_enew() 1268 call s:reset_all_buffers() 1269 1270 let l:other = s:make_buffer_pairs() 1271 let l:current = bufnr() 1272 1273 call assert_fails("enew", "E1513:") 1274 call assert_equal(l:current, bufnr()) 1275 1276 enew! 1277 call assert_notequal(l:other, bufnr()) 1278 call assert_notequal(3, bufnr()) 1279 endfunc 1280 1281 " Fail :ex but :ex! is allowed 1282 func Test_ex() 1283 call s:reset_all_buffers() 1284 1285 let l:other = s:make_buffer_pairs() 1286 let l:current = bufnr() 1287 1288 call assert_fails("ex other", "E1513:") 1289 call assert_equal(l:current, bufnr()) 1290 1291 ex! other 1292 call assert_equal(l:other, bufnr()) 1293 endfunc 1294 1295 " Fail :find but :find! is allowed 1296 func Test_find() 1297 call s:reset_all_buffers() 1298 1299 let l:current = bufnr() 1300 let l:file = tempname() 1301 call writefile([], l:file, 'D') 1302 let l:file = fnamemodify(l:file, ':p') " In case it's Windows 8.3-style. 1303 let l:directory = fnamemodify(l:file, ":p:h") 1304 let l:name = fnamemodify(l:file, ":p:t") 1305 1306 let l:original_path = &path 1307 exe $"set path={l:directory}" 1308 1309 set winfixbuf 1310 1311 call assert_fails($"exe 'find {l:name}'", "E1513:") 1312 call assert_equal(l:current, bufnr()) 1313 1314 exe $"find! {l:name}" 1315 call assert_equal(l:file, expand("%:p")) 1316 1317 exe $"set path={l:original_path}" 1318 endfunc 1319 1320 " Fail :first but :first! is allowed 1321 func Test_first() 1322 call s:reset_all_buffers() 1323 1324 let [l:first, _] = s:make_args_list() 1325 next! 1326 1327 call assert_fails("first", "E1513:") 1328 call assert_notequal(l:first, bufnr()) 1329 1330 first! 1331 call assert_equal(l:first, bufnr()) 1332 endfunc 1333 1334 " Fail :grep but :grep! is allowed 1335 func Test_grep() 1336 CheckFeature quickfix 1337 call s:reset_all_buffers() 1338 1339 edit first.unittest 1340 call append(0, ["some-search-term"]) 1341 write 1342 let l:first = bufnr() 1343 1344 edit current.unittest 1345 call append(0, ["some-search-term"]) 1346 write 1347 let l:current = bufnr() 1348 1349 edit! last.unittest 1350 call append(0, ["some-search-term"]) 1351 write 1352 let l:last = bufnr() 1353 1354 set winfixbuf 1355 1356 buffer! current.unittest 1357 1358 call assert_fails("silent! grep some-search-term *.unittest", "E1513:") 1359 call assert_equal(l:current, bufnr()) 1360 exe $"edit! {l:first}" 1361 1362 silent! grep! some-search-term *.unittest 1363 call assert_notequal(l:first, bufnr()) 1364 1365 call delete("first.unittest") 1366 call delete("current.unittest") 1367 call delete("last.unittest") 1368 endfunc 1369 1370 " Fail :ijump but :ijump! is allowed 1371 func Test_ijump() 1372 call s:reset_all_buffers() 1373 1374 let l:include_file = tempname() .. ".h" 1375 call writefile([ 1376 \ $'#include "{l:include_file}"' 1377 \ ], 1378 \ "main.c", 'D') 1379 call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') 1380 edit main.c 1381 1382 set winfixbuf 1383 1384 let l:current = bufnr() 1385 1386 set define=^\\s*#\\s*define 1387 set include=^\\s*#\\s*include 1388 set path=.,/usr/include,, 1389 1390 call assert_fails("ijump /min/", "E1513:") 1391 call assert_equal(l:current, bufnr()) 1392 1393 set nowinfixbuf 1394 1395 ijump! /min/ 1396 call assert_notequal(l:current, bufnr()) 1397 1398 set define& 1399 set include& 1400 set path& 1401 endfunc 1402 1403 " Fail :lNext but :lNext! is allowed 1404 func Test_lNext() 1405 CheckFeature quickfix 1406 call s:reset_all_buffers() 1407 1408 let [l:first, l:middle, _] = s:make_simple_location_list() 1409 call assert_equal(1, getloclist(0, #{idx: 0}).idx) 1410 1411 lnext! 1412 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1413 call assert_equal(l:middle, bufnr()) 1414 1415 call assert_fails("lNext", "E1513:") 1416 " Ensure the entry didn't change. 1417 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1418 call assert_equal(l:middle, bufnr()) 1419 1420 lnext! 1421 call assert_equal(3, getloclist(0, #{idx: 0}).idx) 1422 call assert_equal(l:middle, bufnr()) 1423 1424 lNext! 1425 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1426 call assert_equal(l:middle, bufnr()) 1427 1428 lNext! 1429 call assert_equal(1, getloclist(0, #{idx: 0}).idx) 1430 call assert_equal(l:first, bufnr()) 1431 endfunc 1432 1433 " Fail :lNfile but :lNfile! is allowed 1434 func Test_lNfile() 1435 CheckFeature quickfix 1436 call s:reset_all_buffers() 1437 1438 let [l:first, l:current, _] = s:make_simple_location_list() 1439 call assert_equal(1, getloclist(0, #{idx: 0}).idx) 1440 1441 lnext! 1442 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1443 call assert_equal(l:current, bufnr()) 1444 1445 call assert_fails("lNfile", "E1513:") 1446 " Ensure the entry didn't change. 1447 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1448 call assert_equal(l:current, bufnr()) 1449 1450 lnext! 1451 call assert_equal(3, getloclist(0, #{idx: 0}).idx) 1452 call assert_equal(l:current, bufnr()) 1453 1454 lNfile! 1455 call assert_equal(1, getloclist(0, #{idx: 0}).idx) 1456 call assert_equal(l:first, bufnr()) 1457 endfunc 1458 1459 " Allow :laddexpr because it doesn't change the current buffer 1460 func Test_laddexpr() 1461 CheckFeature quickfix 1462 call s:reset_all_buffers() 1463 1464 let l:file_path = tempname() 1465 call writefile(["Error - bad-thing-found"], l:file_path, 'D') 1466 exe $"edit {l:file_path}" 1467 let l:file_buffer = bufnr() 1468 let l:current = bufnr() 1469 1470 edit first.unittest 1471 call append(0, ["some-search-term bad-thing-found"]) 1472 1473 edit! other.unittest 1474 1475 set winfixbuf 1476 1477 exe $"buffer! {l:file_buffer}" 1478 1479 exe 'laddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' 1480 call assert_equal(l:current, bufnr()) 1481 endfunc 1482 1483 " Fail :last but :last! is allowed 1484 func Test_last() 1485 call s:reset_all_buffers() 1486 1487 let [_, l:last] = s:make_args_list() 1488 next! 1489 1490 call assert_fails("last", "E1513:") 1491 call assert_notequal(l:last, bufnr()) 1492 1493 last! 1494 call assert_equal(l:last, bufnr()) 1495 endfunc 1496 1497 " Fail :lbuffer but :lbuffer! is allowed 1498 func Test_lbuffer() 1499 CheckFeature quickfix 1500 call s:reset_all_buffers() 1501 1502 let l:file_path = tempname() 1503 call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path, 'D') 1504 exe $"edit {l:file_path}" 1505 let l:file_buffer = bufnr() 1506 let l:current = bufnr() 1507 1508 edit first.unittest 1509 call append(0, ["some-search-term bad-thing-found"]) 1510 1511 edit! other.unittest 1512 1513 set winfixbuf 1514 1515 exe $"buffer! {file_buffer}" 1516 1517 call assert_fails($"lbuffer {file_buffer}", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 1518 call assert_equal(current, bufnr()) 1519 1520 exe $"lbuffer! {file_buffer}" 1521 call assert_equal("first.unittest", expand("%:t")) 1522 endfunc 1523 1524 " Fail :ldo but :ldo! is allowed 1525 func Test_ldo() 1526 CheckFeature quickfix 1527 call s:reset_all_buffers() 1528 1529 let [l:first, l:middle, l:last] = s:make_simple_location_list() 1530 lnext! 1531 1532 call assert_fails($'exe "ldo buffer {l:first}"', "E1513:") 1533 call assert_equal(l:middle, bufnr()) 1534 exe $"ldo! buffer {l:first}" 1535 call assert_notequal(l:last, bufnr()) 1536 endfunc 1537 1538 " Fail :lfdo but :lfdo! is allowed 1539 func Test_lexpr() 1540 CheckFeature quickfix 1541 call s:reset_all_buffers() 1542 1543 let file = tempname() 1544 let entry = $'["{file}:1:bar"]' 1545 let current = bufnr() 1546 1547 set winfixbuf 1548 1549 call assert_fails($"lexpr {entry}", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 1550 call assert_equal(current, bufnr()) 1551 1552 exe $"lexpr! {entry}" 1553 call assert_equal(fnamemodify(file, ":t"), expand("%:t")) 1554 endfunc 1555 1556 " Fail :lfdo but :lfdo! is allowed 1557 func Test_lfdo() 1558 CheckFeature quickfix 1559 call s:reset_all_buffers() 1560 1561 let [first, middle, last] = s:make_simple_location_list() 1562 lnext! 1563 1564 call assert_fails('exe "lfdo buffer ' .. first .. '"', "E1513:") 1565 call assert_equal(middle, bufnr()) 1566 exe $"lfdo! buffer {first}" 1567 call assert_notequal(last, bufnr()) 1568 endfunc 1569 1570 " Fail :lfile but :lfile! is allowed 1571 func Test_lfile() 1572 CheckFeature quickfix 1573 call s:reset_all_buffers() 1574 1575 edit first.unittest 1576 call append(0, ["some-search-term bad-thing-found"]) 1577 write 1578 let l:first = bufnr() 1579 1580 edit! second.unittest 1581 call append(0, ["some-search-term"]) 1582 write 1583 1584 let l:file = tempname() 1585 call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file, 'D') 1586 1587 let l:current = bufnr() 1588 1589 set winfixbuf 1590 1591 call assert_fails($":lfile {l:file}", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 1592 call assert_equal(l:current, bufnr()) 1593 1594 exe $":lfile! {l:file}" 1595 call assert_equal(l:first, bufnr()) 1596 1597 call delete("first.unittest") 1598 call delete("second.unittest") 1599 endfunc 1600 1601 " Fail :ll but :ll! is allowed 1602 func Test_ll() 1603 CheckFeature quickfix 1604 call s:reset_all_buffers() 1605 1606 let [l:first, l:middle, l:last] = s:make_simple_location_list() 1607 lopen 1608 lfirst! 1609 exe "normal \<C-w>j" 1610 normal j 1611 1612 call assert_fails(".ll", "E1513:") 1613 exe "normal \<C-w>k" 1614 call assert_equal(l:first, bufnr()) 1615 exe "normal \<C-w>j" 1616 .ll! 1617 exe "normal \<C-w>k" 1618 call assert_equal(l:middle, bufnr()) 1619 endfunc 1620 1621 " Fail :llast but :llast! is allowed 1622 func Test_llast() 1623 CheckFeature quickfix 1624 call s:reset_all_buffers() 1625 1626 let [l:first, _, l:last] = s:make_simple_location_list() 1627 lfirst! 1628 1629 call assert_fails("llast", "E1513:") 1630 call assert_equal(l:first, bufnr()) 1631 1632 llast! 1633 call assert_equal(l:last, bufnr()) 1634 endfunc 1635 1636 " Fail :lnext but :lnext! is allowed 1637 func Test_lnext() 1638 CheckFeature quickfix 1639 call s:reset_all_buffers() 1640 1641 let [l:first, l:middle, l:last] = s:make_simple_location_list() 1642 ll! 1643 1644 call assert_fails("lnext", "E1513:") 1645 call assert_equal(l:first, bufnr()) 1646 1647 lnext! 1648 call assert_equal(l:middle, bufnr()) 1649 endfunc 1650 1651 " Fail :lnfile but :lnfile! is allowed 1652 func Test_lnfile() 1653 CheckFeature quickfix 1654 call s:reset_all_buffers() 1655 1656 let [_, l:current, l:last] = s:make_simple_location_list() 1657 call assert_equal(1, getloclist(0, #{idx: 0}).idx) 1658 1659 lnext! 1660 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1661 call assert_equal(l:current, bufnr()) 1662 1663 call assert_fails("lnfile", "E1513:") 1664 " Ensure the entry didn't change. 1665 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1666 call assert_equal(l:current, bufnr()) 1667 1668 lnfile! 1669 call assert_equal(4, getloclist(0, #{idx: 0}).idx) 1670 call assert_equal(l:last, bufnr()) 1671 endfunc 1672 1673 " Fail :lpfile but :lpfile! is allowed 1674 func Test_lpfile() 1675 CheckFeature quickfix 1676 call s:reset_all_buffers() 1677 1678 let [l:first, l:current, _] = s:make_simple_location_list() 1679 lnext! 1680 1681 call assert_fails("lpfile", "E1513:") 1682 call assert_equal(l:current, bufnr()) 1683 1684 lnext! " Reset for the next test call 1685 1686 lpfile! 1687 call assert_equal(l:first, bufnr()) 1688 endfunc 1689 1690 " Fail :lprevious but :lprevious! is allowed 1691 func Test_lprevious() 1692 CheckFeature quickfix 1693 call s:reset_all_buffers() 1694 1695 let [l:first, l:middle, _] = s:make_simple_location_list() 1696 call assert_equal(1, getloclist(0, #{idx: 0}).idx) 1697 1698 lnext! 1699 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1700 call assert_equal(l:middle, bufnr()) 1701 1702 call assert_fails("lprevious", "E1513:") 1703 " Ensure the entry didn't change. 1704 call assert_equal(2, getloclist(0, #{idx: 0}).idx) 1705 call assert_equal(l:middle, bufnr()) 1706 1707 lprevious! 1708 call assert_equal(1, getloclist(0, #{idx: 0}).idx) 1709 call assert_equal(l:first, bufnr()) 1710 endfunc 1711 1712 " Fail :lrewind but :lrewind! is allowed 1713 func Test_lrewind() 1714 CheckFeature quickfix 1715 call s:reset_all_buffers() 1716 1717 let [l:first, l:middle, _] = s:make_simple_location_list() 1718 lnext! 1719 1720 call assert_fails("lrewind", "E1513:") 1721 call assert_equal(l:middle, bufnr()) 1722 1723 lrewind! 1724 call assert_equal(l:first, bufnr()) 1725 endfunc 1726 1727 " Fail :ltag but :ltag! is allowed 1728 func Test_ltag() 1729 call s:reset_all_buffers() 1730 1731 set tags=Xtags 1732 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1733 \ "one\tXfile\t1", 1734 \ "three\tXfile\t3", 1735 \ "two\tXfile\t2"], 1736 \ "Xtags", 'D') 1737 call writefile(["one", "two", "three"], "Xfile", 'D') 1738 call writefile(["one"], "Xother", 'D') 1739 edit Xother 1740 exe "normal \<C-]>" 1741 1742 set winfixbuf 1743 1744 let l:current = bufnr() 1745 1746 call assert_fails("ltag one", "E1513:") 1747 1748 ltag! one 1749 1750 set tags& 1751 endfunc 1752 1753 " Fail vim.cmd if we try to change buffers while 'winfixbuf' is set 1754 func Test_lua_command() 1755 " CheckFeature lua 1756 call s:reset_all_buffers() 1757 1758 enew 1759 file first 1760 let l:previous = bufnr() 1761 1762 enew 1763 file second 1764 let l:current = bufnr() 1765 1766 set winfixbuf 1767 1768 call assert_fails($'lua vim.cmd("buffer " .. {l:previous})') 1769 call assert_equal(l:current, bufnr()) 1770 1771 exe $'lua vim.cmd("buffer! " .. {l:previous})' 1772 call assert_equal(l:previous, bufnr()) 1773 endfunc 1774 1775 " Fail :lvimgrep but :lvimgrep! is allowed 1776 func Test_lvimgrep() 1777 CheckFeature quickfix 1778 call s:reset_all_buffers() 1779 1780 edit first.unittest 1781 call append(0, ["some-search-term"]) 1782 write 1783 1784 edit winfix.unittest 1785 call append(0, ["some-search-term"]) 1786 write 1787 let l:current = bufnr() 1788 1789 set winfixbuf 1790 1791 edit! last.unittest 1792 call append(0, ["some-search-term"]) 1793 write 1794 let l:last = bufnr() 1795 1796 buffer! winfix.unittest 1797 1798 call assert_fails("lvimgrep /some-search-term/ *.unittest", "E1513:") 1799 call assert_equal(l:current, bufnr()) 1800 1801 lvimgrep! /some-search-term/ *.unittest 1802 call assert_notequal(l:current, bufnr()) 1803 1804 call delete("first.unittest") 1805 call delete("winfix.unittest") 1806 call delete("last.unittest") 1807 endfunc 1808 1809 " Fail :lvimgrepadd but :lvimgrepadd! is allowed 1810 func Test_lvimgrepadd() 1811 CheckFeature quickfix 1812 call s:reset_all_buffers() 1813 1814 edit first.unittest 1815 call append(0, ["some-search-term"]) 1816 write 1817 1818 edit winfix.unittest 1819 call append(0, ["some-search-term"]) 1820 write 1821 let l:current = bufnr() 1822 1823 set winfixbuf 1824 1825 edit! last.unittest 1826 call append(0, ["some-search-term"]) 1827 write 1828 let l:last = bufnr() 1829 1830 buffer! winfix.unittest 1831 1832 call assert_fails("lvimgrepadd /some-search-term/ *.unittest", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 1833 call assert_equal(l:current, bufnr()) 1834 1835 lvimgrepadd! /some-search-term/ *.unittest 1836 call assert_notequal(l:current, bufnr()) 1837 1838 call delete("first.unittest") 1839 call delete("winfix.unittest") 1840 call delete("last.unittest") 1841 endfunc 1842 1843 " Don't allow global marks to change the current 'winfixbuf' window 1844 func Test_marks_mappings_fail() 1845 call s:reset_all_buffers() 1846 1847 let l:other = s:make_buffer_pairs() 1848 let l:current = bufnr() 1849 exe $"buffer! {l:other}" 1850 normal mA 1851 exe $"buffer! {l:current}" 1852 normal mB 1853 1854 call assert_fails("normal `A", "E1513:") 1855 call assert_equal(l:current, bufnr()) 1856 1857 call assert_fails("normal 'A", "E1513:") 1858 call assert_equal(l:current, bufnr()) 1859 1860 set nowinfixbuf 1861 1862 normal `A 1863 call assert_equal(l:other, bufnr()) 1864 endfunc 1865 1866 " Allow global marks in a 'winfixbuf' window if the jump is the same buffer 1867 func Test_marks_mappings_pass_intra_move() 1868 call s:reset_all_buffers() 1869 1870 let l:current = bufnr() 1871 call append(0, ["some line", "another line"]) 1872 normal mA 1873 normal j 1874 normal mB 1875 1876 set winfixbuf 1877 1878 normal `A 1879 call assert_equal(l:current, bufnr()) 1880 endfunc 1881 1882 " Fail :next but :next! is allowed 1883 func Test_next() 1884 call s:reset_all_buffers() 1885 1886 let [l:first, _] = s:make_args_list() 1887 first! 1888 1889 call assert_fails("next", "E1513:") 1890 call assert_equal(l:first, bufnr()) 1891 1892 next! 1893 call assert_notequal(l:first, bufnr()) 1894 endfunc 1895 1896 " Ensure :mksession saves 'winfixbuf' details 1897 func Test_mksession() 1898 CheckFeature mksession 1899 call s:reset_all_buffers() 1900 1901 set sessionoptions+=options 1902 set winfixbuf 1903 1904 mksession test_winfixbuf_Test_mksession.vim 1905 1906 call s:reset_all_buffers() 1907 let l:winfixbuf = &winfixbuf 1908 call assert_equal(0, l:winfixbuf) 1909 1910 source test_winfixbuf_Test_mksession.vim 1911 1912 let l:winfixbuf = &winfixbuf 1913 call assert_equal(1, l:winfixbuf) 1914 1915 set sessionoptions& 1916 call delete("test_winfixbuf_Test_mksession.vim") 1917 endfunc 1918 1919 " Allow :next if the next index is the same as the current buffer 1920 func Test_next_same_buffer() 1921 call s:reset_all_buffers() 1922 1923 enew 1924 file foo 1925 enew 1926 file bar 1927 enew 1928 file fizz 1929 enew 1930 file buzz 1931 args foo foo bar fizz buzz 1932 1933 edit foo 1934 set winfixbuf 1935 let l:current = bufnr() 1936 1937 " Allow :next because the args list is `[foo] foo bar fizz buzz 1938 next 1939 call assert_equal(l:current, bufnr()) 1940 1941 " Fail :next because the args list is `foo [foo] bar fizz buzz 1942 " and the next buffer would be bar, which is a different buffer 1943 call assert_fails("next", "E1513:") 1944 call assert_equal(l:current, bufnr()) 1945 endfunc 1946 1947 " Fail to jump to a tag with g<C-]> if 'winfixbuf' is enabled 1948 func Test_normal_g_ctrl_square_bracket_right() 1949 call s:reset_all_buffers() 1950 1951 set tags=Xtags 1952 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1953 \ "one\tXfile\t1", 1954 \ "three\tXfile\t3", 1955 \ "two\tXfile\t2"], 1956 \ "Xtags", 'D') 1957 call writefile(["one", "two", "three"], "Xfile", 'D') 1958 call writefile(["one"], "Xother", 'D') 1959 edit Xother 1960 1961 set winfixbuf 1962 1963 let l:current = bufnr() 1964 1965 call assert_fails("normal g\<C-]>", "E1513:") 1966 call assert_equal(l:current, bufnr()) 1967 1968 set tags& 1969 endfunc 1970 1971 " Fail to jump to a tag with g<RightMouse> if 'winfixbuf' is enabled 1972 func Test_normal_g_rightmouse() 1973 call s:reset_all_buffers() 1974 set mouse=n 1975 1976 set tags=Xtags 1977 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1978 \ "one\tXfile\t1", 1979 \ "three\tXfile\t3", 1980 \ "two\tXfile\t2"], 1981 \ "Xtags", 'D') 1982 call writefile(["one", "two", "three"], "Xfile", 'D') 1983 call writefile(["one"], "Xother", 'D') 1984 edit Xother 1985 exe "normal \<C-]>" 1986 1987 set winfixbuf 1988 1989 let l:current = bufnr() 1990 1991 call assert_fails("normal g\<RightMouse>", "E1513:") 1992 call assert_equal(l:current, bufnr()) 1993 1994 set tags& 1995 set mouse& 1996 endfunc 1997 1998 " Fail to jump to a tag with g] if 'winfixbuf' is enabled 1999 func Test_normal_g_square_bracket_right() 2000 call s:reset_all_buffers() 2001 2002 set tags=Xtags 2003 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2004 \ "one\tXfile\t1", 2005 \ "three\tXfile\t3", 2006 \ "two\tXfile\t2"], 2007 \ "Xtags", 'D') 2008 call writefile(["one", "two", "three"], "Xfile", 'D') 2009 call writefile(["one"], "Xother", 'D') 2010 edit Xother 2011 2012 set winfixbuf 2013 2014 let l:current = bufnr() 2015 2016 call assert_fails("normal g]", "E1513:") 2017 call assert_equal(l:current, bufnr()) 2018 2019 set tags& 2020 endfunc 2021 2022 " Fail to jump to a tag with <C-RightMouse> if 'winfixbuf' is enabled 2023 func Test_normal_ctrl_rightmouse() 2024 call s:reset_all_buffers() 2025 set mouse=n 2026 2027 set tags=Xtags 2028 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2029 \ "one\tXfile\t1", 2030 \ "three\tXfile\t3", 2031 \ "two\tXfile\t2"], 2032 \ "Xtags", 'D') 2033 call writefile(["one", "two", "three"], "Xfile", 'D') 2034 call writefile(["one"], "Xother", 'D') 2035 edit Xother 2036 exe "normal \<C-]>" 2037 2038 set winfixbuf 2039 2040 let l:current = bufnr() 2041 2042 call assert_fails("normal \<C-RightMouse>", "E1513:") 2043 call assert_equal(l:current, bufnr()) 2044 2045 set tags& 2046 set mouse& 2047 endfunc 2048 2049 " Fail to jump to a tag with <C-t> if 'winfixbuf' is enabled 2050 func Test_normal_ctrl_t() 2051 call s:reset_all_buffers() 2052 2053 set tags=Xtags 2054 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2055 \ "one\tXfile\t1", 2056 \ "three\tXfile\t3", 2057 \ "two\tXfile\t2"], 2058 \ "Xtags", 'D') 2059 call writefile(["one", "two", "three"], "Xfile", 'D') 2060 call writefile(["one"], "Xother", 'D') 2061 edit Xother 2062 exe "normal \<C-]>" 2063 2064 set winfixbuf 2065 2066 let l:current = bufnr() 2067 2068 call assert_fails("normal \<C-t>", "E1513:") 2069 call assert_equal(l:current, bufnr()) 2070 2071 set tags& 2072 endfunc 2073 2074 " Disallow <C-^> in 'winfixbuf' windows 2075 func Test_normal_ctrl_hat() 2076 call s:reset_all_buffers() 2077 clearjumps 2078 2079 enew 2080 file first 2081 let l:first = bufnr() 2082 2083 enew 2084 file current 2085 let l:current = bufnr() 2086 2087 set winfixbuf 2088 2089 call assert_fails("normal \<C-^>", "E1513:") 2090 call assert_equal(l:current, bufnr()) 2091 endfunc 2092 2093 " Allow <C-i> in 'winfixbuf' windows if the movement stays within the buffer 2094 func Test_normal_ctrl_i_pass() 2095 call s:reset_all_buffers() 2096 clearjumps 2097 2098 enew 2099 file first 2100 let l:first = bufnr() 2101 2102 enew! 2103 file current 2104 let l:current = bufnr() 2105 " Add some lines so we can populate a jumplist" 2106 call append(0, ["some line", "another line"]) 2107 " Add an entry to the jump list 2108 " Go up another line 2109 normal m` 2110 normal k 2111 exe "normal \<C-o>" 2112 2113 set winfixbuf 2114 2115 let l:line = getcurpos()[1] 2116 exe "normal 1\<C-i>" 2117 call assert_notequal(l:line, getcurpos()[1]) 2118 endfunc 2119 2120 " Disallow <C-o> in 'winfixbuf' windows if it would cause the buffer to switch 2121 func Test_normal_ctrl_o_fail() 2122 call s:reset_all_buffers() 2123 clearjumps 2124 2125 enew 2126 file first 2127 let l:first = bufnr() 2128 2129 enew 2130 file current 2131 let l:current = bufnr() 2132 2133 set winfixbuf 2134 2135 call assert_fails("normal \<C-o>", "E1513:") 2136 call assert_equal(l:current, bufnr()) 2137 endfunc 2138 2139 " Allow <C-o> in 'winfixbuf' windows if the movement stays within the buffer 2140 func Test_normal_ctrl_o_pass() 2141 call s:reset_all_buffers() 2142 clearjumps 2143 2144 enew 2145 file first 2146 let l:first = bufnr() 2147 2148 enew! 2149 file current 2150 let l:current = bufnr() 2151 " Add some lines so we can populate a jumplist 2152 call append(0, ["some line", "another line"]) 2153 " Add an entry to the jump list 2154 " Go up another line 2155 normal m` 2156 normal k 2157 2158 set winfixbuf 2159 2160 exe "normal \<C-o>" 2161 call assert_equal(l:current, bufnr()) 2162 endfunc 2163 2164 " Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled 2165 func Test_normal_ctrl_square_bracket_right() 2166 call s:reset_all_buffers() 2167 2168 set tags=Xtags 2169 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2170 \ "one\tXfile\t1", 2171 \ "three\tXfile\t3", 2172 \ "two\tXfile\t2"], 2173 \ "Xtags", 'D') 2174 call writefile(["one", "two", "three"], "Xfile", 'D') 2175 call writefile(["one"], "Xother", 'D') 2176 edit Xother 2177 2178 set winfixbuf 2179 2180 let l:current = bufnr() 2181 2182 call assert_fails("normal \<C-]>", "E1513:") 2183 call assert_equal(l:current, bufnr()) 2184 2185 set tags& 2186 endfunc 2187 2188 " Allow <C-w><C-]> with 'winfixbuf' enabled because it runs in a new, split window 2189 func Test_normal_ctrl_w_ctrl_square_bracket_right() 2190 call s:reset_all_buffers() 2191 2192 set tags=Xtags 2193 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2194 \ "one\tXfile\t1", 2195 \ "three\tXfile\t3", 2196 \ "two\tXfile\t2"], 2197 \ "Xtags", 'D') 2198 call writefile(["one", "two", "three"], "Xfile", 'D') 2199 call writefile(["one"], "Xother", 'D') 2200 edit Xother 2201 2202 set winfixbuf 2203 2204 let l:current_windows = s:get_windows_count() 2205 exe "normal \<C-w>\<C-]>" 2206 call assert_equal(l:current_windows + 1, s:get_windows_count()) 2207 2208 set tags& 2209 endfunc 2210 2211 " Allow <C-w>g<C-]> with 'winfixbuf' enabled because it runs in a new, split window 2212 func Test_normal_ctrl_w_g_ctrl_square_bracket_right() 2213 call s:reset_all_buffers() 2214 2215 set tags=Xtags 2216 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2217 \ "one\tXfile\t1", 2218 \ "three\tXfile\t3", 2219 \ "two\tXfile\t2"], 2220 \ "Xtags", 'D') 2221 call writefile(["one", "two", "three"], "Xfile", 'D') 2222 call writefile(["one"], "Xother", 'D') 2223 edit Xother 2224 2225 set winfixbuf 2226 2227 let l:current_windows = s:get_windows_count() 2228 exe "normal \<C-w>g\<C-]>" 2229 call assert_equal(l:current_windows + 1, s:get_windows_count()) 2230 2231 set tags& 2232 endfunc 2233 2234 " Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled 2235 func Test_normal_gt() 2236 call s:reset_all_buffers() 2237 2238 set tags=Xtags 2239 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2240 \ "one\tXfile\t1", 2241 \ "three\tXfile\t3", 2242 \ "two\tXfile\t2"], 2243 \ "Xtags", 'D') 2244 call writefile(["one", "two", "three"], "Xfile", 'D') 2245 call writefile(["one", "two", "three"], "Xother", 'D') 2246 edit Xother 2247 2248 set winfixbuf 2249 2250 let l:current = bufnr() 2251 2252 call assert_fails("normal \<C-]>", "E1513:") 2253 call assert_equal(l:current, bufnr()) 2254 2255 set tags& 2256 endfunc 2257 2258 " Prevent gF from switching a 'winfixbuf' window's buffer 2259 func Test_normal_gF() 2260 call s:reset_all_buffers() 2261 2262 let l:file = tempname() 2263 call append(0, [l:file]) 2264 call writefile([], l:file, 'D') 2265 " Place the cursor onto the line that has `l:file` 2266 normal gg 2267 " Prevent Vim from erroring with "No write since last change @ command 2268 " line" when we try to call gF, later. 2269 set hidden 2270 2271 set winfixbuf 2272 2273 let l:buffer = bufnr() 2274 2275 call assert_fails("normal gF", "E1513:") 2276 call assert_equal(l:buffer, bufnr()) 2277 2278 set nowinfixbuf 2279 2280 normal gF 2281 call assert_notequal(l:buffer, bufnr()) 2282 2283 set nohidden 2284 endfunc 2285 2286 " Prevent gf from switching a 'winfixbuf' window's buffer 2287 func Test_normal_gf() 2288 call s:reset_all_buffers() 2289 2290 let l:file = tempname() 2291 call append(0, [l:file]) 2292 call writefile([], l:file, 'D') 2293 " Place the cursor onto the line that has `l:file` 2294 normal gg 2295 " Prevent Vim from erroring with "No write since last change @ command 2296 " line" when we try to call gf, later. 2297 set hidden 2298 2299 set winfixbuf 2300 2301 let l:buffer = bufnr() 2302 2303 call assert_fails("normal gf", "E1513:") 2304 call assert_equal(l:buffer, bufnr()) 2305 2306 set nowinfixbuf 2307 2308 normal gf 2309 call assert_notequal(l:buffer, bufnr()) 2310 2311 set nohidden 2312 endfunc 2313 2314 " Fail "goto file under the cursor" (using [f, which is the same as `:normal gf`) 2315 func Test_normal_square_bracket_left_f() 2316 call s:reset_all_buffers() 2317 2318 let l:file = tempname() 2319 call append(0, [l:file]) 2320 call writefile([], l:file, 'D') 2321 " Place the cursor onto the line that has `l:file` 2322 normal gg 2323 " Prevent Vim from erroring with "No write since last change @ command 2324 " line" when we try to call gf, later. 2325 set hidden 2326 2327 set winfixbuf 2328 2329 let l:buffer = bufnr() 2330 2331 call assert_fails("normal [f", "E1513:") 2332 call assert_equal(l:buffer, bufnr()) 2333 2334 set nowinfixbuf 2335 2336 normal [f 2337 call assert_notequal(l:buffer, bufnr()) 2338 2339 set nohidden 2340 endfunc 2341 2342 " Fail to go to a C macro with [<C-d> if 'winfixbuf' is enabled 2343 func Test_normal_square_bracket_left_ctrl_d() 2344 call s:reset_all_buffers() 2345 2346 let l:include_file = tempname() .. ".h" 2347 call writefile(["min(1, 12);", 2348 \ $'#include "{l:include_file}"' 2349 \ ], 2350 \ "main.c", 'D') 2351 call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') 2352 edit main.c 2353 normal ]\<C-d> 2354 2355 set winfixbuf 2356 2357 let l:current = bufnr() 2358 2359 call assert_fails("normal [\<C-d>", "E1513:") 2360 call assert_equal(l:current, bufnr()) 2361 2362 set nowinfixbuf 2363 2364 exe "normal [\<C-d>" 2365 call assert_notequal(l:current, bufnr()) 2366 endfunc 2367 2368 " Fail to go to a C macro with ]<C-d> if 'winfixbuf' is enabled 2369 func Test_normal_square_bracket_right_ctrl_d() 2370 call s:reset_all_buffers() 2371 2372 let l:include_file = tempname() .. ".h" 2373 call writefile(["min(1, 12);", 2374 \ $'#include "{l:include_file}"' 2375 \ ], 2376 \ "main.c", 'D') 2377 call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') 2378 edit main.c 2379 2380 set winfixbuf 2381 2382 let l:current = bufnr() 2383 2384 call assert_fails("normal ]\<C-d>", "E1513:") 2385 call assert_equal(l:current, bufnr()) 2386 2387 set nowinfixbuf 2388 2389 exe "normal ]\<C-d>" 2390 call assert_notequal(l:current, bufnr()) 2391 endfunc 2392 2393 " Fail to go to a C macro with [<C-i> if 'winfixbuf' is enabled 2394 func Test_normal_square_bracket_left_ctrl_i() 2395 call s:reset_all_buffers() 2396 2397 let l:include_file = tempname() .. ".h" 2398 call writefile([$'#include "{l:include_file}"', 2399 \ "min(1, 12);", 2400 \ ], 2401 \ "main.c", 'D') 2402 call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') 2403 edit main.c 2404 " Move to the line with `min(1, 12);` on it" 2405 normal j 2406 2407 set define=^\\s*#\\s*define 2408 set include=^\\s*#\\s*include 2409 set path=.,/usr/include,, 2410 2411 let l:current = bufnr() 2412 2413 set winfixbuf 2414 2415 call assert_fails("normal [\<C-i>", "E1513:") 2416 2417 set nowinfixbuf 2418 2419 exe "normal [\<C-i>" 2420 call assert_notequal(l:current, bufnr()) 2421 2422 set define& 2423 set include& 2424 set path& 2425 endfunc 2426 2427 " Fail to go to a C macro with ]<C-i> if 'winfixbuf' is enabled 2428 func Test_normal_square_bracket_right_ctrl_i() 2429 call s:reset_all_buffers() 2430 2431 let l:include_file = tempname() .. ".h" 2432 call writefile(["min(1, 12);", 2433 \ $'#include "{l:include_file}"' 2434 \ ], 2435 \ "main.c", 'D') 2436 call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') 2437 edit main.c 2438 2439 set winfixbuf 2440 2441 set define=^\\s*#\\s*define 2442 set include=^\\s*#\\s*include 2443 set path=.,/usr/include,, 2444 2445 let l:current = bufnr() 2446 2447 call assert_fails("normal ]\<C-i>", "E1513:") 2448 call assert_equal(l:current, bufnr()) 2449 2450 set nowinfixbuf 2451 2452 exe "normal ]\<C-i>" 2453 call assert_notequal(l:current, bufnr()) 2454 2455 set define& 2456 set include& 2457 set path& 2458 endfunc 2459 2460 " Fail "goto file under the cursor" (using ]f, which is the same as `:normal gf`) 2461 func Test_normal_square_bracket_right_f() 2462 call s:reset_all_buffers() 2463 2464 let l:file = tempname() 2465 call append(0, [l:file]) 2466 call writefile([], l:file, 'D') 2467 " Place the cursor onto the line that has `l:file` 2468 normal gg 2469 " Prevent Vim from erroring with "No write since last change @ command 2470 " line" when we try to call gf, later. 2471 set hidden 2472 2473 set winfixbuf 2474 2475 let l:buffer = bufnr() 2476 2477 call assert_fails("normal ]f", "E1513:") 2478 call assert_equal(l:buffer, bufnr()) 2479 2480 set nowinfixbuf 2481 2482 normal ]f 2483 call assert_notequal(l:buffer, bufnr()) 2484 2485 set nohidden 2486 endfunc 2487 2488 " Fail to jump to a tag with v<C-]> if 'winfixbuf' is enabled 2489 func Test_normal_v_ctrl_square_bracket_right() 2490 call s:reset_all_buffers() 2491 2492 set tags=Xtags 2493 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2494 \ "one\tXfile\t1", 2495 \ "three\tXfile\t3", 2496 \ "two\tXfile\t2"], 2497 \ "Xtags", 'D') 2498 call writefile(["one", "two", "three"], "Xfile", 'D') 2499 call writefile(["one"], "Xother", 'D') 2500 edit Xother 2501 2502 set winfixbuf 2503 2504 let l:current = bufnr() 2505 2506 call assert_fails("normal v\<C-]>", "E1513:") 2507 call assert_equal(l:current, bufnr()) 2508 2509 set tags& 2510 endfunc 2511 2512 " Fail to jump to a tag with vg<C-]> if 'winfixbuf' is enabled 2513 func Test_normal_v_g_ctrl_square_bracket_right() 2514 call s:reset_all_buffers() 2515 2516 set tags=Xtags 2517 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2518 \ "one\tXfile\t1", 2519 \ "three\tXfile\t3", 2520 \ "two\tXfile\t2"], 2521 \ "Xtags", 'D') 2522 call writefile(["one", "two", "three"], "Xfile", 'D') 2523 call writefile(["one"], "Xother", 'D') 2524 edit Xother 2525 2526 set winfixbuf 2527 2528 let l:current = bufnr() 2529 2530 call assert_fails("normal vg\<C-]>", "E1513:") 2531 call assert_equal(l:current, bufnr()) 2532 2533 set tags& 2534 endfunc 2535 2536 " Allow :pedit because, unlike :edit, it uses a separate window 2537 func Test_pedit() 2538 call s:reset_all_buffers() 2539 2540 let l:other = s:make_buffer_pairs() 2541 2542 pedit other 2543 2544 exe "normal \<C-w>w" 2545 call assert_equal(l:other, bufnr()) 2546 endfunc 2547 2548 " Allow :pbuffer because, unlike :buffer, it uses a separate window 2549 func Test_pbuffer() 2550 call s:reset_all_buffers() 2551 2552 let l:other = s:make_buffer_pairs() 2553 2554 exe $'pbuffer {l:other}' 2555 2556 exe "normal \<C-w>w" 2557 call assert_equal(l:other, bufnr()) 2558 endfunc 2559 2560 " Fail :pop but :pop! is allowed 2561 func Test_pop() 2562 call s:reset_all_buffers() 2563 2564 set tags=Xtags 2565 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2566 \ "thesame\tXfile\t1;\"\td\tfile:", 2567 \ "thesame\tXfile\t2;\"\td\tfile:", 2568 \ "thesame\tXfile\t3;\"\td\tfile:", 2569 \ ], 2570 \ "Xtags", 'D') 2571 call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') 2572 call writefile(["thesame one"], "Xother", 'D') 2573 edit Xother 2574 2575 tag thesame 2576 2577 set winfixbuf 2578 2579 let l:current = bufnr() 2580 2581 call assert_fails("pop", "E1513:") 2582 call assert_equal(l:current, bufnr()) 2583 2584 pop! 2585 call assert_notequal(l:current, bufnr()) 2586 2587 set tags& 2588 endfunc 2589 2590 " Fail :previous but :previous! is allowed 2591 func Test_previous() 2592 call s:reset_all_buffers() 2593 2594 let [l:first, _] = s:make_args_list() 2595 next! 2596 2597 call assert_fails("previous", "E1513:") 2598 call assert_notequal(l:first, bufnr()) 2599 2600 previous! 2601 call assert_equal(l:first, bufnr()) 2602 endfunc 2603 2604 " Fail pyxdo if it changes a window with 'winfixbuf' is set 2605 func Test_pythonx_pyxdo() 2606 CheckFeature pythonx 2607 call s:reset_all_buffers() 2608 2609 enew 2610 file first 2611 let g:_previous_buffer = bufnr() 2612 2613 enew 2614 file second 2615 2616 set winfixbuf 2617 2618 pythonx << EOF 2619 import vim 2620 2621 def test_winfixbuf_Test_pythonx_pyxdo_set_buffer(): 2622 buffer = vim.vars['_previous_buffer'] 2623 vim.current.buffer = vim.buffers[buffer] 2624 EOF 2625 2626 try 2627 pyxdo test_winfixbuf_Test_pythonx_pyxdo_set_buffer() 2628 catch /pynvim\.api\.common\.NvimError: Vim:E1513:/ 2629 let l:caught = 1 2630 endtry 2631 2632 call assert_equal(1, l:caught) 2633 2634 unlet g:_previous_buffer 2635 endfunc 2636 2637 " Fail pyxfile if it changes a window with 'winfixbuf' is set 2638 func Test_pythonx_pyxfile() 2639 CheckFeature pythonx 2640 call s:reset_all_buffers() 2641 2642 enew 2643 file first 2644 let g:_previous_buffer = bufnr() 2645 2646 enew 2647 file second 2648 2649 set winfixbuf 2650 2651 call writefile(["import vim", 2652 \ "buffer = vim.vars['_previous_buffer']", 2653 \ "vim.current.buffer = vim.buffers[buffer]", 2654 \ ], 2655 \ "file.py", 'D') 2656 2657 try 2658 pyxfile file.py 2659 catch /pynvim\.api\.common\.NvimError: Vim:E1513:/ 2660 let l:caught = 1 2661 endtry 2662 2663 call assert_equal(1, l:caught) 2664 2665 unlet g:_previous_buffer 2666 endfunc 2667 2668 " Fail vim.current.buffer if 'winfixbuf' is set 2669 func Test_pythonx_vim_current_buffer() 2670 CheckFeature pythonx 2671 call s:reset_all_buffers() 2672 2673 enew 2674 file first 2675 let g:_previous_buffer = bufnr() 2676 2677 enew 2678 file second 2679 2680 let l:caught = 0 2681 2682 set winfixbuf 2683 2684 try 2685 pythonx << EOF 2686 import vim 2687 2688 buffer = vim.vars["_previous_buffer"] 2689 vim.current.buffer = vim.buffers[buffer] 2690 EOF 2691 catch /pynvim\.api\.common\.NvimError: Vim:E1513:/ 2692 let l:caught = 1 2693 endtry 2694 2695 call assert_equal(1, l:caught) 2696 unlet g:_previous_buffer 2697 endfunc 2698 2699 " Ensure remapping to a disabled action still triggers failures 2700 func Test_remap_key_fail() 2701 call s:reset_all_buffers() 2702 2703 enew 2704 file first 2705 let l:first = bufnr() 2706 2707 enew 2708 file current 2709 let l:current = bufnr() 2710 2711 set winfixbuf 2712 2713 nnoremap g <C-^> 2714 2715 call assert_fails("normal g", "E1513:") 2716 call assert_equal(l:current, bufnr()) 2717 2718 nunmap g 2719 endfunc 2720 2721 " Ensure remapping a disabled key to something valid does trigger any failures 2722 func Test_remap_key_pass() 2723 call s:reset_all_buffers() 2724 2725 enew 2726 file first 2727 let l:first = bufnr() 2728 2729 enew 2730 file current 2731 let l:current = bufnr() 2732 2733 set winfixbuf 2734 2735 call assert_fails("normal \<C-^>", "E1513:") 2736 call assert_equal(l:current, bufnr()) 2737 2738 " Disallow <C-^> by default but allow it if the command does something else 2739 nnoremap <C-^> :echo "hello!" 2740 2741 exe "normal \<C-^>" 2742 call assert_equal(l:current, bufnr()) 2743 2744 nunmap <C-^> 2745 endfunc 2746 2747 " Fail :rewind but :rewind! is allowed 2748 func Test_rewind() 2749 call s:reset_all_buffers() 2750 2751 let [l:first, _] = s:make_args_list() 2752 next! 2753 2754 call assert_fails("rewind", "E1513:") 2755 call assert_notequal(l:first, bufnr()) 2756 2757 rewind! 2758 call assert_equal(l:first, bufnr()) 2759 endfunc 2760 2761 " Allow :sblast because it opens the buffer in a new, split window 2762 func Test_sblast() 2763 call s:reset_all_buffers() 2764 2765 let l:other = s:make_buffer_pairs(1) 2766 bfirst! 2767 let l:current = bufnr() 2768 2769 sblast 2770 call assert_equal(l:other, bufnr()) 2771 endfunc 2772 2773 " Fail :sbprevious but :sbprevious! is allowed 2774 func Test_sbprevious() 2775 call s:reset_all_buffers() 2776 2777 let l:other = s:make_buffer_pairs() 2778 let l:current = bufnr() 2779 2780 sbprevious 2781 call assert_equal(l:other, bufnr()) 2782 endfunc 2783 2784 " Make sure 'winfixbuf' can be set using 'winfixbuf' or 'wfb' 2785 func Test_short_option() 2786 call s:reset_all_buffers() 2787 2788 call s:make_buffer_pairs() 2789 2790 set winfixbuf 2791 call assert_fails("edit something_else", "E1513:") 2792 2793 set nowinfixbuf 2794 set wfb 2795 call assert_fails("edit another_place", "E1513:") 2796 2797 set nowfb 2798 edit last_place 2799 endfunc 2800 2801 " Allow :snext because it makes a new window 2802 func Test_snext() 2803 call s:reset_all_buffers() 2804 2805 let [l:first, _] = s:make_args_list() 2806 first! 2807 2808 let l:current_window = win_getid() 2809 2810 snext 2811 call assert_notequal(l:current_window, win_getid()) 2812 call assert_notequal(l:first, bufnr()) 2813 endfunc 2814 2815 " Ensure the first has 'winfixbuf' and a new split window is 'nowinfixbuf' 2816 func Test_split_window() 2817 call s:reset_all_buffers() 2818 2819 split 2820 exe "normal \<C-w>j" 2821 2822 set winfixbuf 2823 2824 let l:winfix_window_1 = win_getid() 2825 vsplit 2826 let l:winfix_window_2 = win_getid() 2827 2828 call assert_equal(1, getwinvar(l:winfix_window_1, "&winfixbuf")) 2829 call assert_equal(0, getwinvar(l:winfix_window_2, "&winfixbuf")) 2830 endfunc 2831 2832 " Fail :tNext but :tNext! is allowed 2833 func Test_tNext() 2834 call s:reset_all_buffers() 2835 2836 set tags=Xtags 2837 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2838 \ "thesame\tXfile\t1;\"\td\tfile:", 2839 \ "thesame\tXfile\t2;\"\td\tfile:", 2840 \ "thesame\tXfile\t3;\"\td\tfile:", 2841 \ ], 2842 \ "Xtags", 'D') 2843 call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') 2844 call writefile(["thesame one"], "Xother", 'D') 2845 edit Xother 2846 2847 tag thesame 2848 exe "normal \<C-^>" 2849 tnext! 2850 2851 set winfixbuf 2852 2853 let l:current = bufnr() 2854 2855 call assert_fails("tNext", "E1513:") 2856 call assert_equal(l:current, bufnr()) 2857 2858 tNext! 2859 2860 set tags& 2861 endfunc 2862 2863 " Call :tabdo and choose the next available 'nowinfixbuf' window. 2864 func Test_tabdo_choose_available_window() 2865 call s:reset_all_buffers() 2866 2867 let [l:first, _] = s:make_args_list() 2868 2869 " Make a split window that is 'nowinfixbuf' but make it the second-to-last 2870 " window so that :tabdo will first try the 'winfixbuf' window, pass over it, 2871 " and prefer the other 'nowinfixbuf' window, instead. 2872 " 2873 " +-------------------+ 2874 " | 'nowinfixbuf' | 2875 " +-------------------+ 2876 " | 'winfixbuf' | <-- Cursor is here 2877 " +-------------------+ 2878 split 2879 let l:nowinfixbuf_window = win_getid() 2880 " Move to the 'winfixbuf' window now 2881 exe "normal \<C-w>j" 2882 let l:winfixbuf_window = win_getid() 2883 2884 let l:expected_windows = s:get_windows_count() 2885 tabdo echo '' 2886 call assert_equal(l:nowinfixbuf_window, win_getid()) 2887 call assert_equal(l:first, bufnr()) 2888 call assert_equal(l:expected_windows, s:get_windows_count()) 2889 endfunc 2890 2891 " Call :tabdo and create a new split window if all available windows are 'winfixbuf'. 2892 func Test_tabdo_make_new_window() 2893 call s:reset_all_buffers() 2894 2895 let [l:first, _] = s:make_buffers_list() 2896 exe $"buffer! {l:first}" 2897 2898 let l:current = win_getid() 2899 let l:current_windows = s:get_windows_count() 2900 2901 tabdo echo '' 2902 call assert_notequal(l:current, win_getid()) 2903 call assert_equal(l:first, bufnr()) 2904 exe "normal \<C-w>j" 2905 call assert_equal(l:first, bufnr()) 2906 call assert_equal(l:current_windows + 1, s:get_windows_count()) 2907 endfunc 2908 2909 " Fail :tag but :tag! is allowed 2910 func Test_tag() 2911 call s:reset_all_buffers() 2912 2913 set tags=Xtags 2914 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2915 \ "one\tXfile\t1", 2916 \ "three\tXfile\t3", 2917 \ "two\tXfile\t2"], 2918 \ "Xtags", 'D') 2919 call writefile(["one", "two", "three"], "Xfile", 'D') 2920 call writefile(["one"], "Xother", 'D') 2921 edit Xother 2922 2923 set winfixbuf 2924 2925 let l:current = bufnr() 2926 2927 call assert_fails("tag one", "E1513:") 2928 call assert_equal(l:current, bufnr()) 2929 2930 tag! one 2931 call assert_notequal(l:current, bufnr()) 2932 2933 set tags& 2934 endfunc 2935 2936 2937 " Fail :tfirst but :tfirst! is allowed 2938 func Test_tfirst() 2939 call s:reset_all_buffers() 2940 2941 set tags=Xtags 2942 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2943 \ "one\tXfile\t1", 2944 \ "three\tXfile\t3", 2945 \ "two\tXfile\t2"], 2946 \ "Xtags", 'D') 2947 call writefile(["one", "two", "three"], "Xfile", 'D') 2948 call writefile(["one"], "Xother", 'D') 2949 tag one 2950 edit Xother 2951 2952 set winfixbuf 2953 2954 let l:current = bufnr() 2955 2956 call assert_fails("tfirst", "E1513:") 2957 call assert_equal(l:current, bufnr()) 2958 2959 tfirst! 2960 call assert_notequal(l:current, bufnr()) 2961 2962 set tags& 2963 endfunc 2964 2965 " Fail :tjump but :tjump! is allowed 2966 func Test_tjump() 2967 call s:reset_all_buffers() 2968 2969 set tags=Xtags 2970 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2971 \ "one\tXfile\t1", 2972 \ "three\tXfile\t3", 2973 \ "two\tXfile\t2"], 2974 \ "Xtags", 'D') 2975 call writefile(["one", "two", "three"], "Xfile", 'D') 2976 call writefile(["one"], "Xother", 'D') 2977 edit Xother 2978 2979 set winfixbuf 2980 2981 let l:current = bufnr() 2982 2983 call assert_fails("tjump one", "E1513:") 2984 call assert_equal(l:current, bufnr()) 2985 2986 tjump! one 2987 call assert_notequal(l:current, bufnr()) 2988 2989 set tags& 2990 endfunc 2991 2992 " Fail :tlast but :tlast! is allowed 2993 func Test_tlast() 2994 call s:reset_all_buffers() 2995 2996 set tags=Xtags 2997 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 2998 \ "one\tXfile\t1", 2999 \ "three\tXfile\t3", 3000 \ "two\tXfile\t2"], 3001 \ "Xtags", 'D') 3002 call writefile(["one", "two", "three"], "Xfile", 'D') 3003 edit Xfile 3004 tjump one 3005 edit Xfile 3006 3007 set winfixbuf 3008 3009 let l:current = bufnr() 3010 3011 call assert_fails("tlast", "E1513:") 3012 call assert_equal(l:current, bufnr()) 3013 3014 tlast! 3015 call assert_equal(l:current, bufnr()) 3016 3017 set tags& 3018 endfunc 3019 3020 " Fail :tnext but :tnext! is allowed 3021 func Test_tnext() 3022 call s:reset_all_buffers() 3023 3024 set tags=Xtags 3025 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 3026 \ "thesame\tXfile\t1;\"\td\tfile:", 3027 \ "thesame\tXfile\t2;\"\td\tfile:", 3028 \ "thesame\tXfile\t3;\"\td\tfile:", 3029 \ ], 3030 \ "Xtags", 'D') 3031 call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') 3032 call writefile(["thesame one"], "Xother", 'D') 3033 edit Xother 3034 3035 tag thesame 3036 exe "normal \<C-^>" 3037 3038 set winfixbuf 3039 3040 let l:current = bufnr() 3041 3042 call assert_fails("tnext", "E1513:") 3043 call assert_equal(l:current, bufnr()) 3044 3045 tnext! 3046 call assert_notequal(l:current, bufnr()) 3047 3048 set tags& 3049 endfunc 3050 3051 " Fail :tprevious but :tprevious! is allowed 3052 func Test_tprevious() 3053 call s:reset_all_buffers() 3054 3055 set tags=Xtags 3056 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 3057 \ "thesame\tXfile\t1;\"\td\tfile:", 3058 \ "thesame\tXfile\t2;\"\td\tfile:", 3059 \ "thesame\tXfile\t3;\"\td\tfile:", 3060 \ ], 3061 \ "Xtags", 'D') 3062 call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') 3063 call writefile(["thesame one"], "Xother", 'D') 3064 edit Xother 3065 3066 tag thesame 3067 exe "normal \<C-^>" 3068 tnext! 3069 3070 set winfixbuf 3071 3072 let l:current = bufnr() 3073 3074 call assert_fails("tprevious", "E1513:") 3075 call assert_equal(l:current, bufnr()) 3076 3077 tprevious! 3078 3079 set tags& 3080 endfunc 3081 3082 " Fail :view but :view! is allowed 3083 func Test_view() 3084 call s:reset_all_buffers() 3085 3086 let l:other = s:make_buffer_pairs() 3087 let l:current = bufnr() 3088 3089 call assert_fails("view other", "E1513:") 3090 call assert_equal(l:current, bufnr()) 3091 3092 view! other 3093 call assert_equal(l:other, bufnr()) 3094 endfunc 3095 3096 " Fail :visual but :visual! is allowed 3097 func Test_visual() 3098 call s:reset_all_buffers() 3099 3100 let l:other = s:make_buffer_pairs() 3101 let l:current = bufnr() 3102 3103 call assert_fails("visual other", "E1513:") 3104 call assert_equal(l:current, bufnr()) 3105 3106 visual! other 3107 call assert_equal(l:other, bufnr()) 3108 endfunc 3109 3110 " Fail :vimgrep but :vimgrep! is allowed 3111 func Test_vimgrep() 3112 CheckFeature quickfix 3113 call s:reset_all_buffers() 3114 3115 edit first.unittest 3116 call append(0, ["some-search-term"]) 3117 write 3118 3119 edit winfix.unittest 3120 call append(0, ["some-search-term"]) 3121 write 3122 let l:current = bufnr() 3123 3124 set winfixbuf 3125 3126 edit! last.unittest 3127 call append(0, ["some-search-term"]) 3128 write 3129 let l:last = bufnr() 3130 3131 buffer! winfix.unittest 3132 3133 call assert_fails("vimgrep /some-search-term/ *.unittest", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 3134 call assert_equal(l:current, bufnr()) 3135 3136 " Don't error and also do swap to the first match because ! was included 3137 vimgrep! /some-search-term/ *.unittest 3138 call assert_notequal(l:current, bufnr()) 3139 3140 call delete("first.unittest") 3141 call delete("winfix.unittest") 3142 call delete("last.unittest") 3143 endfunc 3144 3145 " Fail :vimgrepadd but ::vimgrepadd! is allowed 3146 func Test_vimgrepadd() 3147 CheckFeature quickfix 3148 call s:reset_all_buffers() 3149 3150 edit first.unittest 3151 call append(0, ["some-search-term"]) 3152 write 3153 3154 edit winfix.unittest 3155 call append(0, ["some-search-term"]) 3156 write 3157 let l:current = bufnr() 3158 3159 set winfixbuf 3160 3161 edit! last.unittest 3162 call append(0, ["some-search-term"]) 3163 write 3164 let l:last = bufnr() 3165 3166 buffer! winfix.unittest 3167 3168 call assert_fails("vimgrepadd /some-search-term/ *.unittest", "E1513: Cannot switch buffer. 'winfixbuf' is enabled") 3169 call assert_equal(l:current, bufnr()) 3170 3171 vimgrepadd! /some-search-term/ *.unittest 3172 call assert_notequal(l:current, bufnr()) 3173 call delete("first.unittest") 3174 call delete("winfix.unittest") 3175 call delete("last.unittest") 3176 endfunc 3177 3178 " Fail :wNext but :wNext! is allowed 3179 func Test_wNext() 3180 call s:reset_all_buffers() 3181 3182 let [l:first, _] = s:make_args_list() 3183 next! 3184 3185 call assert_fails("wNext", "E1513:") 3186 call assert_notequal(l:first, bufnr()) 3187 3188 wNext! 3189 call assert_equal(l:first, bufnr()) 3190 3191 call delete("first") 3192 call delete("middle") 3193 call delete("last") 3194 endfunc 3195 3196 " Allow :windo unless `:windo foo` would change a 'winfixbuf' window's buffer 3197 func Test_windo() 3198 call s:reset_all_buffers() 3199 3200 let l:current_window = win_getid() 3201 let l:current_buffer = bufnr() 3202 split 3203 enew 3204 file some_other_buffer 3205 3206 set winfixbuf 3207 3208 let l:current = win_getid() 3209 3210 windo echo '' 3211 call assert_equal(l:current_window, win_getid()) 3212 3213 call assert_fails($'exe "windo buffer {l:current_buffer}"', "E1513:") 3214 call assert_equal(l:current_window, win_getid()) 3215 3216 exe $"windo buffer! {l:current_buffer}" 3217 call assert_equal(l:current_window, win_getid()) 3218 endfunc 3219 3220 " Fail :wnext but :wnext! is allowed 3221 func Test_wnext() 3222 call s:reset_all_buffers() 3223 3224 let [_, l:last] = s:make_args_list() 3225 next! 3226 3227 call assert_fails("wnext", "E1513:") 3228 call assert_notequal(l:last, bufnr()) 3229 3230 wnext! 3231 call assert_equal(l:last, bufnr()) 3232 3233 call delete("first") 3234 call delete("middle") 3235 call delete("last") 3236 endfunc 3237 3238 " Fail :wprevious but :wprevious! is allowed 3239 func Test_wprevious() 3240 call s:reset_all_buffers() 3241 3242 let [l:first, _] = s:make_args_list() 3243 next! 3244 3245 call assert_fails("wprevious", "E1513:") 3246 call assert_notequal(l:first, bufnr()) 3247 3248 wprevious! 3249 call assert_equal(l:first, bufnr()) 3250 3251 call delete("first") 3252 call delete("middle") 3253 call delete("last") 3254 endfunc 3255 3256 func Test_quickfix_switchbuf_invalid_prevwin() 3257 call s:reset_all_buffers() 3258 3259 call s:make_simple_quickfix() 3260 call assert_equal(1, getqflist(#{idx: 0}).idx) 3261 3262 set switchbuf=uselast 3263 split 3264 copen 3265 exe winnr('#') 'quit' 3266 call assert_equal(2, winnr('$')) 3267 3268 cnext " Would've triggered a null pointer member access 3269 call assert_equal(2, getqflist(#{idx: 0}).idx) 3270 3271 set switchbuf& 3272 endfunc 3273 3274 func Test_listdo_goto_prevwin() 3275 call s:reset_all_buffers() 3276 call s:make_buffers_list() 3277 3278 new 3279 call assert_equal(0, &winfixbuf) 3280 wincmd p 3281 call assert_equal(1, &winfixbuf) 3282 call assert_notequal(bufnr(), bufnr('#')) 3283 3284 augroup ListDoGotoPrevwin 3285 au! 3286 au BufLeave * let s:triggered = 1 3287 \| call assert_equal(bufnr(), winbufnr(winnr())) 3288 augroup END 3289 " Should correctly switch to the window without 'winfixbuf', and curbuf should 3290 " be consistent with curwin->w_buffer for autocommands. 3291 bufdo " 3292 call assert_equal(0, &winfixbuf) 3293 call assert_equal(1, s:triggered) 3294 unlet! s:triggered 3295 au! ListDoGotoPrevwin 3296 3297 set winfixbuf 3298 wincmd p 3299 call assert_equal(2, winnr('$')) 3300 " Both curwin and prevwin have 'winfixbuf' set, so should split a new window 3301 " without it set. 3302 bufdo " 3303 call assert_equal(0, &winfixbuf) 3304 call assert_equal(3, winnr('$')) 3305 3306 quit 3307 call assert_equal(2, winnr('$')) 3308 call assert_equal(1, &winfixbuf) 3309 augroup ListDoGotoPrevwin 3310 au! 3311 au WinEnter * ++once set winfixbuf 3312 augroup END 3313 " Same as before, but naughty autocommands set 'winfixbuf' for the new window. 3314 " :bufdo should give up in this case. 3315 call assert_fails('bufdo "', 'E1513:') 3316 3317 au! ListDoGotoPrevwin 3318 augroup! ListDoGotoPrevwin 3319 endfunc 3320 3321 func Test_quickfix_changed_split_failed() 3322 call s:reset_all_buffers() 3323 3324 call s:make_simple_quickfix() 3325 call assert_equal(1, winnr('$')) 3326 3327 " Quickfix code will open a split in an attempt to get a 'nowinfixbuf' window 3328 " to switch buffers in. Interfere with things by setting 'winfixbuf' in it. 3329 augroup QfChanged 3330 au! 3331 au WinEnter * ++once call assert_equal(2, winnr('$')) 3332 \| set winfixbuf | call setqflist([], 'f') 3333 augroup END 3334 call assert_fails('cnext', ['E1513:', 'E925:']) 3335 " Check that the split was automatically closed. 3336 call assert_equal(1, winnr('$')) 3337 3338 au! QfChanged 3339 augroup! QfChanged 3340 endfunc 3341 3342 func Test_bufdo_cnext_splitwin_fails() 3343 call s:reset_all_buffers() 3344 call s:make_simple_quickfix() 3345 call assert_equal(1, getqflist(#{idx: 0}).idx) 3346 " Make sure there is not enough room to 3347 " split the winfixedbuf window 3348 let &winheight=&lines 3349 let &winminheight=&lines-2 3350 " Still want E1513, or it may not be clear why a split was attempted and why 3351 " it failing caused the commands to abort. 3352 call assert_fails(':bufdo echo 1', ['E36:', 'E1513:']) 3353 call assert_fails(':cnext', ['E36:', 'E1513:']) 3354 " Ensure the entry didn't change. 3355 call assert_equal(1, getqflist(#{idx: 0}).idx) 3356 set winminheight&vim winheight&vim 3357 endfunc 3358 3359 " Test that exiting with 'winfixbuf' and EXITFREE doesn't cause an error. 3360 func Test_exitfree_no_error() 3361 let lines =<< trim END 3362 set winfixbuf 3363 qall! 3364 END 3365 call writefile(lines, 'Xwfb_exitfree', 'D') 3366 call assert_notmatch('E1513:', 3367 "\ system(GetVimCommandClean() .. ' --not-a-term -X -S Xwfb_exitfree')) 3368 \ system(GetVimCommandClean() .. ' -X -S Xwfb_exitfree')) 3369 endfunc 3370 3371 " vim: shiftwidth=2 sts=2 expandtab