test_tagjump.vim (47028B)
1 " Tests for tagjump (tags and special searches) 2 3 source check.vim 4 source screendump.vim 5 6 " SEGV occurs in older versions. (At least 7.4.1748 or older) 7 func Test_ptag_with_notagstack() 8 CheckFeature quickfix 9 10 set notagstack 11 call assert_fails('ptag does_not_exist_tag_name', 'E433') 12 set tagstack&vim 13 endfunc 14 15 func Test_ptjump() 16 CheckFeature quickfix 17 18 set tags=Xpttags 19 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 20 \ "one\tXptfile\t1", 21 \ "three\tXptfile\t3", 22 \ "two\tXptfile\t2"], 23 \ 'Xpttags', 'D') 24 call writefile(['one', 'two', 'three'], 'Xptfile', 'D') 25 26 %bw! 27 ptjump two 28 call assert_equal(2, winnr()) 29 wincmd p 30 call assert_equal(1, &previewwindow) 31 call assert_equal('Xptfile', expand("%:p:t")) 32 call assert_equal(2, line('.')) 33 call assert_equal(2, winnr('$')) 34 call assert_equal(1, winnr()) 35 close 36 call setline(1, ['one', 'two', 'three']) 37 exe "normal 3G\<C-W>g}" 38 call assert_equal(2, winnr()) 39 wincmd p 40 call assert_equal(1, &previewwindow) 41 call assert_equal('Xptfile', expand("%:p:t")) 42 call assert_equal(3, line('.')) 43 call assert_equal(2, winnr('$')) 44 call assert_equal(1, winnr()) 45 close 46 exe "normal 3G5\<C-W>\<C-G>}" 47 wincmd p 48 call assert_equal(5, winheight(0)) 49 close 50 51 set tags& 52 endfunc 53 54 func Test_cancel_ptjump() 55 CheckFeature quickfix 56 57 set tags=Xtags 58 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 59 \ "word\tfile1\tcmd1", 60 \ "word\tfile2\tcmd2"], 61 \ 'Xtags', 'D') 62 63 only! 64 call feedkeys(":ptjump word\<CR>\<CR>", "xt") 65 help 66 call assert_equal(2, winnr('$')) 67 68 set tags& 69 quit 70 endfunc 71 72 func Test_static_tagjump() 73 set tags=Xtjtags 74 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 75 \ "one\tXtjfile1\t/^one/;\"\tf\tfile:\tsignature:(void)", 76 \ "word\tXtjfile2\tcmd2"], 77 \ 'Xtjtags', 'D') 78 new Xtjfile1 79 call setline(1, ['empty', 'one()', 'empty']) 80 write 81 tag one 82 call assert_equal(2, line('.')) 83 84 bwipe! 85 set tags& 86 call delete('Xtjfile1') 87 endfunc 88 89 func Test_duplicate_tagjump() 90 set tags=Xdttags 91 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 92 \ "thesame\tXdtfile1\t1;\"\td\tfile:", 93 \ "thesame\tXdtfile1\t2;\"\td\tfile:", 94 \ "thesame\tXdtfile1\t3;\"\td\tfile:", 95 \ ], 96 \ 'Xdttags', 'D') 97 new Xdtfile1 98 call setline(1, ['thesame one', 'thesame two', 'thesame three']) 99 write 100 tag thesame 101 call assert_equal(1, line('.')) 102 tnext 103 call assert_equal(2, line('.')) 104 tnext 105 call assert_equal(3, line('.')) 106 107 bwipe! 108 set tags& 109 call delete('Xdtfile1') 110 endfunc 111 112 func Test_tagjump_switchbuf() 113 CheckFeature quickfix 114 115 set tags=Xswtags 116 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 117 \ "second\tXsbfile1\t2", 118 \ "third\tXsbfile1\t3",], 119 \ 'Xswtags', 'D') 120 call writefile(['first', 'second', 'third'], 'Xsbfile1', 'D') 121 122 enew | only 123 set switchbuf= 124 stag second 125 call assert_equal(2, winnr('$')) 126 call assert_equal(2, line('.')) 127 stag third 128 call assert_equal(3, winnr('$')) 129 call assert_equal(3, line('.')) 130 131 enew | only 132 set switchbuf=useopen 133 stag second 134 call assert_equal(2, winnr('$')) 135 call assert_equal(2, line('.')) 136 stag third 137 call assert_equal(2, winnr('$')) 138 call assert_equal(3, line('.')) 139 140 enew | only 141 set switchbuf=usetab 142 tab stag second 143 call assert_equal(2, tabpagenr('$')) 144 call assert_equal(2, line('.')) 145 1tabnext | stag third 146 call assert_equal(2, tabpagenr('$')) 147 call assert_equal(3, line('.')) 148 tabonly 149 150 " use a vertically split window 151 enew | only 152 set switchbuf=vsplit 153 stag third 154 call assert_equal(2, winnr('$')) 155 call assert_equal(1, winnr()) 156 call assert_equal(3, line('.')) 157 call assert_equal(['row', [['leaf', win_getid(1)], ['leaf', win_getid(2)]]], winlayout()) 158 159 " jump to a tag in a new tabpage 160 enew | only 161 set switchbuf=newtab 162 stag second 163 call assert_equal(2, tabpagenr('$')) 164 call assert_equal(2, tabpagenr()) 165 call assert_equal(2, line('.')) 166 0tab stag third 167 call assert_equal(3, tabpagenr('$')) 168 call assert_equal(1, tabpagenr()) 169 call assert_equal(3, line('.')) 170 171 tabclose! 172 tabclose! 173 enew | only 174 set tags& 175 set switchbuf&vim 176 endfunc 177 178 " Tests for [ CTRL-I and CTRL-W CTRL-I commands 179 function Test_keyword_jump() 180 call writefile(["#include Xinclude", "", 181 \ "", 182 \ "/* test text test tex start here", 183 \ " some text", 184 \ " test text", 185 \ " start OK if found this line", 186 \ " start found wrong line", 187 \ "test text"], 'Xtestfile') 188 call writefile(["/* test text test tex start here", 189 \ " some text", 190 \ " test text", 191 \ " start OK if found this line", 192 \ " start found wrong line", 193 \ "test text"], 'Xinclude') 194 new Xtestfile 195 call cursor(1,1) 196 call search("start") 197 exe "normal! 5[\<C-I>" 198 call assert_equal(" start OK if found this line", getline('.')) 199 call cursor(1,1) 200 call search("start") 201 exe "normal! 5\<C-W>\<C-I>" 202 call assert_equal(" start OK if found this line", getline('.')) 203 204 " invalid tag search pattern 205 call assert_fails('tag /\%(/', 'E426:') 206 207 enew! | only 208 call delete('Xtestfile') 209 call delete('Xinclude') 210 endfunction 211 212 " Test for jumping to a tag with 'hidden' set, with symbolic link in path of 213 " tag. This only works for Unix, because of the symbolic link. 214 func Test_tag_symbolic() 215 if !has('unix') 216 return 217 endif 218 set hidden 219 call delete("Xtest.dir", "rf") 220 call system("ln -s . Xtest.dir") 221 " Create a tags file with the current directory name inserted. 222 call writefile([ 223 \ "SECTION_OFF " . getcwd() . "/Xtest.dir/Xtest.c /^#define SECTION_OFF 3$/", 224 \ '', 225 \ ], 'Xtags') 226 call writefile(['#define SECTION_OFF 3', 227 \ '#define NUM_SECTIONS 3'], 'Xtest.c') 228 229 " Try jumping to a tag, but with a path that contains a symbolic link. When 230 " wrong, this will give the ATTENTION message. The next space will then be 231 " eaten by hit-return, instead of moving the cursor to 'd'. 232 set tags=Xtags 233 enew! 234 call append(0, 'SECTION_OFF') 235 call cursor(1,1) 236 exe "normal \<C-]> " 237 call assert_equal('Xtest.c', expand('%:t')) 238 call assert_equal(2, col('.')) 239 240 set nohidden " Accommodate Nvim default 241 set tags& 242 enew! 243 call delete('Xtags') 244 call delete('Xtest.c') 245 call delete("Xtest.dir", "rf") 246 %bwipe! 247 endfunc 248 249 " Tests for tag search with !_TAG_FILE_ENCODING. 250 func Test_tag_file_encoding() 251 if has('vms') 252 throw 'Skipped: does not work on VMS' 253 endif 254 255 if !has('iconv') || iconv("\x82\x60", "cp932", "utf-8") != "\uff21" 256 throw 'Skipped: iconv does not work' 257 endif 258 259 let save_enc = &encoding 260 set encoding=utf8 261 262 let content = ['text for tags1', 'abcdefghijklmnopqrs'] 263 call writefile(content, 'Xtags1.txt') 264 let content = ['text for tags2', 'ABC'] 265 call writefile(content, 'Xtags2.txt') 266 let content = ['text for tags3', 'ABC'] 267 call writefile(content, 'Xtags3.txt') 268 let content = ['!_TAG_FILE_ENCODING utf-8 //', 'abcdefghijklmnopqrs Xtags1.txt /abcdefghijklmnopqrs'] 269 call writefile(content, 'Xtags1') 270 271 " case1: 272 new 273 set tags=Xtags1 274 tag abcdefghijklmnopqrs 275 call assert_equal('Xtags1.txt', expand('%:t')) 276 call assert_equal('abcdefghijklmnopqrs', getline('.')) 277 close 278 279 " case2: 280 new 281 let content = ['!_TAG_FILE_ENCODING cp932 //', 282 \ "\x82`\x82a\x82b Xtags2.txt /\x82`\x82a\x82b"] 283 call writefile(content, 'Xtags') 284 set tags=Xtags 285 tag /.BC 286 call assert_equal('Xtags2.txt', expand('%:t')) 287 call assert_equal('ABC', getline('.')) 288 call delete('Xtags') 289 close 290 291 " case3: 292 new 293 let contents = [ 294 \ "!_TAG_FILE_SORTED 1 //", 295 \ "!_TAG_FILE_ENCODING cp932 //"] 296 for i in range(1, 100) 297 call add(contents, 'abc' .. i 298 \ .. " Xtags3.txt /\x82`\x82a\x82b") 299 endfor 300 call writefile(contents, 'Xtags') 301 set tags=Xtags 302 tag abc50 303 call assert_equal('Xtags3.txt', expand('%:t')) 304 call assert_equal('ABC', getline('.')) 305 call delete('Xtags') 306 close 307 308 set tags& 309 let &encoding = save_enc 310 call delete('Xtags1.txt') 311 call delete('Xtags2.txt') 312 call delete('Xtags3.txt') 313 call delete('Xtags1') 314 endfunc 315 316 " Test for emacs-style tags file (TAGS) 317 func Test_tagjump_etags() 318 if !has('emacs_tags') 319 return 320 endif 321 call writefile([ 322 \ "void foo() {}", 323 \ "int main(int argc, char **argv)", 324 \ "{", 325 \ "\tfoo();", 326 \ "\treturn 0;", 327 \ "}", 328 \ ], 'Xmain.c') 329 330 call writefile([ 331 \ "\x0c", 332 \ "Xmain.c,64", 333 \ "void foo() {}\x7ffoo\x011,0", 334 \ "int main(int argc, char **argv)\x7fmain\x012,14", 335 \ ], 'Xtags') 336 set tags=Xtags 337 ta foo 338 call assert_equal('void foo() {}', getline('.')) 339 340 " Test for including another tags file 341 call writefile([ 342 \ "\x0c", 343 \ "Xmain.c,64", 344 \ "void foo() {}\x7ffoo\x011,0", 345 \ "\x0c", 346 \ "Xnonexisting,include", 347 \ "\x0c", 348 \ "Xtags2,include" 349 \ ], 'Xtags') 350 call writefile([ 351 \ "\x0c", 352 \ "Xmain.c,64", 353 \ "int main(int argc, char **argv)\x7fmain\x012,14", 354 \ ], 'Xtags2') 355 tag main 356 call assert_equal(2, line('.')) 357 call assert_fails('tag bar', 'E426:') 358 359 " corrupted tag line 360 call writefile([ 361 \ "\x0c", 362 \ "Xmain.c,8", 363 \ "int main" 364 \ ], 'Xtags', 'b') 365 call assert_fails('tag foo', 'E426:') 366 367 " invalid line number 368 call writefile([ 369 \ "\x0c", 370 \ "Xmain.c,64", 371 \ "void foo() {}\x7ffoo\x0abc,0", 372 \ ], 'Xtags') 373 call assert_fails('tag foo', 'E426:') 374 375 " invalid tag name 376 call writefile([ 377 \ "\x0c", 378 \ "Xmain.c,64", 379 \ ";;;;\x7f1,0", 380 \ ], 'Xtags') 381 call assert_fails('tag foo', 'E431:') 382 383 " end of file after a CTRL-L line 384 call writefile([ 385 \ "\x0c", 386 \ "Xmain.c,64", 387 \ "void foo() {}\x7ffoo\x011,0", 388 \ "\x0c", 389 \ ], 'Xtags') 390 call assert_fails('tag main', 'E426:') 391 392 " error in an included tags file 393 call writefile([ 394 \ "\x0c", 395 \ "Xtags2,include" 396 \ ], 'Xtags') 397 call writefile([ 398 \ "\x0c", 399 \ "Xmain.c,64", 400 \ "void foo() {}", 401 \ ], 'Xtags2') 402 call assert_fails('tag foo', 'E431:') 403 404 call delete('Xtags') 405 call delete('Xtags2') 406 call delete('Xmain.c') 407 set tags& 408 bwipe! 409 endfunc 410 411 " Test for getting and modifying the tag stack 412 func Test_getsettagstack() 413 call writefile(['line1', 'line2', 'line3'], 'Xfile1') 414 call writefile(['line1', 'line2', 'line3'], 'Xfile2') 415 call writefile(['line1', 'line2', 'line3'], 'Xfile3') 416 417 enew | only 418 call settagstack(1, {'items' : []}) 419 call assert_equal(0, gettagstack(1).length) 420 call assert_equal([], 1->gettagstack().items) 421 " Error cases 422 call assert_equal({}, gettagstack(100)) 423 call assert_equal(-1, settagstack(100, {'items' : []})) 424 call assert_fails('call settagstack(1, [1, 10])', 'E1206:') 425 call assert_fails("call settagstack(1, {'items' : 10})", 'E714:') 426 call assert_fails("call settagstack(1, {'items' : []}, 10)", 'E1174:') 427 call assert_fails("call settagstack(1, {'items' : []}, 'b')", 'E962:') 428 call assert_equal(-1, settagstack(0, v:_null_dict)) 429 430 set tags=Xtags 431 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 432 \ "one\tXfile1\t1", 433 \ "three\tXfile3\t3", 434 \ "two\tXfile2\t2"], 435 \ 'Xtags') 436 437 let stk = [] 438 call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'one', 439 \ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1}) 440 tag one 441 call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'two', 442 \ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1}) 443 tag two 444 call add(stk, {'bufnr' : bufnr('%'), 'tagname' : 'three', 445 \ 'from' : [bufnr('%'), line('.'), col('.'), 0], 'matchnr' : 1}) 446 tag three 447 call assert_equal(3, gettagstack(1).length) 448 call assert_equal(stk, gettagstack(1).items) 449 " Check for default - current window 450 call assert_equal(3, gettagstack().length) 451 call assert_equal(stk, gettagstack().items) 452 453 " Try to set current index to invalid values 454 call settagstack(1, {'curidx' : -1}) 455 call assert_equal(1, gettagstack().curidx) 456 eval {'curidx' : 50}->settagstack(1) 457 call assert_equal(4, gettagstack().curidx) 458 459 " Try pushing invalid items onto the stack 460 call settagstack(1, {'items' : []}) 461 call settagstack(1, {'items' : ["plate"]}, 'a') 462 call assert_equal(0, gettagstack().length) 463 call assert_equal([], gettagstack().items) 464 call settagstack(1, {'items' : [{"tagname" : "abc"}]}, 'a') 465 call assert_equal(0, gettagstack().length) 466 call assert_equal([], gettagstack().items) 467 call settagstack(1, {'items' : [{"from" : 100}]}, 'a') 468 call assert_equal(0, gettagstack().length) 469 call assert_equal([], gettagstack().items) 470 call settagstack(1, {'items' : [{"from" : [2, 1, 0, 0]}]}, 'a') 471 call assert_equal(0, gettagstack().length) 472 call assert_equal([], gettagstack().items) 473 474 " Push one item at a time to the stack 475 call settagstack(1, {'items' : []}) 476 call settagstack(1, {'items' : [stk[0]]}, 'a') 477 call settagstack(1, {'items' : [stk[1]]}, 'a') 478 call settagstack(1, {'items' : [stk[2]]}, 'a') 479 call settagstack(1, {'curidx' : 4}) 480 call assert_equal({'length' : 3, 'curidx' : 4, 'items' : stk}, 481 \ gettagstack(1)) 482 483 " Try pushing items onto a full stack 484 for i in range(7) 485 call settagstack(1, {'items' : stk}, 'a') 486 endfor 487 call assert_equal(20, gettagstack().length) 488 call settagstack(1, 489 \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 'a') 490 call assert_equal('abc', gettagstack().items[19].tagname) 491 492 " truncate the tag stack 493 call settagstack(1, 494 \ {'curidx' : 9, 495 \ 'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't') 496 let t = gettagstack() 497 call assert_equal(9, t.length) 498 call assert_equal(10, t.curidx) 499 500 " truncate the tag stack without pushing any new items 501 call settagstack(1, {'curidx' : 5}, 't') 502 let t = gettagstack() 503 call assert_equal(4, t.length) 504 call assert_equal(5, t.curidx) 505 506 " truncate an empty tag stack and push new items 507 call settagstack(1, {'items' : []}) 508 call settagstack(1, 509 \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't') 510 let t = gettagstack() 511 call assert_equal(1, t.length) 512 call assert_equal(2, t.curidx) 513 514 " Tag with multiple matches 515 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 516 \ "two\tXfile1\t1", 517 \ "two\tXfile2\t3", 518 \ "two\tXfile3\t2"], 519 \ 'Xtags') 520 call settagstack(1, {'items' : []}) 521 tag two 522 tnext 523 tnext 524 call assert_equal(1, gettagstack().length) 525 call assert_equal(3, gettagstack().items[0].matchnr) 526 527 call settagstack(1, {'items' : []}) 528 call delete('Xfile1') 529 call delete('Xfile2') 530 call delete('Xfile3') 531 call delete('Xtags') 532 set tags& 533 endfunc 534 535 func Test_tag_with_count() 536 call writefile([ 537 \ 'test Xtest.h /^void test();$/;" p typeref:typename:void signature:()', 538 \ ], 'Xtags') 539 call writefile([ 540 \ 'main Xtest.c /^int main()$/;" f typeref:typename:int signature:()', 541 \ 'test Xtest.c /^void test()$/;" f typeref:typename:void signature:()', 542 \ ], 'Ytags') 543 cal writefile([ 544 \ 'int main()', 545 \ 'void test()', 546 \ ], 'Xtest.c') 547 cal writefile([ 548 \ 'void test();', 549 \ ], 'Xtest.h') 550 set tags=Xtags,Ytags 551 552 new Xtest.c 553 let tl = taglist('test', 'Xtest.c') 554 call assert_equal(tl[0].filename, 'Xtest.c') 555 call assert_equal(tl[1].filename, 'Xtest.h') 556 557 tag test 558 call assert_equal(bufname('%'), 'Xtest.c') 559 1tag test 560 call assert_equal(bufname('%'), 'Xtest.c') 561 2tag test 562 call assert_equal(bufname('%'), 'Xtest.h') 563 564 set tags& 565 call delete('Xtags') 566 call delete('Ytags') 567 bwipe Xtest.h 568 bwipe Xtest.c 569 call delete('Xtest.h') 570 call delete('Xtest.c') 571 endfunc 572 573 func Test_tagnr_recall() 574 call writefile([ 575 \ 'test Xtest.h /^void test();$/;" p', 576 \ 'main Xtest.c /^int main()$/;" f', 577 \ 'test Xtest.c /^void test()$/;" f', 578 \ ], 'Xtags') 579 cal writefile([ 580 \ 'int main()', 581 \ 'void test()', 582 \ ], 'Xtest.c') 583 cal writefile([ 584 \ 'void test();', 585 \ ], 'Xtest.h') 586 set tags=Xtags 587 588 new Xtest.c 589 let tl = taglist('test', 'Xtest.c') 590 call assert_equal(tl[0].filename, 'Xtest.c') 591 call assert_equal(tl[1].filename, 'Xtest.h') 592 593 2tag test 594 call assert_equal(bufname('%'), 'Xtest.h') 595 pop 596 call assert_equal(bufname('%'), 'Xtest.c') 597 tag 598 call assert_equal(bufname('%'), 'Xtest.h') 599 600 set tags& 601 call delete('Xtags') 602 bwipe Xtest.h 603 bwipe Xtest.c 604 call delete('Xtest.h') 605 call delete('Xtest.c') 606 endfunc 607 608 func Test_tag_line_toolong() 609 call writefile([ 610 \ '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 django/contrib/admin/templates/admin/edit_inline/stacked.html 16;" j line:16 language:HTML' 611 \ ], 'Xtags') 612 set tags=Xtags 613 let old_vbs = &verbose 614 set verbose=5 615 " ":tjump" should give "tag not found" not "Format error in tags file" 616 call assert_fails('tj /foo', 'E426') 617 try 618 tj /foo 619 catch /^Vim\%((\a\+)\)\=:E431/ 620 call assert_report(v:exception) 621 catch /.*/ 622 endtry 623 call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1]) 624 625 call writefile([ 626 \ '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 django/contrib/admin/templates/admin/edit_inline/stacked.html 16;" j line:16 language:HTML' 627 \ ], 'Xtags') 628 call assert_fails('tj /foo', 'E426') 629 try 630 tj /foo 631 catch /^Vim\%((\a\+)\)\=:E431/ 632 call assert_report(v:exception) 633 catch /.*/ 634 endtry 635 call assert_equal('Searching tags file Xtags', split(execute('messages'), '\n')[-1]) 636 637 " binary search works in file with long line 638 call writefile([ 639 \ 'asdfasfd nowhere 16', 640 \ 'foobar Xsomewhere 3; " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567', 641 \ 'zasdfasfd nowhere 16', 642 \ ], 'Xtags') 643 call writefile([ 644 \ 'one', 645 \ 'two', 646 \ 'trhee', 647 \ 'four', 648 \ ], 'Xsomewhere') 649 tag foobar 650 call assert_equal('Xsomewhere', expand('%')) 651 call assert_equal(3, getcurpos()[1]) 652 653 " expansion on command line works with long lines when &wildoptions contains 654 " 'tagfile' 655 set wildoptions=tagfile 656 call writefile([ 657 \ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa file /^pattern$/;" f' 658 \ ], 'Xtags') 659 call feedkeys(":tag \<Tab>", 'tx') 660 " Should not crash 661 call assert_true(v:true) 662 663 call delete('Xtags') 664 call delete('Xsomewhere') 665 set tags& 666 let &verbose = old_vbs 667 endfunc 668 669 " Check that using :tselect does not run into the hit-enter prompt. 670 " Requires a terminal to trigger that prompt. 671 func Test_tselect() 672 CheckScreendump 673 674 call writefile([ 675 \ 'main Xtest.h /^void test();$/;" f', 676 \ 'main Xtest.c /^int main()$/;" f', 677 \ 'main Xtest.x /^void test()$/;" f', 678 \ ], 'Xtags') 679 cal writefile([ 680 \ 'int main()', 681 \ 'void test()', 682 \ ], 'Xtest.c') 683 684 let lines =<< trim [SCRIPT] 685 set tags=Xtags 686 [SCRIPT] 687 call writefile(lines, 'XTest_tselect') 688 let buf = RunVimInTerminal('-S XTest_tselect', {'rows': 10, 'cols': 50}) 689 690 call TermWait(buf, 50) 691 call term_sendkeys(buf, ":tselect main\<CR>2\<CR>") 692 call VerifyScreenDump(buf, 'Test_tselect_1', {}) 693 694 call StopVimInTerminal(buf) 695 call delete('Xtags') 696 call delete('Xtest.c') 697 call delete('XTest_tselect') 698 endfunc 699 700 func Test_tagline() 701 call writefile([ 702 \ 'provision Xtest.py /^ def provision(self, **kwargs):$/;" m line:1 language:Python class:Foo', 703 \ 'provision Xtest.py /^ def provision(self, **kwargs):$/;" m line:3 language:Python class:Bar', 704 \], 'Xtags') 705 call writefile([ 706 \ ' def provision(self, **kwargs):', 707 \ ' pass', 708 \ ' def provision(self, **kwargs):', 709 \ ' pass', 710 \], 'Xtest.py') 711 712 set tags=Xtags 713 714 1tag provision 715 call assert_equal(line('.'), 1) 716 2tag provision 717 call assert_equal(line('.'), 3) 718 719 call delete('Xtags') 720 call delete('Xtest.py') 721 set tags& 722 endfunc 723 724 " Test for expanding environment variable in a tag file name 725 func Test_tag_envvar() 726 call writefile(["Func1\t$FOO\t/^Func1/"], 'Xtags') 727 set tags=Xtags 728 729 let $FOO='TagTestEnv' 730 731 let caught_exception = v:false 732 try 733 tag Func1 734 catch /E429:/ 735 call assert_match('E429:.*"TagTestEnv".*', v:exception) 736 let caught_exception = v:true 737 endtry 738 call assert_true(caught_exception) 739 740 set tags& 741 call delete('Xtags') 742 unlet $FOO 743 endfunc 744 745 " Test for :ptag 746 func Test_tag_preview() 747 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 748 \ "second\tXfile1\t2", 749 \ "third\tXfile1\t3",], 750 \ 'Xtags') 751 set tags=Xtags 752 call writefile(['first', 'second', 'third'], 'Xfile1') 753 754 enew | only 755 ptag third 756 call assert_equal(2, winnr()) 757 call assert_equal(2, winnr('$')) 758 call assert_equal(1, getwinvar(1, '&previewwindow')) 759 call assert_equal(0, getwinvar(2, '&previewwindow')) 760 wincmd P 761 call assert_equal(3, line('.')) 762 763 " jump to the tag again 764 wincmd w 765 ptag third 766 wincmd P 767 call assert_equal(3, line('.')) 768 769 " jump to the newer tag 770 wincmd w 771 ptag 772 wincmd P 773 call assert_equal(3, line('.')) 774 775 " close the preview window 776 pclose 777 call assert_equal(1, winnr('$')) 778 779 call delete('Xfile1') 780 call delete('Xtags') 781 set tags& 782 endfunc 783 784 " Tests for guessing the tag location 785 func Test_tag_guess() 786 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 787 \ "func1\tXfoo\t/^int func1(int x)/", 788 \ "func2\tXfoo\t/^int func2(int y)/", 789 \ "func3\tXfoo\t/^func3/", 790 \ "func4\tXfoo\t/^func4/"], 791 \ 'Xtags') 792 set tags=Xtags 793 let code =<< trim [CODE] 794 795 int FUNC1 (int x) { } 796 int 797 func2 (int y) { } 798 int * func3 () { } 799 800 [CODE] 801 call writefile(code, 'Xfoo') 802 803 let v:statusmsg = '' 804 ta func1 805 call assert_match('E435:', v:statusmsg) 806 call assert_equal(2, line('.')) 807 let v:statusmsg = '' 808 ta func2 809 call assert_match('E435:', v:statusmsg) 810 call assert_equal(4, line('.')) 811 let v:statusmsg = '' 812 ta func3 813 call assert_match('E435:', v:statusmsg) 814 call assert_equal(5, line('.')) 815 call assert_fails('ta func4', 'E434:') 816 817 call delete('Xtags') 818 call delete('Xfoo') 819 set tags& 820 endfunc 821 822 " Test for an unsorted tags file 823 func Test_tag_sort() 824 let l = [ 825 \ "first\tXfoo\t1", 826 \ "ten\tXfoo\t3", 827 \ "six\tXfoo\t2"] 828 call writefile(l, 'Xtags') 829 set tags=Xtags 830 let code =<< trim [CODE] 831 int first() {} 832 int six() {} 833 int ten() {} 834 [CODE] 835 call writefile(code, 'Xfoo') 836 837 call assert_fails('tag first', 'E432:') 838 839 " When multiple tag files are not sorted, then message should be displayed 840 " multiple times 841 call writefile(l, 'Xtags2') 842 set tags=Xtags,Xtags2 843 call assert_fails('tag first', ['E432:', 'E432:']) 844 845 call delete('Xtags') 846 call delete('Xtags2') 847 call delete('Xfoo') 848 set tags& 849 %bwipe 850 endfunc 851 852 " Test for an unsorted tags file 853 func Test_tag_fold() 854 call writefile([ 855 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 856 \ "!_TAG_FILE_SORTED\t2\t/0=unsorted, 1=sorted, 2=foldcase/", 857 \ "first\tXfoo\t1", 858 \ "second\tXfoo\t2", 859 \ "third\tXfoo\t3"], 860 \ 'Xtags') 861 set tags=Xtags 862 let code =<< trim [CODE] 863 int first() {} 864 int second() {} 865 int third() {} 866 [CODE] 867 call writefile(code, 'Xfoo') 868 869 enew 870 tag second 871 call assert_equal('Xfoo', bufname('')) 872 call assert_equal(2, line('.')) 873 874 call delete('Xtags') 875 call delete('Xfoo') 876 set tags& 877 %bwipe 878 endfunc 879 880 " Test for the :ltag command 881 func Test_ltag() 882 call writefile([ 883 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 884 \ "first\tXfoo\t1", 885 \ "second\tXfoo\t/^int second() {}$/", 886 \ "third\tXfoo\t3"], 887 \ 'Xtags') 888 set tags=Xtags 889 let code =<< trim [CODE] 890 int first() {} 891 int second() {} 892 int third() {} 893 [CODE] 894 call writefile(code, 'Xfoo') 895 896 enew 897 call setloclist(0, [], 'f') 898 ltag third 899 call assert_equal('Xfoo', bufname('')) 900 call assert_equal(3, line('.')) 901 call assert_equal([{'lnum': 3, 'end_lnum': 0, 'bufnr': bufnr('Xfoo'), 902 \ 'col': 0, 'end_col': 0, 'pattern': '', 'valid': 1, 'vcol': 0, 903 \ 'nr': 0, 'type': '', 'module': '', 'text': 'third'}], getloclist(0)) 904 905 ltag second 906 call assert_equal(2, line('.')) 907 call assert_equal([{'lnum': 0, 'end_lnum': 0, 'bufnr': bufnr('Xfoo'), 908 \ 'col': 0, 'end_col': 0, 'pattern': '^\Vint second() {}\$', 909 \ 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'module': '', 910 \ 'text': 'second'}], getloclist(0)) 911 912 call delete('Xtags') 913 call delete('Xfoo') 914 set tags& 915 %bwipe 916 endfunc 917 918 " Test for setting the last search pattern to the tag search pattern 919 " when cpoptions has 't' 920 func Test_tag_last_search_pat() 921 call writefile([ 922 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 923 \ "first\tXfoo\t/^int first() {}/", 924 \ "second\tXfoo\t/^int second() {}/", 925 \ "third\tXfoo\t/^int third() {}/"], 926 \ 'Xtags', 'D') 927 set tags=Xtags 928 let code =<< trim [CODE] 929 int first() {} 930 int second() {} 931 int third() {} 932 [CODE] 933 call writefile(code, 'Xfoo', 'D') 934 935 enew 936 let save_cpo = &cpo 937 set cpo+=t 938 let @/ = '' 939 tag second 940 call assert_equal('^int second() {}', @/) 941 let &cpo = save_cpo 942 943 set tags& 944 %bwipe 945 endfunc 946 947 " Tag stack tests 948 func Test_tag_stack() 949 let l = [] 950 for i in range(10, 31) 951 let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"] 952 endfor 953 call writefile(l, 'Xtags', 'D') 954 set tags=Xtags 955 956 let l = [] 957 for i in range(10, 31) 958 let l += ["int var" .. i .. ";"] 959 endfor 960 call writefile(l, 'Xfoo', 'D') 961 962 enew 963 " Jump to a tag when the tag stack is full. Oldest entry should be removed. 964 for i in range(10, 30) 965 exe "tag var" .. i 966 endfor 967 let t = gettagstack() 968 call assert_equal(20, t.length) 969 call assert_equal('var11', t.items[0].tagname) 970 let full = deepcopy(t.items) 971 tag var31 972 let t = gettagstack() 973 call assert_equal('var12', t.items[0].tagname) 974 call assert_equal('var31', t.items[19].tagname) 975 976 " Jump to a tag when the tag stack is full, but with user data this time. 977 call foreach(full, {i, item -> extend(item, {'user_data': $'udata{i}'})}) 978 call settagstack(0, {'items': full}) 979 let t = gettagstack() 980 call assert_equal(20, t.length) 981 call assert_equal('var11', t.items[0].tagname) 982 call assert_equal('udata0', t.items[0].user_data) 983 tag var31 984 let t = gettagstack() 985 call assert_equal('var12', t.items[0].tagname) 986 call assert_equal('udata1', t.items[0].user_data) 987 call assert_equal('var31', t.items[19].tagname) 988 call assert_false(has_key(t.items[19], 'user_data')) 989 990 " Use tnext with a single match 991 call assert_fails('tnext', 'E427:') 992 993 " Jump to newest entry from the top of the stack 994 call assert_fails('tag', 'E556:') 995 996 " Pop with zero count from the top of the stack 997 call assert_fails('0pop', 'E556:') 998 999 " Pop from an unsaved buffer 1000 enew! 1001 call append(1, "sample text") 1002 call assert_fails('pop', 'E37:') 1003 call assert_equal(21, gettagstack().curidx) 1004 enew! 1005 1006 " Pop all the entries in the tag stack 1007 call assert_fails('30pop', 'E555:') 1008 1009 " Pop with a count when already at the bottom of the stack 1010 call assert_fails('exe "normal 4\<C-T>"', 'E555:') 1011 call assert_equal(1, gettagstack().curidx) 1012 1013 " Jump to newest entry from the bottom of the stack with zero count 1014 call assert_fails('0tag', 'E555:') 1015 1016 " Pop the tag stack when it is empty 1017 call settagstack(1, {'items' : []}) 1018 call assert_fails('pop', 'E73:') 1019 1020 " References to wiped buffer are deleted. 1021 for i in range(10, 20) 1022 edit Xtest 1023 exe "tag var" .. i 1024 endfor 1025 edit Xtest 1026 1027 let t = gettagstack() 1028 call assert_equal(11, t.length) 1029 call assert_equal(12, t.curidx) 1030 1031 bwipe! 1032 1033 let t = gettagstack() 1034 call assert_equal(0, t.length) 1035 call assert_equal(1, t.curidx) 1036 1037 " References to wiped buffer are deleted with multiple tabpages. 1038 let w1 = win_getid() 1039 call settagstack(1, {'items' : []}) 1040 for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor 1041 enew 1042 1043 new 1044 let w2 = win_getid() 1045 call settagstack(1, {'items' : []}) 1046 for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor 1047 enew 1048 1049 tabnew 1050 let w3 = win_getid() 1051 call settagstack(1, {'items' : []}) 1052 for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor 1053 enew 1054 1055 new 1056 let w4 = win_getid() 1057 call settagstack(1, {'items' : []}) 1058 for i in range(10, 20) | edit Xtest | exe "tag var" .. i | endfor 1059 enew 1060 1061 for w in [w1, w2, w3, w4] 1062 let t = gettagstack(w) 1063 call assert_equal(11, t.length) 1064 call assert_equal(12, t.curidx) 1065 endfor 1066 1067 bwipe! Xtest 1068 1069 for w in [w1, w2, w3, w4] 1070 let t = gettagstack(w) 1071 call assert_equal(0, t.length) 1072 call assert_equal(1, t.curidx) 1073 endfor 1074 1075 %bwipe! 1076 set tags& 1077 endfunc 1078 1079 " Test for browsing multiple matching tags 1080 func Test_tag_multimatch() 1081 call writefile([ 1082 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1083 \ "first\tXfoo\t1", 1084 \ "first\tXfoo\t2", 1085 \ "first\tXfoo\t3"], 1086 \ 'Xtags') 1087 set tags=Xtags 1088 let code =<< trim [CODE] 1089 int first() {} 1090 int first() {} 1091 int first() {} 1092 [CODE] 1093 call writefile(code, 'Xfoo') 1094 1095 call settagstack(1, {'items' : []}) 1096 tag first 1097 tlast 1098 call assert_equal(3, line('.')) 1099 call assert_fails('tnext', 'E428:') 1100 tfirst 1101 call assert_equal(1, line('.')) 1102 call assert_fails('tprev', 'E425:') 1103 1104 tlast 1105 call feedkeys("5\<CR>", 't') 1106 tselect first 1107 call assert_equal(2, gettagstack().curidx) 1108 1109 set ignorecase 1110 tag FIRST 1111 tnext 1112 call assert_equal(2, line('.')) 1113 tlast 1114 tprev 1115 call assert_equal(2, line('.')) 1116 tNext 1117 call assert_equal(1, line('.')) 1118 set ignorecase& 1119 1120 call delete('Xtags') 1121 call delete('Xfoo') 1122 set tags& 1123 %bwipe 1124 endfunc 1125 1126 " Test for previewing multiple matching tags 1127 func Test_preview_tag_multimatch() 1128 call writefile([ 1129 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1130 \ "first\tXfoo\t1", 1131 \ "first\tXfoo\t2", 1132 \ "first\tXfoo\t3"], 1133 \ 'Xtags') 1134 set tags=Xtags 1135 let code =<< trim [CODE] 1136 int first() {} 1137 int first() {} 1138 int first() {} 1139 [CODE] 1140 call writefile(code, 'Xfoo') 1141 1142 enew | only 1143 ptag first 1144 ptlast 1145 wincmd P 1146 call assert_equal(3, line('.')) 1147 wincmd w 1148 call assert_fails('ptnext', 'E428:') 1149 ptprev 1150 wincmd P 1151 call assert_equal(2, line('.')) 1152 wincmd w 1153 ptfirst 1154 wincmd P 1155 call assert_equal(1, line('.')) 1156 wincmd w 1157 call assert_fails('ptprev', 'E425:') 1158 ptnext 1159 wincmd P 1160 call assert_equal(2, line('.')) 1161 wincmd w 1162 ptlast 1163 call feedkeys("5\<CR>", 't') 1164 ptselect first 1165 wincmd P 1166 call assert_equal(3, line('.')) 1167 1168 pclose 1169 1170 call delete('Xtags') 1171 call delete('Xfoo') 1172 set tags& 1173 %bwipe 1174 endfunc 1175 1176 " Test for jumping to multiple matching tags across multiple :tags commands 1177 func Test_tnext_multimatch() 1178 call writefile([ 1179 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1180 \ "first\tXfoo1\t1", 1181 \ "first\tXfoo2\t1", 1182 \ "first\tXfoo3\t1"], 1183 \ 'Xtags') 1184 set tags=Xtags 1185 let code =<< trim [CODE] 1186 int first() {} 1187 [CODE] 1188 call writefile(code, 'Xfoo1') 1189 call writefile(code, 'Xfoo2') 1190 call writefile(code, 'Xfoo3') 1191 1192 tag first 1193 tag first 1194 pop 1195 tnext 1196 tnext 1197 call assert_fails('tnext', 'E428:') 1198 1199 call delete('Xtags') 1200 call delete('Xfoo1') 1201 call delete('Xfoo2') 1202 call delete('Xfoo3') 1203 set tags& 1204 %bwipe 1205 endfunc 1206 1207 " Test for jumping to multiple matching tags in non-existing files 1208 func Test_multimatch_non_existing_files() 1209 call writefile([ 1210 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1211 \ "first\tXfoo1\t1", 1212 \ "first\tXfoo2\t1", 1213 \ "first\tXfoo3\t1"], 1214 \ 'Xtags') 1215 set tags=Xtags 1216 1217 call settagstack(1, {'items' : []}) 1218 call assert_fails('tag first', 'E429:') 1219 call assert_equal(3, gettagstack().items[0].matchnr) 1220 1221 call delete('Xtags') 1222 set tags& 1223 %bwipe 1224 endfunc 1225 1226 func Test_tselect_listing() 1227 call writefile([ 1228 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1229 \ "first\tXfoo\t1" .. ';"' .. "\tv\ttyperef:typename:int\tfile:", 1230 \ "first\tXfoo\t2" .. ';"' .. "\tkind:v\ttyperef:typename:char\tfile:"], 1231 \ 'Xtags') 1232 set tags=Xtags 1233 1234 let code =<< trim [CODE] 1235 static int first; 1236 static char first; 1237 [CODE] 1238 call writefile(code, 'Xfoo') 1239 1240 call feedkeys("\<CR>", "t") 1241 let l = split(execute("tselect first"), "\n") 1242 let expected =<< [DATA] 1243 # pri kind tag file 1244 1 FS v first Xfoo 1245 typeref:typename:int 1246 1 1247 2 FS v first Xfoo 1248 typeref:typename:char 1249 2 1250 [DATA] 1251 " Type number and <Enter> (q or empty cancels): 1252 " Nvim: Prompt message is sent to cmdline prompt. 1253 1254 call assert_equal(expected, l) 1255 1256 call delete('Xtags') 1257 call delete('Xfoo') 1258 set tags& 1259 %bwipe 1260 endfunc 1261 1262 " Test for :isearch, :ilist, :ijump and :isplit commands 1263 " Test for [i, ]i, [I, ]I, [ CTRL-I, ] CTRL-I and CTRL-W i commands 1264 func Test_inc_search() 1265 new 1266 call setline(1, ['1:foo', '2:foo', 'foo', '3:foo', '4:foo', '===']) 1267 call cursor(3, 1) 1268 1269 " Test for [i and ]i 1270 call assert_equal('1:foo', execute('normal [i')) 1271 call assert_equal('2:foo', execute('normal 2[i')) 1272 call assert_fails('normal 3[i', 'E387:') 1273 call assert_equal('3:foo', execute('normal ]i')) 1274 call assert_equal('4:foo', execute('normal 2]i')) 1275 call assert_fails('normal 3]i', 'E389:') 1276 call assert_fails('normal G]i', 'E349:') 1277 call assert_fails('normal [i', 'E349:') 1278 call cursor(3, 1) 1279 1280 " Test for :isearch 1281 call assert_equal('1:foo', execute('isearch foo')) 1282 call assert_equal('3:foo', execute('isearch 4 /foo/')) 1283 call assert_fails('isearch 3 foo', 'E387:') 1284 call assert_equal('3:foo', execute('+1,$isearch foo')) 1285 call assert_fails('1,.-1isearch 3 foo', 'E389:') 1286 call assert_fails('isearch bar', 'E389:') 1287 call assert_fails('isearch /foo/3', 'E488:') 1288 1289 " Test for [I and ]I 1290 call assert_equal([ 1291 \ ' 1: 1 1:foo', 1292 \ ' 2: 2 2:foo', 1293 \ ' 3: 3 foo', 1294 \ ' 4: 4 3:foo', 1295 \ ' 5: 5 4:foo'], split(execute('normal [I'), "\n")) 1296 call assert_equal([ 1297 \ ' 1: 4 3:foo', 1298 \ ' 2: 5 4:foo'], split(execute('normal ]I'), "\n")) 1299 call assert_fails('normal G]I', 'E349:') 1300 call assert_fails('normal [I', 'E349:') 1301 call cursor(3, 1) 1302 1303 " Test for :ilist 1304 call assert_equal([ 1305 \ ' 1: 1 1:foo', 1306 \ ' 2: 2 2:foo', 1307 \ ' 3: 3 foo', 1308 \ ' 4: 4 3:foo', 1309 \ ' 5: 5 4:foo'], split(execute('ilist foo'), "\n")) 1310 call assert_equal([ 1311 \ ' 1: 4 3:foo', 1312 \ ' 2: 5 4:foo'], split(execute('+1,$ilist /foo/'), "\n")) 1313 call assert_fails('ilist bar', 'E389:') 1314 1315 " Test for [ CTRL-I and ] CTRL-I 1316 exe "normal [\t" 1317 call assert_equal([1, 3], [line('.'), col('.')]) 1318 exe "normal 2j4[\t" 1319 call assert_equal([4, 3], [line('.'), col('.')]) 1320 call assert_fails("normal k3[\t", 'E387:') 1321 call assert_fails("normal 6[\t", 'E389:') 1322 exe "normal ]\t" 1323 call assert_equal([4, 3], [line('.'), col('.')]) 1324 exe "normal k2]\t" 1325 call assert_equal([5, 3], [line('.'), col('.')]) 1326 call assert_fails("normal 2k3]\t", 'E389:') 1327 call assert_fails("normal G[\t", 'E349:') 1328 call assert_fails("normal ]\t", 'E349:') 1329 call cursor(3, 1) 1330 1331 " Test for :ijump 1332 call cursor(3, 1) 1333 ijump foo 1334 call assert_equal([1, 3], [line('.'), col('.')]) 1335 call cursor(3, 1) 1336 ijump 4 /foo/ 1337 call assert_equal([4, 3], [line('.'), col('.')]) 1338 call cursor(3, 1) 1339 call assert_fails('ijump 3 foo', 'E387:') 1340 +,$ijump 2 foo 1341 call assert_equal([5, 3], [line('.'), col('.')]) 1342 call assert_fails('ijump bar', 'E389:') 1343 1344 " Test for CTRL-W i 1345 call cursor(3, 1) 1346 wincmd i 1347 call assert_equal([1, 3, 3], [line('.'), col('.'), winnr('$')]) 1348 close 1349 5wincmd i 1350 call assert_equal([5, 3, 3], [line('.'), col('.'), winnr('$')]) 1351 close 1352 call assert_fails('3wincmd i', 'E387:') 1353 call assert_fails('6wincmd i', 'E389:') 1354 call assert_fails("normal G\<C-W>i", 'E349:') 1355 call cursor(3, 1) 1356 1357 " Test for :isplit 1358 isplit foo 1359 call assert_equal([1, 3, 3], [line('.'), col('.'), winnr('$')]) 1360 close 1361 isplit 5 /foo/ 1362 call assert_equal([5, 3, 3], [line('.'), col('.'), winnr('$')]) 1363 close 1364 call assert_fails('isplit 3 foo', 'E387:') 1365 call assert_fails('isplit 6 foo', 'E389:') 1366 call assert_fails('isplit bar', 'E389:') 1367 1368 bw! 1369 endfunc 1370 1371 " this was using a line from ml_get() freed by the regexp 1372 func Test_isearch_copy_line() 1373 new 1374 norm o 1375 norm 0 1376 0norm o 1377 sil! norm bc0 1378 sil! isearch \%') 1379 bwipe! 1380 endfunc 1381 1382 " Test for :dsearch, :dlist, :djump and :dsplit commands 1383 " Test for [d, ]d, [D, ]D, [ CTRL-D, ] CTRL-D and CTRL-W d commands 1384 func Test_macro_search() 1385 new 1386 call setline(1, ['#define FOO 1', '#define FOO 2', '#define FOO 3', 1387 \ '#define FOO 4', '#define FOO 5']) 1388 call cursor(3, 9) 1389 1390 " Test for [d and ]d 1391 call assert_equal('#define FOO 1', execute('normal [d')) 1392 call assert_equal('#define FOO 2', execute('normal 2[d')) 1393 call assert_fails('normal 3[d', 'E387:') 1394 call assert_equal('#define FOO 4', execute('normal ]d')) 1395 call assert_equal('#define FOO 5', execute('normal 2]d')) 1396 call assert_fails('normal 3]d', 'E388:') 1397 1398 " Test for :dsearch 1399 call assert_equal('#define FOO 1', execute('dsearch FOO')) 1400 call assert_equal('#define FOO 5', execute('dsearch 5 /FOO/')) 1401 call assert_fails('dsearch 3 FOO', 'E387:') 1402 call assert_equal('#define FOO 4', execute('+1,$dsearch FOO')) 1403 call assert_fails('1,.-1dsearch 3 FOO', 'E388:') 1404 call assert_fails('dsearch BAR', 'E388:') 1405 1406 " Test for [D and ]D 1407 call assert_equal([ 1408 \ ' 1: 1 #define FOO 1', 1409 \ ' 2: 2 #define FOO 2', 1410 \ ' 3: 3 #define FOO 3', 1411 \ ' 4: 4 #define FOO 4', 1412 \ ' 5: 5 #define FOO 5'], split(execute('normal [D'), "\n")) 1413 call assert_equal([ 1414 \ ' 1: 4 #define FOO 4', 1415 \ ' 2: 5 #define FOO 5'], split(execute('normal ]D'), "\n")) 1416 1417 " Test for :dlist 1418 call assert_equal([ 1419 \ ' 1: 1 #define FOO 1', 1420 \ ' 2: 2 #define FOO 2', 1421 \ ' 3: 3 #define FOO 3', 1422 \ ' 4: 4 #define FOO 4', 1423 \ ' 5: 5 #define FOO 5'], split(execute('dlist FOO'), "\n")) 1424 call assert_equal([ 1425 \ ' 1: 4 #define FOO 4', 1426 \ ' 2: 5 #define FOO 5'], split(execute('+1,$dlist /FOO/'), "\n")) 1427 call assert_fails('dlist BAR', 'E388:') 1428 1429 " Test for [ CTRL-D and ] CTRL-D 1430 exe "normal [\<C-D>" 1431 call assert_equal([1, 9], [line('.'), col('.')]) 1432 exe "normal 2j4[\<C-D>" 1433 call assert_equal([4, 9], [line('.'), col('.')]) 1434 call assert_fails("normal k3[\<C-D>", 'E387:') 1435 call assert_fails("normal 6[\<C-D>", 'E388:') 1436 exe "normal ]\<C-D>" 1437 call assert_equal([4, 9], [line('.'), col('.')]) 1438 exe "normal k2]\<C-D>" 1439 call assert_equal([5, 9], [line('.'), col('.')]) 1440 call assert_fails("normal 2k3]\<C-D>", 'E388:') 1441 1442 " Test for :djump 1443 call cursor(3, 9) 1444 djump FOO 1445 call assert_equal([1, 9], [line('.'), col('.')]) 1446 call cursor(3, 9) 1447 djump 4 /FOO/ 1448 call assert_equal([4, 9], [line('.'), col('.')]) 1449 call cursor(3, 9) 1450 call assert_fails('djump 3 FOO', 'E387:') 1451 +,$djump 2 FOO 1452 call assert_equal([5, 9], [line('.'), col('.')]) 1453 call assert_fails('djump BAR', 'E388:') 1454 1455 " Test for CTRL-W d 1456 call cursor(3, 9) 1457 wincmd d 1458 call assert_equal([1, 9, 3], [line('.'), col('.'), winnr('$')]) 1459 close 1460 5wincmd d 1461 call assert_equal([5, 9, 3], [line('.'), col('.'), winnr('$')]) 1462 close 1463 call assert_fails('3wincmd d', 'E387:') 1464 call assert_fails('6wincmd d', 'E388:') 1465 new 1466 call assert_fails("normal \<C-W>d", 'E349:') 1467 call assert_fails("normal \<C-W>\<C-D>", 'E349:') 1468 close 1469 1470 " Test for :dsplit 1471 dsplit FOO 1472 call assert_equal([1, 9, 3], [line('.'), col('.'), winnr('$')]) 1473 close 1474 dsplit 5 /FOO/ 1475 call assert_equal([5, 9, 3], [line('.'), col('.'), winnr('$')]) 1476 close 1477 call assert_fails('dsplit 3 FOO', 'E387:') 1478 call assert_fails('dsplit 6 FOO', 'E388:') 1479 call assert_fails('dsplit BAR', 'E388:') 1480 1481 bw! 1482 endfunc 1483 1484 func Test_define_search() 1485 " this was accessing freed memory 1486 new 1487 call setline(1, ['first line', '', '#define something 0']) 1488 sil norm o0 1489 sil! norm 1490 bwipe! 1491 1492 new somefile 1493 call setline(1, ['first line', '', '#define something 0']) 1494 sil norm 0o0 1495 sil! norm ]d 1496 bwipe! 1497 endfunc 1498 1499 " Test for [*, [/, ]* and ]/ 1500 func Test_comment_search() 1501 new 1502 call setline(1, ['', '/*', ' *', ' *', ' */']) 1503 normal! 4gg[/ 1504 call assert_equal([2, 1], [line('.'), col('.')]) 1505 normal! 3gg[* 1506 call assert_equal([2, 1], [line('.'), col('.')]) 1507 normal! 3gg]/ 1508 call assert_equal([5, 3], [line('.'), col('.')]) 1509 normal! 3gg]* 1510 call assert_equal([5, 3], [line('.'), col('.')]) 1511 %d 1512 call setline(1, ['', '/*', ' *', ' *']) 1513 call assert_beeps('normal! 3gg]/') 1514 %d 1515 call setline(1, ['', ' *', ' *', ' */']) 1516 call assert_beeps('normal! 4gg[/') 1517 %d 1518 call setline(1, ' /* comment */') 1519 normal! 15|[/ 1520 call assert_equal(9, col('.')) 1521 normal! 15|]/ 1522 call assert_equal(21, col('.')) 1523 call setline(1, ' comment */') 1524 call assert_beeps('normal! 15|[/') 1525 call setline(1, ' /* comment') 1526 call assert_beeps('normal! 15|]/') 1527 bw! 1528 endfunc 1529 1530 " Test for the 'taglength' option 1531 func Test_tag_length() 1532 set tags=Xtags 1533 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1534 \ "tame\tXfile1\t1;", 1535 \ "tape\tXfile2\t1;"], 'Xtags') 1536 call writefile(['tame'], 'Xfile1') 1537 call writefile(['tape'], 'Xfile2') 1538 1539 " Jumping to the tag 'tape', should instead jump to 'tame' 1540 new 1541 set taglength=2 1542 tag tape 1543 call assert_equal('Xfile1', @%) 1544 " Tag search should jump to the right tag 1545 enew 1546 tag /^tape$ 1547 call assert_equal('Xfile2', @%) 1548 1549 call delete('Xtags') 1550 call delete('Xfile1') 1551 call delete('Xfile2') 1552 set tags& taglength& 1553 endfunc 1554 1555 " Tests for errors in a tags file 1556 func Test_tagfile_errors() 1557 set tags=Xtags 1558 1559 " missing search pattern or line number for a tag 1560 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1561 \ "foo\tXfile\t"], 'Xtags', 'b') 1562 call writefile(['foo'], 'Xfile') 1563 1564 enew 1565 tag foo 1566 call assert_equal('', @%) 1567 let caught_431 = v:false 1568 try 1569 eval taglist('.*') 1570 catch /:E431:/ 1571 let caught_431 = v:true 1572 endtry 1573 call assert_equal(v:true, caught_431) 1574 1575 " tag name and file name are not separated by a tab 1576 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1577 \ "foo Xfile 1"], 'Xtags') 1578 call assert_fails('tag foo', 'E431:') 1579 1580 " file name and search pattern are not separated by a tab 1581 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1582 \ "foo\tXfile 1;"], 'Xtags') 1583 call assert_fails('tag foo', 'E431:') 1584 1585 call delete('Xtags') 1586 call delete('Xfile') 1587 set tags& 1588 endfunc 1589 1590 " When :stag fails to open the file, should close the new window 1591 func Test_stag_close_window_on_error() 1592 new | only 1593 set tags=Xtags 1594 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1595 \ "foo\tXfile\t1"], 'Xtags') 1596 call writefile(['foo'], 'Xfile') 1597 call writefile([], '.Xfile.swp') 1598 " Remove the catch-all that runtest.vim adds 1599 au! SwapExists 1600 augroup StagTest 1601 au! 1602 autocmd SwapExists Xfile let v:swapchoice='q' 1603 augroup END 1604 1605 stag foo 1606 call assert_equal(1, winnr('$')) 1607 call assert_equal('', @%) 1608 1609 augroup StagTest 1610 au! 1611 augroup END 1612 call delete('Xfile') 1613 call delete('.Xfile.swp') 1614 set tags& 1615 endfunc 1616 1617 " Test for 'tagbsearch' (binary search) 1618 func Test_tagbsearch() 1619 " If a tags file header says the tags are sorted, but the tags are actually 1620 " unsorted, then binary search should fail and linear search should work. 1621 call writefile([ 1622 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1623 \ "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/", 1624 \ "third\tXfoo\t3", 1625 \ "second\tXfoo\t2", 1626 \ "first\tXfoo\t1"], 1627 \ 'Xtags', 'D') 1628 set tags=Xtags 1629 let code =<< trim [CODE] 1630 int first() {} 1631 int second() {} 1632 int third() {} 1633 [CODE] 1634 call writefile(code, 'Xfoo', 'D') 1635 1636 enew 1637 set tagbsearch 1638 call assert_fails('tag first', 'E426:') 1639 call assert_equal('', bufname()) 1640 call assert_fails('tag second', 'E426:') 1641 call assert_equal('', bufname()) 1642 tag third 1643 call assert_equal('Xfoo', bufname()) 1644 call assert_equal(3, line('.')) 1645 %bw! 1646 1647 set notagbsearch 1648 tag first 1649 call assert_equal('Xfoo', bufname()) 1650 call assert_equal(1, line('.')) 1651 enew 1652 tag second 1653 call assert_equal('Xfoo', bufname()) 1654 call assert_equal(2, line('.')) 1655 enew 1656 tag third 1657 call assert_equal('Xfoo', bufname()) 1658 call assert_equal(3, line('.')) 1659 %bw! 1660 1661 " If a tags file header says the tags are unsorted, but the tags are 1662 " actually sorted, then binary search should work. 1663 call writefile([ 1664 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1665 \ "!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/", 1666 \ "first\tXfoo\t1", 1667 \ "second\tXfoo\t2", 1668 \ "third\tXfoo\t3"], 1669 \ 'Xtags') 1670 1671 set tagbsearch 1672 tag first 1673 call assert_equal('Xfoo', bufname()) 1674 call assert_equal(1, line('.')) 1675 enew 1676 tag second 1677 call assert_equal('Xfoo', bufname()) 1678 call assert_equal(2, line('.')) 1679 enew 1680 tag third 1681 call assert_equal('Xfoo', bufname()) 1682 call assert_equal(3, line('.')) 1683 %bw! 1684 1685 " Binary search fails on EOF 1686 call writefile([ 1687 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1688 \ "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/", 1689 \ "bar\tXfoo\t1", 1690 \ "foo\tXfoo\t2"], 1691 \ 'Xtags') 1692 call assert_fails('tag bbb', 'E426:') 1693 1694 set tags& tagbsearch& 1695 endfunc 1696 1697 " Test tag guessing with very short names 1698 func Test_tag_guess_short() 1699 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1700 \ "y\tXf\t/^y()/"], 1701 \ 'Xt', 'D') 1702 set tags=Xt cpoptions+=t 1703 call writefile(['', 'int * y () {}', ''], 'Xf', 'D') 1704 1705 let v:statusmsg = '' 1706 let @/ = '' 1707 ta y 1708 call assert_match('E435:', v:statusmsg) 1709 call assert_equal(2, line('.')) 1710 call assert_match('<y', @/) 1711 1712 set tags& cpoptions-=t 1713 endfunc 1714 1715 func Test_tag_excmd_with_nostartofline() 1716 call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", 1717 \ "f\tXfile\tascii"], 1718 \ 'Xtags', 'D') 1719 call writefile(['f', 'foobar'], 'Xfile', 'D') 1720 1721 set nostartofline 1722 new Xfile 1723 setlocal tags=Xtags 1724 normal! G$ 1725 " This used to cause heap-buffer-overflow 1726 tag f 1727 1728 bwipe! 1729 set startofline& 1730 endfunc 1731 1732 " vim: shiftwidth=2 sts=2 expandtab