neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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