test_ins_complete.vim (210234B)
1 " Test for insert completion 2 3 source screendump.vim 4 source check.vim 5 source vim9.vim 6 7 " Test for insert expansion 8 func Test_ins_complete() 9 edit test_ins_complete.vim 10 " The files in the current directory interferes with the files 11 " used by this test. So use a separate directory for the test. 12 call mkdir('Xdir') 13 cd Xdir 14 15 set ff=unix 16 call writefile(["test11\t36Gepeto\t/Tag/", 17 \ "asd\ttest11file\t36G", 18 \ "Makefile\tto\trun"], 'Xtestfile') 19 call writefile(['', 'start of testfile', 20 \ 'ru', 21 \ 'run1', 22 \ 'run2', 23 \ 'STARTTEST', 24 \ 'ENDTEST', 25 \ 'end of testfile'], 'Xtestdata') 26 set ff& 27 28 enew! 29 edit Xtestdata 30 new 31 call append(0, ['#include "Xtestfile"', '']) 32 call cursor(2, 1) 33 34 set cot= 35 set cpt=.,w 36 " add-expands (word from next line) from other window 37 exe "normal iru\<C-N>\<C-N>\<C-X>\<C-N>\<Esc>\<C-A>" 38 call assert_equal('run1 run3', getline('.')) 39 " add-expands (current buffer first) 40 exe "normal o\<C-P>\<C-X>\<C-N>" 41 call assert_equal('run3 run3', getline('.')) 42 " Local expansion, ends in an empty line (unless it becomes a global 43 " expansion) 44 exe "normal o\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>" 45 call assert_equal('', getline('.')) 46 " starts Local and switches to global add-expansion 47 exe "normal o\<C-X>\<C-P>\<C-P>\<C-X>\<C-X>\<C-N>\<C-X>\<C-N>\<C-N>" 48 call assert_equal('run1 run2', getline('.')) 49 50 set cpt=.,\ ,w,i 51 " i-add-expands and switches to local 52 exe "normal OM\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-X>\<C-X>\<C-P>" 53 call assert_equal("Makefile\tto\trun3", getline('.')) 54 " add-expands lines (it would end in an empty line if it didn't ignore 55 " itself) 56 exe "normal o\<C-X>\<C-L>\<C-X>\<C-L>\<C-P>\<C-P>" 57 call assert_equal("Makefile\tto\trun3", getline('.')) 58 call assert_equal("Makefile\tto\trun3", getline(line('.') - 1)) 59 60 set cpt=kXtestfile 61 " checks k-expansion, and file expansion (use Xtest11 instead of test11, 62 " because TEST11.OUT may match first on DOS) 63 write Xtest11.one 64 write Xtest11.two 65 exe "normal o\<C-N>\<Esc>IX\<Esc>A\<C-X>\<C-F>\<C-N>" 66 call assert_equal('Xtest11.two', getline('.')) 67 68 " use CTRL-X CTRL-F to complete Xtest11.one, remove it and then use CTRL-X 69 " CTRL-F again to verify this doesn't cause trouble. 70 exe "normal oXt\<C-X>\<C-F>\<BS>\<BS>\<BS>\<BS>\<BS>\<BS>\<BS>\<BS>\<C-X>\<C-F>" 71 call assert_equal('Xtest11.one', getline('.')) 72 normal ddk 73 74 " Test for expanding a non-existing filename 75 exe "normal oa1b2X3Y4\<C-X>\<C-F>" 76 call assert_equal('a1b2X3Y4', getline('.')) 77 normal ddk 78 79 set cpt=w 80 " checks make_cyclic in other window 81 exe "normal oST\<C-N>\<C-P>\<C-P>\<C-P>\<C-P>" 82 call assert_equal('STARTTEST', getline('.')) 83 84 set cpt=u nohid 85 " checks unloaded buffer expansion 86 only 87 exe "normal oEN\<C-N>" 88 call assert_equal('ENDTEST', getline('.')) 89 " checks adding mode abortion 90 exe "normal ounl\<C-N>\<C-X>\<C-X>\<C-P>" 91 call assert_equal('unless', getline('.')) 92 93 set cpt=t,d def=^\\k* tags=Xtestfile notagbsearch 94 " tag expansion, define add-expansion interrupted 95 exe "normal o\<C-X>\<C-]>\<C-X>\<C-D>\<C-X>\<C-D>\<C-X>\<C-X>\<C-D>\<C-X>\<C-D>\<C-X>\<C-D>\<C-X>\<C-D>" 96 call assert_equal('test11file 36Gepeto /Tag/ asd', getline('.')) 97 " t-expansion 98 exe "normal oa\<C-N>\<Esc>" 99 call assert_equal('asd', getline('.')) 100 101 %bw! 102 call delete('Xtestfile') 103 call delete('Xtest11.one') 104 call delete('Xtest11.two') 105 call delete('Xtestdata') 106 set cpt& cot& def& tags& tagbsearch& hidden& 107 cd .. 108 call delete('Xdir', 'rf') 109 endfunc 110 111 func Test_ins_complete_invalid_byte() 112 if has('unix') && executable('base64') 113 " this weird command was causing an illegal memory access 114 call writefile(['bm9ybTlvMDCAMM4Dbw4OGA4ODg=='], 'Xinvalid64') 115 call system('base64 -d Xinvalid64 > Xinvalid') 116 call writefile(['qa!'], 'Xexit') 117 call RunVim([], [], " -i NONE -n -X -Z -e -m -s -S Xinvalid -S Xexit") 118 call delete('Xinvalid64') 119 call delete('Xinvalid') 120 call delete('Xexit') 121 endif 122 endfunc 123 124 func Test_omni_dash() 125 func Omni(findstart, base) 126 if a:findstart 127 return 5 128 else 129 return ['-help', '-v'] 130 endif 131 endfunc 132 set omnifunc=Omni 133 new 134 exe "normal Gofind -\<C-x>\<C-o>" 135 call assert_equal("find -help", getline('$')) 136 %d 137 set complete=o 138 exe "normal Gofind -\<C-n>" 139 call assert_equal("find -help", getline('$')) 140 141 bwipe! 142 delfunc Omni 143 set omnifunc= complete& 144 endfunc 145 146 func Test_omni_throw() 147 let g:CallCount = 0 148 func Omni(findstart, base) 149 let g:CallCount += 1 150 if a:findstart 151 throw "he he he" 152 endif 153 endfunc 154 set omnifunc=Omni 155 new 156 try 157 exe "normal ifoo\<C-x>\<C-o>" 158 call assert_false(v:true, 'command should have failed') 159 catch 160 call assert_exception('he he he') 161 call assert_equal(1, g:CallCount) 162 endtry 163 %d 164 set complete=o 165 let g:CallCount = 0 166 try 167 exe "normal ifoo\<C-n>" 168 call assert_false(v:true, 'command should have failed') 169 catch 170 call assert_exception('he he he') 171 call assert_equal(1, g:CallCount) 172 endtry 173 174 bwipe! 175 delfunc Omni 176 unlet g:CallCount 177 set omnifunc= complete& 178 endfunc 179 180 func Test_omni_autoload() 181 let save_rtp = &rtp 182 set rtp=Xruntime/some 183 let dir = 'Xruntime/some/autoload' 184 call mkdir(dir, 'pR') 185 186 let lines =<< trim END 187 func omni#Func(findstart, base) 188 if a:findstart 189 return 1 190 else 191 return ['match'] 192 endif 193 endfunc 194 195 eval 1 + 2 196 END 197 call writefile(lines, dir .. '/omni.vim') 198 199 new 200 setlocal omnifunc=omni#Func 201 call feedkeys("i\<C-X>\<C-O>\<Esc>", 'xt') 202 203 setlocal complete=.,Fomni#Func 204 call feedkeys("S\<C-N>\<Esc>", 'xt') 205 setlocal complete& 206 207 bwipe! 208 set omnifunc= 209 let &rtp = save_rtp 210 endfunc 211 212 func Test_completefunc_args() 213 let s:args = [] 214 func! CompleteFunc(findstart, base) 215 let s:args += [[a:findstart, empty(a:base)]] 216 endfunc 217 new 218 219 set completefunc=CompleteFunc 220 call feedkeys("i\<C-X>\<C-U>\<Esc>", 'x') 221 call assert_equal([1, 1], s:args[0]) 222 call assert_equal(0, s:args[1][0]) 223 set completefunc= 224 225 let s:args = [] 226 set omnifunc=CompleteFunc 227 call feedkeys("i\<C-X>\<C-O>\<Esc>", 'x') 228 call assert_equal([1, 1], s:args[0]) 229 call assert_equal(0, s:args[1][0]) 230 set omnifunc= 231 232 set complete=FCompleteFunc 233 call feedkeys("i\<C-N>\<Esc>", 'x') 234 call assert_equal([1, 1], s:args[0]) 235 call assert_equal(0, s:args[1][0]) 236 set complete=o 237 call feedkeys("i\<C-N>\<Esc>", 'x') 238 call assert_equal([1, 1], s:args[0]) 239 call assert_equal(0, s:args[1][0]) 240 set complete& 241 242 bwipe! 243 unlet s:args 244 delfunc CompleteFunc 245 endfunc 246 247 func s:CompleteDone_CompleteFuncNone( findstart, base ) 248 throw 'skipped: Nvim does not support v:none' 249 if a:findstart 250 return 0 251 endif 252 253 return v:none 254 endfunc 255 256 func s:CompleteDone_CompleteFuncDict( findstart, base ) 257 if a:findstart 258 return 0 259 endif 260 261 return { 262 \ 'words': [ 263 \ { 264 \ 'word': 'aword', 265 \ 'abbr': 'wrd', 266 \ 'menu': 'extra text', 267 \ 'info': 'words are cool', 268 \ 'kind': 'W', 269 \ 'user_data': ['one', 'two'] 270 \ } 271 \ ] 272 \ } 273 endfunc 274 275 func s:CompleteDone_CheckCompletedItemNone() 276 let s:called_completedone = 1 277 endfunc 278 279 func s:CompleteDone_CheckCompletedItemDict(pre) 280 call assert_equal( 'aword', v:completed_item[ 'word' ] ) 281 call assert_equal( 'wrd', v:completed_item[ 'abbr' ] ) 282 call assert_equal( 'extra text', v:completed_item[ 'menu' ] ) 283 call assert_equal( 'words are cool', v:completed_item[ 'info' ] ) 284 call assert_equal( 'W', v:completed_item[ 'kind' ] ) 285 call assert_equal( ['one', 'two'], v:completed_item[ 'user_data' ] ) 286 287 if a:pre 288 call assert_equal(a:pre == 1 ? 'function' : 'keyword', complete_info().mode) 289 endif 290 291 let s:called_completedone = 1 292 endfunc 293 294 func Test_CompleteDoneNone() 295 throw 'skipped: Nvim does not support v:none' 296 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemNone() 297 let oldline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '') 298 299 set completefunc=<SID>CompleteDone_CompleteFuncNone 300 execute "normal a\<C-X>\<C-U>\<C-Y>" 301 set completefunc& 302 let newline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '') 303 304 call assert_true(s:called_completedone) 305 call assert_equal(oldline, newline) 306 let s:called_completedone = 0 307 308 set complete=F<SID>CompleteDone_CompleteFuncNone 309 execute "normal a\<C-N>\<C-Y>" 310 set complete& 311 let newline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '') 312 313 call assert_true(s:called_completedone) 314 call assert_equal(oldline, newline) 315 let s:called_completedone = 0 316 au! CompleteDone 317 endfunc 318 319 func Test_CompleteDone_vevent_keys() 320 func OnDone() 321 let g:complete_word = get(v:event, 'complete_word', v:null) 322 let g:complete_type = get(v:event, 'complete_type', v:null) 323 endfunction 324 325 autocmd CompleteDone * :call OnDone() 326 327 func CompleteFunc(findstart, base) 328 if a:findstart 329 return col(".") 330 endif 331 return [#{word: "foo"}, #{word: "bar"}] 332 endfunc 333 set omnifunc=CompleteFunc 334 set completefunc=CompleteFunc 335 set complete=.,FCompleteFunc 336 set completeopt+=menuone 337 338 new 339 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'tx') 340 call assert_equal('', g:complete_word) 341 call assert_equal('omni', g:complete_type) 342 343 call feedkeys("S\<C-X>\<C-O>\<C-Y>\<Esc>", 'tx') 344 call assert_equal('foo', g:complete_word) 345 call assert_equal('omni', g:complete_type) 346 347 call feedkeys("S\<C-X>\<C-O>\<C-N>\<C-Y>\<Esc>0", 'tx') 348 call assert_equal('bar', g:complete_word) 349 call assert_equal('omni', g:complete_type) 350 351 call feedkeys("Shello vim visual v\<C-X>\<C-N>\<ESC>", 'tx') 352 call assert_equal('', g:complete_word) 353 call assert_equal('keyword', g:complete_type) 354 355 call feedkeys("Shello vim visual v\<C-X>\<C-N>\<C-Y>", 'tx') 356 call assert_equal('vim', g:complete_word) 357 call assert_equal('keyword', g:complete_type) 358 359 call feedkeys("Shello vim visual v\<C-N>\<ESC>", 'tx') 360 call assert_equal('', g:complete_word) 361 call assert_equal('keyword', g:complete_type) 362 363 call feedkeys("Shello vim visual v\<C-N>\<C-Y>", 'tx') 364 call assert_equal('vim', g:complete_word) 365 call assert_equal('keyword', g:complete_type) 366 367 call feedkeys("Shello vim\<CR>completion test\<CR>\<C-X>\<C-l>\<C-Y>", 'tx') 368 call assert_equal('completion test', g:complete_word) 369 call assert_equal('whole_line', g:complete_type) 370 371 call feedkeys("S\<C-X>\<C-U>\<C-Y>", 'tx') 372 call assert_equal('foo', g:complete_word) 373 call assert_equal('function', g:complete_type) 374 375 inoremap <buffer> <f3> <cmd>call complete(1, ["red", "blue"])<cr> 376 call feedkeys("S\<f3>\<C-Y>", 'tx') 377 call assert_equal('red', g:complete_word) 378 call assert_equal('eval', g:complete_type) 379 380 call feedkeys("S\<C-X>\<C-V>\<C-Y>", 'tx') 381 call assert_equal('!', g:complete_word) 382 call assert_equal('cmdline', g:complete_type) 383 384 call writefile([''], 'foo_test', 'D') 385 call feedkeys("Sfoo\<C-X>\<C-F>\<C-Y>\<Esc>", 'tx') 386 call assert_equal('foo_test', g:complete_word) 387 call assert_equal('files', g:complete_type) 388 389 call writefile(['hello help'], 'Xtest_case.txt', 'D') 390 set dictionary=Xtest_case.txt 391 call feedkeys("ggdGSh\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx') 392 call assert_equal('hello', g:complete_word) 393 call assert_equal('dictionary', g:complete_type) 394 395 set spell spelllang=en_us 396 call feedkeys("STheatre\<C-X>s\<C-Y>\<Esc>", 'tx') 397 call assert_equal('Theater', g:complete_word) 398 call assert_equal('spell', g:complete_type) 399 400 bwipe! 401 set completeopt& omnifunc& completefunc& spell& spelllang& dictionary& complete& 402 autocmd! CompleteDone 403 delfunc OnDone 404 delfunc CompleteFunc 405 unlet g:complete_word 406 unlet g:complete_type 407 endfunc 408 409 func Test_CompleteDoneDict() 410 au CompleteDonePre * :call <SID>CompleteDone_CheckCompletedItemDict(1) 411 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDict(0) 412 413 set completefunc=<SID>CompleteDone_CompleteFuncDict 414 execute "normal a\<C-X>\<C-U>\<C-Y>" 415 set completefunc& 416 417 call assert_equal(['one', 'two'], v:completed_item[ 'user_data' ]) 418 call assert_true(s:called_completedone) 419 420 let s:called_completedone = 0 421 au! CompleteDonePre 422 au! CompleteDone 423 424 au CompleteDonePre * :call <SID>CompleteDone_CheckCompletedItemDict(2) 425 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDict(0) 426 427 set complete=.,F<SID>CompleteDone_CompleteFuncDict 428 execute "normal a\<C-N>\<C-Y>" 429 set complete& 430 431 call assert_equal(['one', 'two'], v:completed_item[ 'user_data' ]) 432 call assert_true(s:called_completedone) 433 434 let s:called_completedone = 0 435 au! CompleteDonePre 436 au! CompleteDone 437 endfunc 438 439 func s:CompleteDone_CompleteFuncDictNoUserData(findstart, base) 440 if a:findstart 441 return 0 442 endif 443 444 return { 445 \ 'words': [ 446 \ { 447 \ 'word': 'aword', 448 \ 'abbr': 'wrd', 449 \ 'menu': 'extra text', 450 \ 'info': 'words are cool', 451 \ 'kind': 'W', 452 \ } 453 \ ] 454 \ } 455 endfunc 456 457 func s:CompleteDone_CheckCompletedItemDictNoUserData() 458 call assert_equal( 'aword', v:completed_item[ 'word' ] ) 459 call assert_equal( 'wrd', v:completed_item[ 'abbr' ] ) 460 call assert_equal( 'extra text', v:completed_item[ 'menu' ] ) 461 call assert_equal( 'words are cool', v:completed_item[ 'info' ] ) 462 call assert_equal( 'W', v:completed_item[ 'kind' ] ) 463 call assert_equal( '', v:completed_item[ 'user_data' ] ) 464 465 let s:called_completedone = 1 466 endfunc 467 468 func Test_CompleteDoneDictNoUserData() 469 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDictNoUserData() 470 471 set completefunc=<SID>CompleteDone_CompleteFuncDictNoUserData 472 execute "normal a\<C-X>\<C-U>\<C-Y>" 473 set completefunc& 474 475 call assert_equal('', v:completed_item[ 'user_data' ]) 476 call assert_true(s:called_completedone) 477 478 let s:called_completedone = 0 479 480 set complete=.,F<SID>CompleteDone_CompleteFuncDictNoUserData 481 execute "normal a\<C-N>\<C-Y>" 482 set complete& 483 484 call assert_equal('', v:completed_item[ 'user_data' ]) 485 call assert_true(s:called_completedone) 486 487 let s:called_completedone = 0 488 au! CompleteDone 489 endfunc 490 491 func s:CompleteDone_CompleteFuncList(findstart, base) 492 if a:findstart 493 return 0 494 endif 495 496 return [ 'aword' ] 497 endfunc 498 499 func s:CompleteDone_CheckCompletedItemList() 500 call assert_equal( 'aword', v:completed_item[ 'word' ] ) 501 call assert_equal( '', v:completed_item[ 'abbr' ] ) 502 call assert_equal( '', v:completed_item[ 'menu' ] ) 503 call assert_equal( '', v:completed_item[ 'info' ] ) 504 call assert_equal( '', v:completed_item[ 'kind' ] ) 505 call assert_equal( '', v:completed_item[ 'user_data' ] ) 506 507 let s:called_completedone = 1 508 endfunc 509 510 func Test_CompleteDoneList() 511 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemList() 512 513 set completefunc=<SID>CompleteDone_CompleteFuncList 514 execute "normal a\<C-X>\<C-U>\<C-Y>" 515 set completefunc& 516 517 call assert_equal('', v:completed_item[ 'user_data' ]) 518 call assert_true(s:called_completedone) 519 520 let s:called_completedone = 0 521 522 set complete=.,F<SID>CompleteDone_CompleteFuncList 523 execute "normal a\<C-N>\<C-Y>" 524 set complete& 525 526 call assert_equal('', v:completed_item[ 'user_data' ]) 527 call assert_true(s:called_completedone) 528 529 let s:called_completedone = 0 530 531 set complete=.,F 532 execute "normal a\<C-N>\<C-Y>" 533 set complete& 534 535 call assert_equal('', v:completed_item[ 'user_data' ]) 536 call assert_true(s:called_completedone) 537 538 let s:called_completedone = 0 539 au! CompleteDone 540 endfunc 541 542 func Test_CompleteDone_undo() 543 au CompleteDone * call append(0, "prepend1") 544 new 545 call setline(1, ["line1", "line2"]) 546 call feedkeys("Go\<C-X>\<C-N>\<CR>\<ESC>", "tx") 547 call assert_equal(["prepend1", "line1", "line2", "line1", ""], 548 \ getline(1, '$')) 549 undo 550 call assert_equal(["line1", "line2"], getline(1, '$')) 551 bwipe! 552 au! CompleteDone 553 endfunc 554 555 func Test_CompleteDone_modify() 556 let value = { 557 \ 'word': '', 558 \ 'abbr': '', 559 \ 'menu': '', 560 \ 'info': '', 561 \ 'kind': '', 562 \ 'user_data': '', 563 \ } 564 let v:completed_item = value 565 call assert_equal(value, v:completed_item) 566 endfunc 567 568 func CompleteTest(findstart, query) 569 if a:findstart 570 return col('.') 571 endif 572 return ['matched'] 573 endfunc 574 575 func Test_completefunc_info() 576 new 577 set completeopt=menuone 578 set completefunc=CompleteTest 579 " Can be called outside of ins-completion 580 call feedkeys("i\<C-X>\<C-U>\<C-Y>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") 581 call assert_equal("matched{'preinserted_text': '', 'pum_visible': 0, 'mode': '', 'selected': -1, 'items': []}", getline(1)) 582 %d 583 call feedkeys("i\<C-X>\<C-U>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") 584 call assert_equal("matched{'preinserted_text': '', 'pum_visible': 1, 'mode': 'function', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1)) 585 %d 586 set complete=.,FCompleteTest 587 call feedkeys("i\<C-N>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") 588 call assert_equal("matched{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1)) 589 %d 590 set complete=.,F 591 call feedkeys("i\<C-N>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") 592 call assert_equal("matched{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1)) 593 set completeopt& 594 set complete& 595 set completefunc& 596 endfunc 597 598 " For ^N completion, `completefunc` receives the same leader string in both the 599 " 'info' and 'expansion' phases (the leader is not removed before expansion). 600 " This avoids flicker when `completefunc` (e.g. an LSP client) is slow and calls 601 " 'sleep', which triggers out_flush(). 602 func Test_completefunc_leader() 603 func CptColTest(findstart, query) 604 if a:findstart 605 call assert_equal(b:compl_line, getline(1)) 606 call assert_equal(b:cursor_col, col('.')) 607 return col('.') 608 endif 609 call assert_equal(b:compl_line, getline(1)) 610 call assert_equal(b:cursor_col, col('.')) 611 " return v:none 612 return [] 613 endfunc 614 615 set complete=FCptColTest 616 new 617 618 " Replace mode 619 let b:compl_line = "foo barxyz" 620 let b:cursor_col = 10 621 call feedkeys("ifoo barbaz\<Esc>2hRxy\<C-N>", "tx") 622 623 " Insert mode 624 let b:compl_line = "foo bar" 625 let b:cursor_col = 8 626 call feedkeys("Sfoo bar\<C-N>", "tx") 627 628 set completeopt=longest 629 call feedkeys("Sfoo bar\<C-N>", "tx") 630 631 set completeopt=menuone 632 call feedkeys("Sfoo bar\<C-N>", "tx") 633 634 set completeopt=menuone,preinsert 635 call feedkeys("Sfoo bar\<C-N>", "tx") 636 bwipe! 637 set complete& completeopt& 638 delfunc CptColTest 639 endfunc 640 641 func ScrollInfoWindowUserDefinedFn(findstart, query) 642 " User defined function (i_CTRL-X_CTRL-U) 643 if a:findstart 644 return col('.') 645 endif 646 let infostr = range(20)->mapnew({_, v -> string(v)})->join("\n") 647 return [{'word': 'foo', 'info': infostr}, {'word': 'bar'}] 648 endfunc 649 650 func ScrollInfoWindowPageDown() 651 call win_execute(popup_findinfo(), "normal! \<PageDown>") 652 return '' 653 endfunc 654 655 func ScrollInfoWindowPageUp() 656 call win_execute(popup_findinfo(), "normal! \<PageUp>") 657 return '' 658 endfunc 659 660 func ScrollInfoWindowTest(mvmt, count, fline) 661 new 662 set completeopt=menuone,popup,noinsert,noselect 663 set completepopup=height:5 664 set completefunc=ScrollInfoWindowUserDefinedFn 665 let keyseq = "i\<C-X>\<C-U>\<C-N>" 666 for _ in range(a:count) 667 let keyseq .= (a:mvmt == "pageup" ? "\<C-R>\<C-R>=ScrollInfoWindowPageUp()\<CR>" : 668 \ "\<C-R>\<C-R>=ScrollInfoWindowPageDown()\<CR>") 669 endfor 670 let keyseq .= "\<C-R>\<C-R>=string(popup_getpos(popup_findinfo()))\<CR>\<ESC>" 671 call feedkeys(keyseq, "tx") 672 call assert_match('''firstline'': ' . a:fline, getline(1)) 673 bwipe! 674 set completeopt& 675 set completepopup& 676 set completefunc& 677 endfunc 678 679 func Test_scroll_info_window() 680 throw 'Skipped: popup_findinfo() is N/A' 681 call ScrollInfoWindowTest("", 0, 1) 682 call ScrollInfoWindowTest("pagedown", 1, 4) 683 call ScrollInfoWindowTest("pagedown", 2, 7) 684 call ScrollInfoWindowTest("pagedown", 3, 11) 685 call ScrollInfoWindowTest("pageup", 3, 1) 686 endfunc 687 688 func CompleteInfoUserDefinedFn(findstart, query) 689 " User defined function (i_CTRL-X_CTRL-U) 690 if a:findstart 691 return col('.') 692 endif 693 return [{'word': 'foo'}, {'word': 'bar'}, {'word': 'baz'}, {'word': 'qux'}] 694 endfunc 695 696 func CompleteInfoTestUserDefinedFn(mvmt, idx, noselect) 697 if a:noselect 698 set completeopt=menuone,popup,noinsert,noselect 699 else 700 set completeopt=menu,preview 701 endif 702 let items = "[" . 703 \ "{'word': 'foo', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . 704 \ "{'word': 'bar', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . 705 \ "{'word': 'baz', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " . 706 \ "{'word': 'qux', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}" . 707 \ "]" 708 new 709 set completefunc=CompleteInfoUserDefinedFn 710 call feedkeys("i\<C-X>\<C-U>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") 711 let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : '' 712 call assert_equal(completed. "{'preinserted_text': '', 'pum_visible': 1, 'mode': 'function', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1)) 713 %d 714 set complete=.,FCompleteInfoUserDefinedFn 715 call feedkeys("i\<C-N>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") 716 let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : '' 717 call assert_equal(completed. "{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1)) 718 %d 719 set complete=.,F 720 call feedkeys("i\<C-N>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx") 721 let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : '' 722 call assert_equal(completed. "{'preinserted_text': '', 'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1)) 723 bwipe! 724 set completeopt& completefunc& complete& 725 endfunc 726 727 func Test_complete_info_user_defined_fn() 728 " forward 729 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 1, v:true) 730 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 2, v:true) 731 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 2, v:false) 732 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 3, v:false) 733 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>", -1, v:false) 734 " backward 735 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 2, v:true) 736 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 1, v:true) 737 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>", -1, v:true) 738 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 3, v:false) 739 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 2, v:false) 740 " forward backward 741 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 1, v:true) 742 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 0, v:true) 743 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 2, v:false) 744 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 3, v:false) 745 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 1, v:false) 746 " backward forward 747 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 0, v:true) 748 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 2, v:true) 749 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 1, v:false) 750 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 3, v:false) 751 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-N>\<C-N>", 1, v:false) 752 endfunc 753 754 " Test that mouse scrolling/movement should not interrupt completion. 755 func Test_mouse_scroll_move_during_completion() 756 new 757 com! -buffer TestCommand1 echo 'TestCommand1' 758 com! -buffer TestCommand2 echo 'TestCommand2' 759 call setline(1, ['', '', '', '', '']) 760 call cursor(5, 1) 761 762 " Without completion menu scrolling can move text. 763 set completeopt-=menu wrap 764 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelDown>\<C-V>", 'tx') 765 call assert_equal('TestCommand2', getline('.')) 766 call assert_notequal(1, winsaveview().topline) 767 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelUp>\<C-V>", 'tx') 768 call assert_equal('TestCommand2', getline('.')) 769 call assert_equal(1, winsaveview().topline) 770 set nowrap 771 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelRight>\<C-V>", 'tx') 772 call assert_equal('TestCommand2', getline('.')) 773 call assert_notequal(0, winsaveview().leftcol) 774 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelLeft>\<C-V>", 'tx') 775 call assert_equal('TestCommand2', getline('.')) 776 call assert_equal(0, winsaveview().leftcol) 777 call feedkeys("ccT\<C-X>\<C-V>\<MouseMove>\<C-V>", 'tx') 778 call assert_equal('TestCommand2', getline('.')) 779 780 " With completion menu scrolling cannot move text. 781 set completeopt+=menu wrap 782 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelDown>\<C-V>", 'tx') 783 call assert_equal('TestCommand2', getline('.')) 784 call assert_equal(1, winsaveview().topline) 785 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelUp>\<C-V>", 'tx') 786 call assert_equal('TestCommand2', getline('.')) 787 call assert_equal(1, winsaveview().topline) 788 set nowrap 789 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelRight>\<C-V>", 'tx') 790 call assert_equal('TestCommand2', getline('.')) 791 call assert_equal(0, winsaveview().leftcol) 792 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelLeft>\<C-V>", 'tx') 793 call assert_equal('TestCommand2', getline('.')) 794 call assert_equal(0, winsaveview().leftcol) 795 call feedkeys("ccT\<C-X>\<C-V>\<MouseMove>\<C-V>", 'tx') 796 call assert_equal('TestCommand2', getline('.')) 797 798 bwipe! 799 set completeopt& wrap& 800 endfunc 801 802 " Check that when using feedkeys() typeahead does not interrupt searching for 803 " completions. 804 func Test_compl_feedkeys() 805 new 806 set completeopt=menuone,noselect 807 call feedkeys("ajump ju\<C-X>\<C-N>\<C-P>\<ESC>", "tx") 808 call assert_equal("jump jump", getline(1)) 809 bwipe! 810 set completeopt& 811 endfunc 812 813 func s:ComplInCmdwin_GlobalCompletion(a, l, p) 814 return 'global' 815 endfunc 816 817 func s:ComplInCmdwin_LocalCompletion(a, l, p) 818 return 'local' 819 endfunc 820 821 func Test_compl_in_cmdwin() 822 set wildmenu wildchar=<Tab> 823 com! -nargs=1 -complete=command GetInput let input = <q-args> 824 com! -buffer TestCommand echo 'TestCommand' 825 let w:test_winvar = 'winvar' 826 let b:test_bufvar = 'bufvar' 827 828 " User-defined commands 829 let input = '' 830 call feedkeys("q:iGetInput T\<C-x>\<C-v>\<CR>", 'tx!') 831 call assert_equal('TestCommand', input) 832 833 let input = '' 834 call feedkeys("q::GetInput T\<Tab>\<CR>:q\<CR>", 'tx!') 835 call assert_equal('T', input) 836 837 com! -nargs=1 -complete=var GetInput let input = <q-args> 838 " Window-local variables 839 let input = '' 840 call feedkeys("q:iGetInput w:test_\<C-x>\<C-v>\<CR>", 'tx!') 841 call assert_equal('w:test_winvar', input) 842 843 let input = '' 844 call feedkeys("q::GetInput w:test_\<Tab>\<CR>:q\<CR>", 'tx!') 845 call assert_equal('w:test_', input) 846 847 " Buffer-local variables 848 let input = '' 849 call feedkeys("q:iGetInput b:test_\<C-x>\<C-v>\<CR>", 'tx!') 850 call assert_equal('b:test_bufvar', input) 851 852 let input = '' 853 call feedkeys("q::GetInput b:test_\<Tab>\<CR>:q\<CR>", 'tx!') 854 call assert_equal('b:test_', input) 855 856 857 " Argument completion of buffer-local command 858 func s:ComplInCmdwin_GlobalCompletionList(a, l, p) 859 return ['global'] 860 endfunc 861 862 func s:ComplInCmdwin_LocalCompletionList(a, l, p) 863 return ['local'] 864 endfunc 865 866 func s:ComplInCmdwin_CheckCompletion(arg) 867 call assert_equal('local', a:arg) 868 endfunc 869 870 com! -nargs=1 -complete=custom,<SID>ComplInCmdwin_GlobalCompletion 871 \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) 872 com! -buffer -nargs=1 -complete=custom,<SID>ComplInCmdwin_LocalCompletion 873 \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) 874 call feedkeys("q:iTestCommand \<Tab>\<CR>", 'tx!') 875 876 com! -nargs=1 -complete=customlist,<SID>ComplInCmdwin_GlobalCompletionList 877 \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) 878 com! -buffer -nargs=1 -complete=customlist,<SID>ComplInCmdwin_LocalCompletionList 879 \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) 880 881 call feedkeys("q:iTestCommand \<Tab>\<CR>", 'tx!') 882 883 func! s:ComplInCmdwin_CheckCompletion(arg) 884 call assert_equal('global', a:arg) 885 endfunc 886 new 887 call feedkeys("q:iTestCommand \<Tab>\<CR>", 'tx!') 888 quit 889 890 delfunc s:ComplInCmdwin_GlobalCompletion 891 delfunc s:ComplInCmdwin_LocalCompletion 892 delfunc s:ComplInCmdwin_GlobalCompletionList 893 delfunc s:ComplInCmdwin_LocalCompletionList 894 delfunc s:ComplInCmdwin_CheckCompletion 895 896 delcom -buffer TestCommand 897 delcom TestCommand 898 delcom GetInput 899 unlet w:test_winvar 900 unlet b:test_bufvar 901 set wildmenu& wildchar& 902 endfunc 903 904 " Test for insert path completion with completeslash option 905 func Test_ins_completeslash() 906 CheckMSWindows 907 908 call mkdir('Xdir') 909 let orig_shellslash = &shellslash 910 set cpt& 911 new 912 913 set noshellslash 914 915 set completeslash= 916 exe "normal oXd\<C-X>\<C-F>" 917 call assert_equal('Xdir\', getline('.')) 918 919 set completeslash=backslash 920 exe "normal oXd\<C-X>\<C-F>" 921 call assert_equal('Xdir\', getline('.')) 922 923 set completeslash=slash 924 exe "normal oXd\<C-X>\<C-F>" 925 call assert_equal('Xdir/', getline('.')) 926 927 set shellslash 928 929 set completeslash= 930 exe "normal oXd\<C-X>\<C-F>" 931 call assert_equal('Xdir/', getline('.')) 932 933 set completeslash=backslash 934 exe "normal oXd\<C-X>\<C-F>" 935 call assert_equal('Xdir\', getline('.')) 936 937 set completeslash=slash 938 exe "normal oXd\<C-X>\<C-F>" 939 call assert_equal('Xdir/', getline('.')) 940 %bw! 941 call delete('Xdir', 'rf') 942 943 set noshellslash 944 set completeslash=slash 945 call assert_true(stridx(globpath(&rtp, 'syntax/*.vim', 1, 1)[0], '\') != -1) 946 947 let &shellslash = orig_shellslash 948 set completeslash= 949 endfunc 950 951 func Test_pum_stopped_by_timer() 952 CheckScreendump 953 954 let lines =<< trim END 955 call setline(1, ['hello', 'hullo', 'heeee', '']) 956 func StartCompl() 957 call timer_start(100, { -> execute('stopinsert') }) 958 call feedkeys("Gah\<C-N>") 959 endfunc 960 END 961 962 call writefile(lines, 'Xpumscript') 963 let buf = RunVimInTerminal('-S Xpumscript', #{rows: 12}) 964 call term_sendkeys(buf, ":call StartCompl()\<CR>") 965 call TermWait(buf, 200) 966 call term_sendkeys(buf, "k") 967 call VerifyScreenDump(buf, 'Test_pum_stopped_by_timer', {}) 968 969 call StopVimInTerminal(buf) 970 call delete('Xpumscript') 971 endfunc 972 973 func Test_complete_stopinsert_startinsert() 974 nnoremap <F2> <Cmd>startinsert<CR> 975 inoremap <F2> <Cmd>stopinsert<CR> 976 " This just checks if this causes an error 977 call feedkeys("i\<C-X>\<C-N>\<F2>\<F2>", 'x') 978 nunmap <F2> 979 iunmap <F2> 980 endfunc 981 982 func Test_pum_with_folds_two_tabs() 983 CheckScreendump 984 985 let lines =<< trim END 986 set fdm=marker 987 call setline(1, ['" x {{{1', '" a some text']) 988 call setline(3, range(&lines)->map({_, val -> '" a' .. val})) 989 norm! zm 990 tab sp 991 call feedkeys('2Gzv', 'xt') 992 call feedkeys("0fa", 'xt') 993 END 994 995 call writefile(lines, 'Xpumscript') 996 let buf = RunVimInTerminal('-S Xpumscript', #{rows: 10}) 997 call TermWait(buf, 50) 998 call term_sendkeys(buf, "a\<C-N>") 999 call VerifyScreenDump(buf, 'Test_pum_with_folds_two_tabs', {}) 1000 1001 call term_sendkeys(buf, "\<Esc>") 1002 call StopVimInTerminal(buf) 1003 call delete('Xpumscript') 1004 endfunc 1005 1006 func Test_pum_with_preview_win() 1007 CheckScreendump 1008 1009 let lines =<< trim END 1010 funct Omni_test(findstart, base) 1011 if a:findstart 1012 return col(".") - 1 1013 endif 1014 return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}] 1015 endfunc 1016 set omnifunc=Omni_test 1017 set completeopt+=longest 1018 END 1019 1020 call writefile(lines, 'Xpreviewscript') 1021 let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12}) 1022 call term_sendkeys(buf, "Gi\<C-X>\<C-O>") 1023 call TermWait(buf, 200) 1024 call term_sendkeys(buf, "\<C-N>") 1025 call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {}) 1026 1027 call term_sendkeys(buf, "\<Esc>") 1028 call StopVimInTerminal(buf) 1029 call delete('Xpreviewscript') 1030 endfunc 1031 1032 func Test_scrollbar_on_wide_char() 1033 CheckScreendump 1034 1035 let lines =<< trim END 1036 call setline(1, ['a', ' 啊啊啊', 1037 \ ' 哦哦哦', 1038 \ ' 呃呃呃']) 1039 call setline(5, range(10)->map({i, v -> 'aa' .. v .. 'bb'})) 1040 END 1041 call writefile(lines, 'Xwidescript') 1042 let buf = RunVimInTerminal('-S Xwidescript', #{rows: 10}) 1043 call term_sendkeys(buf, "A\<C-N>") 1044 call VerifyScreenDump(buf, 'Test_scrollbar_on_wide_char', {}) 1045 1046 call StopVimInTerminal(buf) 1047 call delete('Xwidescript') 1048 endfunc 1049 1050 " Test for inserting the tag search pattern in insert mode 1051 func Test_ins_compl_tag_sft() 1052 call writefile([ 1053 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 1054 \ "first\tXfoo\t/^int first() {}$/", 1055 \ "second\tXfoo\t/^int second() {}$/", 1056 \ "third\tXfoo\t/^int third() {}$/"], 1057 \ 'Xtags') 1058 set tags=Xtags 1059 let code =<< trim [CODE] 1060 int first() {} 1061 int second() {} 1062 int third() {} 1063 [CODE] 1064 call writefile(code, 'Xfoo') 1065 1066 enew 1067 set showfulltag 1068 exe "normal isec\<C-X>\<C-]>\<C-N>\<CR>" 1069 call assert_equal('int second() {}', getline(1)) 1070 set noshowfulltag 1071 1072 call delete('Xtags') 1073 call delete('Xfoo') 1074 set tags& 1075 %bwipe! 1076 endfunc 1077 1078 " Test for 'completefunc' deleting text 1079 func Test_completefunc_error() 1080 new 1081 " delete text when called for the first time 1082 func CompleteFunc(findstart, base) 1083 if a:findstart == 1 1084 normal dd 1085 return col('.') - 1 1086 endif 1087 return ['a', 'b'] 1088 endfunc 1089 set completefunc=CompleteFunc 1090 call setline(1, ['', 'abcd', '']) 1091 call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:') 1092 set complete=FCompleteFunc 1093 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:') 1094 set complete=F 1095 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:') 1096 1097 " delete text when called for the second time 1098 func CompleteFunc2(findstart, base) 1099 if a:findstart == 1 1100 return col('.') - 1 1101 endif 1102 normal dd 1103 return ['a', 'b'] 1104 endfunc 1105 set completefunc=CompleteFunc2 1106 call setline(1, ['', 'abcd', '']) 1107 call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:') 1108 set complete=FCompleteFunc2 1109 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:') 1110 set complete=F 1111 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:') 1112 1113 " Jump to a different window from the complete function 1114 func CompleteFunc3(findstart, base) 1115 if a:findstart == 1 1116 return col('.') - 1 1117 endif 1118 wincmd p 1119 return ['a', 'b'] 1120 endfunc 1121 set completefunc=CompleteFunc3 1122 new 1123 call assert_fails('exe "normal a\<C-X>\<C-U>"', 'E565:') 1124 %d 1125 set complete=FCompleteFunc3 1126 call assert_fails('exe "normal a\<C-N>"', 'E565:') 1127 %d 1128 set complete=F 1129 call assert_fails('exe "normal a\<C-N>"', 'E565:') 1130 bw! 1131 1132 set completefunc& complete& 1133 delfunc CompleteFunc 1134 delfunc CompleteFunc2 1135 delfunc CompleteFunc3 1136 bw! 1137 endfunc 1138 1139 " Test for returning non-string values from 'completefunc' 1140 func Test_completefunc_invalid_data() 1141 new 1142 func! CompleteFunc(findstart, base) 1143 if a:findstart == 1 1144 return col('.') - 1 1145 endif 1146 return [{}, '', 'moon'] 1147 endfunc 1148 set completefunc=CompleteFunc 1149 exe "normal i\<C-X>\<C-U>" 1150 call assert_equal('moon', getline(1)) 1151 %d 1152 set complete=FCompleteFunc 1153 exe "normal i\<C-N>" 1154 call assert_equal('moon', getline(1)) 1155 %d 1156 set complete=F 1157 exe "normal i\<C-N>" 1158 call assert_equal('moon', getline(1)) 1159 set completefunc& complete& 1160 delfunc! CompleteFunc 1161 bw! 1162 endfunc 1163 1164 " Test for errors in using complete() function 1165 func Test_complete_func_error() 1166 call assert_fails('call complete(1, ["a"])', 'E785:') 1167 func ListColors() 1168 call complete(col('.'), "blue") 1169 endfunc 1170 call assert_fails('exe "normal i\<C-R>=ListColors()\<CR>"', 'E474:') 1171 func ListMonths() 1172 call complete(col('.'), test_null_list()) 1173 endfunc 1174 " Nvim allows a NULL list 1175 " call assert_fails('exe "normal i\<C-R>=ListMonths()\<CR>"', 'E474:') 1176 delfunc ListColors 1177 delfunc ListMonths 1178 call assert_fails('call complete_info({})', 'E714:') 1179 call assert_equal([], complete_info(['items']).items) 1180 endfunc 1181 1182 " Test for recursively starting completion mode using complete() 1183 func Test_recursive_complete_func() 1184 func ListColors() 1185 call complete(5, ["red", "blue"]) 1186 return '' 1187 endfunc 1188 new 1189 call setline(1, ['a1', 'a2']) 1190 set complete=. 1191 exe "normal Goa\<C-X>\<C-L>\<C-R>=ListColors()\<CR>\<C-N>" 1192 call assert_equal('a2blue', getline(3)) 1193 delfunc ListColors 1194 bw! 1195 endfunc 1196 1197 " Test for using complete() with completeopt+=longest 1198 func Test_complete_with_longest() 1199 new 1200 inoremap <buffer> <f3> <cmd>call complete(1, ["iaax", "iaay", "iaaz"])<cr> 1201 1202 " default: insert first match 1203 set completeopt& 1204 call setline(1, ['i']) 1205 exe "normal Aa\<f3>\<esc>" 1206 call assert_equal('iaax', getline(1)) 1207 1208 " with longest: insert longest prefix 1209 set completeopt+=longest 1210 call setline(1, ['i']) 1211 exe "normal Aa\<f3>\<esc>" 1212 call assert_equal('iaa', getline(1)) 1213 set completeopt& 1214 bwipe! 1215 endfunc 1216 1217 " Test for buffer-local value of 'completeopt' 1218 func Test_completeopt_buffer_local() 1219 set completeopt=menu 1220 new 1221 call setline(1, ['foofoo', 'foobar', 'foobaz', '']) 1222 call assert_equal('', &l:completeopt) 1223 call assert_equal('menu', &completeopt) 1224 call assert_equal('menu', &g:completeopt) 1225 1226 setlocal bufhidden=hide 1227 enew 1228 call setline(1, ['foofoo', 'foobar', 'foobaz', '']) 1229 call assert_equal('', &l:completeopt) 1230 call assert_equal('menu', &completeopt) 1231 call assert_equal('menu', &g:completeopt) 1232 1233 setlocal completeopt+=fuzzy,noinsert 1234 call assert_equal('menu,fuzzy,noinsert', &l:completeopt) 1235 call assert_equal('menu,fuzzy,noinsert', &completeopt) 1236 call assert_equal('menu', &g:completeopt) 1237 call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix') 1238 call assert_equal('foobaz', getline('.')) 1239 1240 setlocal completeopt= 1241 call assert_equal('', &l:completeopt) 1242 call assert_equal('menu', &completeopt) 1243 call assert_equal('menu', &g:completeopt) 1244 call feedkeys("Gccf\<C-X>\<C-N>\<C-Y>", 'tnix') 1245 call assert_equal('foofoo', getline('.')) 1246 1247 setlocal completeopt+=longest 1248 call assert_equal('menu,longest', &l:completeopt) 1249 call assert_equal('menu,longest', &completeopt) 1250 call assert_equal('menu', &g:completeopt) 1251 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix') 1252 call assert_equal('foo', getline('.')) 1253 1254 setlocal bufhidden=hide 1255 buffer # 1256 call assert_equal('', &l:completeopt) 1257 call assert_equal('menu', &completeopt) 1258 call assert_equal('menu', &g:completeopt) 1259 call feedkeys("Gccf\<C-X>\<C-N>\<C-Y>", 'tnix') 1260 call assert_equal('foofoo', getline('.')) 1261 1262 setlocal completeopt+=fuzzy,noinsert 1263 call assert_equal('menu,fuzzy,noinsert', &l:completeopt) 1264 call assert_equal('menu,fuzzy,noinsert', &completeopt) 1265 call assert_equal('menu', &g:completeopt) 1266 call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix') 1267 call assert_equal('foobaz', getline('.')) 1268 1269 buffer # 1270 call assert_equal('menu,longest', &l:completeopt) 1271 call assert_equal('menu,longest', &completeopt) 1272 call assert_equal('menu', &g:completeopt) 1273 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix') 1274 call assert_equal('foo', getline('.')) 1275 1276 setlocal bufhidden=wipe 1277 buffer! # 1278 bwipe! 1279 call assert_equal('', &l:completeopt) 1280 call assert_equal('menu', &completeopt) 1281 call assert_equal('menu', &g:completeopt) 1282 1283 new | only 1284 call setline(1, ['foofoo', 'foobar', 'foobaz', '']) 1285 set completeopt& 1286 setlocal completeopt=menu,fuzzy,noinsert 1287 setglobal completeopt=menu,longest 1288 call assert_equal('menu,fuzzy,noinsert', &completeopt) 1289 call assert_equal('menu,fuzzy,noinsert', &l:completeopt) 1290 call assert_equal('menu,longest', &g:completeopt) 1291 call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix') 1292 call assert_equal('foobaz', getline('.')) 1293 setlocal bufhidden=wipe 1294 new | only! 1295 call setline(1, ['foofoo', 'foobar', 'foobaz', '']) 1296 call assert_equal('menu,longest', &completeopt) 1297 call assert_equal('menu,longest', &g:completeopt) 1298 call assert_equal('', &l:completeopt) 1299 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix') 1300 call assert_equal('foo', getline('.')) 1301 bwipe! 1302 1303 new | only 1304 call setline(1, ['foofoo', 'foobar', 'foobaz', '']) 1305 set completeopt& 1306 setlocal completeopt=menu,fuzzy,noinsert 1307 set completeopt=menu,longest 1308 call assert_equal('menu,longest', &completeopt) 1309 call assert_equal('menu,longest', &g:completeopt) 1310 call assert_equal('', &l:completeopt) 1311 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix') 1312 call assert_equal('foo', getline('.')) 1313 setlocal bufhidden=wipe 1314 new | only! 1315 call setline(1, ['foofoo', 'foobar', 'foobaz', '']) 1316 call assert_equal('menu,longest', &completeopt) 1317 call assert_equal('menu,longest', &g:completeopt) 1318 call assert_equal('', &l:completeopt) 1319 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix') 1320 call assert_equal('foo', getline('.')) 1321 bwipe! 1322 1323 set completeopt& 1324 endfunc 1325 1326 " Test for completing words following a completed word in a line 1327 func Test_complete_wrapscan() 1328 " complete words from another buffer 1329 new 1330 call setline(1, ['one two', 'three four']) 1331 new 1332 setlocal complete=w 1333 call feedkeys("itw\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>", 'xt') 1334 call assert_equal('two three four', getline(1)) 1335 bw! 1336 " complete words from the current buffer 1337 setlocal complete=. 1338 %d 1339 call setline(1, ['one two', '']) 1340 call cursor(2, 1) 1341 call feedkeys("ion\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>", 'xt') 1342 call assert_equal('one two one two', getline(2)) 1343 bw! 1344 endfunc 1345 1346 " Test for completing special characters 1347 func Test_complete_special_chars() 1348 new 1349 call setline(1, 'int .*[-\^$ func float') 1350 call feedkeys("oin\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>", 'xt') 1351 call assert_equal('int .*[-\^$ func float', getline(2)) 1352 bw! 1353 endfunc 1354 1355 " Test for completion when text is wrapped across lines. 1356 func Test_complete_across_line() 1357 new 1358 call setline(1, ['red green blue', 'one two three']) 1359 setlocal textwidth=20 1360 exe "normal 2G$a re\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>" 1361 call assert_equal(['one two three red', 'green blue one'], getline(2, '$')) 1362 bw! 1363 endfunc 1364 1365 " Test for completing words with a '.' at the end of a word. 1366 func Test_complete_joinspaces() 1367 new 1368 call setline(1, ['one two.', 'three. four']) 1369 set joinspaces 1370 exe "normal Goon\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>" 1371 call assert_equal("one two. three. four", getline(3)) 1372 set joinspaces& 1373 bw! 1374 endfunc 1375 1376 " Test for using CTRL-L to add one character when completing matching 1377 func Test_complete_add_onechar() 1378 new 1379 call setline(1, ['wool', 'woodwork']) 1380 call feedkeys("Gowoo\<C-P>\<C-P>\<C-P>\<C-L>f", 'xt') 1381 call assert_equal('woof', getline(3)) 1382 1383 " use 'ignorecase' and backspace to erase characters from the prefix string 1384 " and then add letters using CTRL-L 1385 %d 1386 set ignorecase backspace=2 1387 setlocal complete=. 1388 call setline(1, ['workhorse', 'workload']) 1389 normal Go 1390 exe "normal aWOR\<C-P>\<bs>\<bs>\<bs>\<bs>\<bs>\<bs>\<C-L>\<C-L>\<C-L>" 1391 call assert_equal('workh', getline(3)) 1392 set ignorecase& backspace& 1393 bw! 1394 endfunc 1395 1396 " Test for using CTRL-X CTRL-L to complete whole lines lines 1397 func Test_complete_wholeline() 1398 new 1399 " complete one-line 1400 call setline(1, ['a1', 'a2']) 1401 exe "normal ggoa\<C-X>\<C-L>" 1402 call assert_equal(['a1', 'a1', 'a2'], getline(1, '$')) 1403 " go to the next match (wrapping around the buffer) 1404 exe "normal 2GCa\<C-X>\<C-L>\<C-N>" 1405 call assert_equal(['a1', 'a', 'a2'], getline(1, '$')) 1406 " go to the next match 1407 exe "normal 2GCa\<C-X>\<C-L>\<C-N>\<C-N>" 1408 call assert_equal(['a1', 'a2', 'a2'], getline(1, '$')) 1409 exe "normal 2GCa\<C-X>\<C-L>\<C-N>\<C-N>\<C-N>" 1410 call assert_equal(['a1', 'a1', 'a2'], getline(1, '$')) 1411 " repeat the test using CTRL-L 1412 " go to the next match (wrapping around the buffer) 1413 exe "normal 2GCa\<C-X>\<C-L>\<C-L>" 1414 call assert_equal(['a1', 'a2', 'a2'], getline(1, '$')) 1415 " go to the next match 1416 exe "normal 2GCa\<C-X>\<C-L>\<C-L>\<C-L>" 1417 call assert_equal(['a1', 'a', 'a2'], getline(1, '$')) 1418 exe "normal 2GCa\<C-X>\<C-L>\<C-L>\<C-L>\<C-L>" 1419 call assert_equal(['a1', 'a1', 'a2'], getline(1, '$')) 1420 %d 1421 " use CTRL-X CTRL-L to add one more line 1422 call setline(1, ['a1', 'b1']) 1423 setlocal complete=. 1424 exe "normal ggOa\<C-X>\<C-L>\<C-X>\<C-L>\<C-X>\<C-L>" 1425 call assert_equal(['a1', 'b1', '', 'a1', 'b1'], getline(1, '$')) 1426 bw! 1427 endfunc 1428 1429 " Test for using CTRL-X CTRL-S to complete spell suggestions 1430 func Test_complete_spell() 1431 new 1432 setlocal spell 1433 " without fuzzy 1434 call setline(1, 'The rigth thing') 1435 exe "normal! A\<C-X>\<C-S>" 1436 call assert_equal('The right thing', getline(1)) 1437 %d 1438 " with fuzzy 1439 setlocal completeopt+=fuzzy 1440 call setline(1, 'The rigth thing') 1441 exe "normal! A\<C-X>\<C-S>" 1442 call assert_equal('The right thing', getline(1)) 1443 bw! 1444 endfunc 1445 1446 " Test insert completion with 'cindent' (adjust the indent) 1447 func Test_complete_with_cindent() 1448 new 1449 setlocal cindent 1450 call setline(1, ['if (i == 1)', " j = 2;"]) 1451 exe "normal Go{\<CR>i\<C-X>\<C-L>\<C-X>\<C-L>\<CR>}" 1452 call assert_equal(['{', "\tif (i == 1)", "\t\tj = 2;", '}'], getline(3, '$')) 1453 1454 %d 1455 call setline(1, ['when while', '{', '']) 1456 setlocal cinkeys+==while 1457 exe "normal Giwh\<C-P> " 1458 call assert_equal("\twhile ", getline('$')) 1459 bw! 1460 endfunc 1461 1462 " Test for <CTRL-X> <CTRL-V> completion. Complete commands and functions 1463 func Test_complete_cmdline() 1464 new 1465 exe "normal icaddb\<C-X>\<C-V>" 1466 call assert_equal('caddbuffer', getline(1)) 1467 exe "normal ocall getqf\<C-X>\<C-V>" 1468 call assert_equal('call getqflist(', getline(2)) 1469 exe "normal oabcxyz(\<C-X>\<C-V>" 1470 call assert_equal('abcxyz(', getline(3)) 1471 com! -buffer TestCommand1 echo 'TestCommand1' 1472 com! -buffer TestCommand2 echo 'TestCommand2' 1473 write! TestCommand1Test 1474 write! TestCommand2Test 1475 " Test repeating <CTRL-X> <CTRL-V> and switching to another CTRL-X mode 1476 exe "normal oT\<C-X>\<C-V>\<C-X>\<C-V>\<C-X>\<C-F>\<Esc>" 1477 call assert_equal('TestCommand2Test', getline(4)) 1478 call delete('TestCommand1Test') 1479 call delete('TestCommand2Test') 1480 delcom TestCommand1 1481 delcom TestCommand2 1482 bw! 1483 endfunc 1484 1485 " Test for <CTRL-X> <CTRL-Z> stopping completion without changing the match 1486 func Test_complete_stop() 1487 new 1488 func Save_mode1() 1489 let g:mode1 = mode(1) 1490 return '' 1491 endfunc 1492 func Save_mode2() 1493 let g:mode2 = mode(1) 1494 return '' 1495 endfunc 1496 inoremap <F1> <C-R>=Save_mode1()<CR> 1497 inoremap <F2> <C-R>=Save_mode2()<CR> 1498 call setline(1, ['aaa bbb ccc ']) 1499 exe "normal A\<C-N>\<C-P>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>" 1500 call assert_equal('ic', g:mode1) 1501 call assert_equal('i', g:mode2) 1502 call assert_equal('aaa bbb ccc ', getline(1)) 1503 exe "normal A\<C-N>\<Down>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>" 1504 call assert_equal('ic', g:mode1) 1505 call assert_equal('i', g:mode2) 1506 call assert_equal('aaa bbb ccc aaa', getline(1)) 1507 set completeopt+=noselect 1508 exe "normal A \<C-N>\<Down>\<Down>\<C-L>\<C-L>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>" 1509 call assert_equal('ic', g:mode1) 1510 call assert_equal('i', g:mode2) 1511 call assert_equal('aaa bbb ccc aaa bb', getline(1)) 1512 set completeopt& 1513 exe "normal A d\<C-N>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>" 1514 call assert_equal('ic', g:mode1) 1515 call assert_equal('i', g:mode2) 1516 call assert_equal('aaa bbb ccc aaa bb d', getline(1)) 1517 com! -buffer TestCommand1 echo 'TestCommand1' 1518 com! -buffer TestCommand2 echo 'TestCommand2' 1519 exe "normal oT\<C-X>\<C-V>\<C-X>\<C-V>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>" 1520 call assert_equal('ic', g:mode1) 1521 call assert_equal('i', g:mode2) 1522 call assert_equal('TestCommand2', getline(2)) 1523 delcom TestCommand1 1524 delcom TestCommand2 1525 unlet g:mode1 1526 unlet g:mode2 1527 iunmap <F1> 1528 iunmap <F2> 1529 delfunc Save_mode1 1530 delfunc Save_mode2 1531 bw! 1532 endfunc 1533 1534 " Test for typing CTRL-R in insert completion mode to insert a register 1535 " content. 1536 func Test_complete_reginsert() 1537 new 1538 call setline(1, ['a1', 'a12', 'a123', 'a1234']) 1539 1540 " if a valid CTRL-X mode key is returned from <C-R>=, then it should be 1541 " processed. Otherwise, CTRL-X mode should be stopped and the key should be 1542 " inserted. 1543 exe "normal Goa\<C-P>\<C-R>=\"\\<C-P>\"\<CR>" 1544 call assert_equal('a123', getline(5)) 1545 let @r = "\<C-P>\<C-P>" 1546 exe "normal GCa\<C-P>\<C-R>=@r\<CR>" 1547 call assert_equal('a12', getline(5)) 1548 exe "normal GCa\<C-P>\<C-R>=\"x\"\<CR>" 1549 call assert_equal('a1234x', getline(5)) 1550 bw! 1551 endfunc 1552 1553 func Test_issue_7021() 1554 CheckMSWindows 1555 1556 let orig_shellslash = &shellslash 1557 set noshellslash 1558 1559 set completeslash=slash 1560 call assert_false(expand('~') =~ '/') 1561 1562 let &shellslash = orig_shellslash 1563 set completeslash= 1564 endfunc 1565 1566 " Test for 'longest' setting in 'completeopt' with latin1 and utf-8 encodings 1567 func Test_complete_longest_match() 1568 " for e in ['latin1', 'utf-8'] 1569 for e in ['utf-8'] 1570 exe 'set encoding=' .. e 1571 new 1572 set complete=. 1573 set completeopt=menu,longest 1574 call setline(1, ['pfx_a1', 'pfx_a12', 'pfx_a123', 'pfx_b1']) 1575 exe "normal Gopfx\<C-P>" 1576 call assert_equal('pfx_', getline(5)) 1577 bw! 1578 endfor 1579 1580 " Test for completing additional words with longest match set 1581 new 1582 call setline(1, ['abc1', 'abd2']) 1583 exe "normal Goab\<C-P>\<C-X>\<C-P>" 1584 call assert_equal('ab', getline(3)) 1585 bw! 1586 set complete& completeopt& 1587 endfunc 1588 1589 " Test for removing the first displayed completion match and selecting the 1590 " match just before that. 1591 func Test_complete_erase_firstmatch() 1592 new 1593 call setline(1, ['a12', 'a34', 'a56']) 1594 set complete=. 1595 exe "normal Goa\<C-P>\<BS>\<BS>3\<CR>" 1596 call assert_equal('a34', getline('$')) 1597 set complete& 1598 bw! 1599 endfunc 1600 1601 " Test for completing words from unloaded buffers 1602 func Test_complete_from_unloadedbuf() 1603 call writefile(['abc'], "Xfile1") 1604 call writefile(['def'], "Xfile2") 1605 edit Xfile1 1606 edit Xfile2 1607 new | close 1608 enew 1609 bunload Xfile1 Xfile2 1610 set complete=u 1611 " complete from an unloaded buffer 1612 exe "normal! ia\<C-P>" 1613 call assert_equal('abc', getline(1)) 1614 exe "normal! od\<C-P>" 1615 call assert_equal('def', getline(2)) 1616 set complete& 1617 %bw! 1618 call delete("Xfile1") 1619 call delete("Xfile2") 1620 endfunc 1621 1622 " Test for completing whole lines from unloaded buffers 1623 func Test_complete_wholeline_unloadedbuf() 1624 call writefile(['a line1', 'a line2', 'a line3'], "Xfile1") 1625 edit Xfile1 1626 enew 1627 set complete=u 1628 exe "normal! ia\<C-X>\<C-L>\<C-P>" 1629 call assert_equal('a line2', getline(1)) 1630 %d 1631 " completing from an unlisted buffer should fail 1632 bdel Xfile1 1633 exe "normal! ia\<C-X>\<C-L>\<C-P>" 1634 call assert_equal('a', getline(1)) 1635 set complete& 1636 %bw! 1637 call delete("Xfile1") 1638 endfunc 1639 1640 " Test for completing words from unlisted buffers 1641 func Test_complete_from_unlistedbuf() 1642 call writefile(['abc'], "Xfile1") 1643 call writefile(['def'], "Xfile2") 1644 edit Xfile1 1645 edit Xfile2 1646 new | close 1647 bdel Xfile1 Xfile2 1648 set complete=U 1649 " complete from an unlisted buffer 1650 exe "normal! ia\<C-P>" 1651 call assert_equal('abc', getline(1)) 1652 exe "normal! od\<C-P>" 1653 call assert_equal('def', getline(2)) 1654 set complete& 1655 %bw! 1656 call delete("Xfile1") 1657 call delete("Xfile2") 1658 endfunc 1659 1660 " Test for completing whole lines from unlisted buffers 1661 func Test_complete_wholeline_unlistedbuf() 1662 call writefile(['a line1', 'a line2', 'a line3'], "Xfile1") 1663 edit Xfile1 1664 enew 1665 set complete=U 1666 " completing from an unloaded buffer should fail 1667 exe "normal! ia\<C-X>\<C-L>\<C-P>" 1668 call assert_equal('a', getline(1)) 1669 %d 1670 bdel Xfile1 1671 exe "normal! ia\<C-X>\<C-L>\<C-P>" 1672 call assert_equal('a line2', getline(1)) 1673 set complete& 1674 %bw! 1675 call delete("Xfile1") 1676 endfunc 1677 1678 " Test for adding a multibyte character using CTRL-L in completion mode 1679 func Test_complete_mbyte_char_add() 1680 new 1681 set complete=. 1682 call setline(1, 'abė') 1683 exe "normal! oa\<C-P>\<BS>\<BS>\<C-L>\<C-L>" 1684 call assert_equal('abė', getline(2)) 1685 " Test for a leader with multibyte character 1686 %d 1687 call setline(1, 'abėĕ') 1688 exe "normal! oabė\<C-P>" 1689 call assert_equal('abėĕ', getline(2)) 1690 bw! 1691 endfunc 1692 1693 " Test for using <C-X><C-P> for local expansion even if 'complete' is set to 1694 " not to complete matches from the local buffer. Also test using multiple 1695 " <C-X> to cancel the current completion mode. 1696 func Test_complete_local_expansion() 1697 new 1698 set complete=t 1699 call setline(1, ['abc', 'def']) 1700 exe "normal! Go\<C-X>\<C-P>" 1701 call assert_equal("def", getline(3)) 1702 exe "normal! Go\<C-P>" 1703 call assert_equal("", getline(4)) 1704 exe "normal! Go\<C-X>\<C-N>" 1705 call assert_equal("abc", getline(5)) 1706 exe "normal! Go\<C-N>" 1707 call assert_equal("", getline(6)) 1708 1709 " use multiple <C-X> to cancel the previous completion mode 1710 exe "normal! Go\<C-P>\<C-X>\<C-P>" 1711 call assert_equal("", getline(7)) 1712 exe "normal! Go\<C-P>\<C-X>\<C-X>\<C-P>" 1713 call assert_equal("", getline(8)) 1714 exe "normal! Go\<C-P>\<C-X>\<C-X>\<C-X>\<C-P>" 1715 call assert_equal("abc", getline(9)) 1716 1717 " interrupt the current completion mode 1718 set completeopt=menu,noinsert 1719 exe "normal! Go\<C-X>\<C-F>\<C-X>\<C-X>\<C-P>\<C-Y>" 1720 call assert_equal("abc", getline(10)) 1721 1722 " when only one <C-X> is used to interrupt, do normal expansion 1723 exe "normal! Go\<C-X>\<C-F>\<C-X>\<C-P>" 1724 call assert_equal("", getline(11)) 1725 set completeopt& 1726 1727 " using two <C-X> in non-completion mode and restarting the same mode 1728 exe "normal! God\<C-X>\<C-X>\<C-P>\<C-X>\<C-X>\<C-P>\<C-Y>" 1729 call assert_equal("def", getline(12)) 1730 1731 " test for adding a match from the original empty text 1732 %d 1733 call setline(1, 'abc def g') 1734 exe "normal! o\<C-X>\<C-P>\<C-N>\<C-X>\<C-P>" 1735 call assert_equal('def', getline(2)) 1736 exe "normal! 0C\<C-X>\<C-N>\<C-P>\<C-X>\<C-N>" 1737 call assert_equal('abc', getline(2)) 1738 1739 bw! 1740 endfunc 1741 1742 " Test for undoing changes after a insert-mode completion 1743 func Test_complete_undo() 1744 new 1745 set complete=. 1746 " undo with 'ignorecase' 1747 call setline(1, ['ABOVE', 'BELOW']) 1748 set ignorecase 1749 exe "normal! Goab\<C-G>u\<C-P>" 1750 call assert_equal("ABOVE", getline(3)) 1751 undo 1752 call assert_equal("ab", getline(3)) 1753 set ignorecase& 1754 %d 1755 " undo with longest match 1756 set completeopt=menu,longest 1757 call setline(1, ['above', 'about']) 1758 exe "normal! Goa\<C-G>u\<C-P>" 1759 call assert_equal("abo", getline(3)) 1760 undo 1761 call assert_equal("a", getline(3)) 1762 set completeopt& 1763 %d 1764 " undo for line completion 1765 call setline(1, ['above that change', 'below that change']) 1766 exe "normal! Goabove\<C-G>u\<C-X>\<C-L>" 1767 call assert_equal("above that change", getline(3)) 1768 undo 1769 call assert_equal("above", getline(3)) 1770 1771 bw! 1772 endfunc 1773 1774 " Test for completing a very long word 1775 func Test_complete_long_word() 1776 set complete& 1777 new 1778 call setline(1, repeat('x', 950) .. ' one two three') 1779 exe "normal! Gox\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>" 1780 call assert_equal(repeat('x', 950) .. ' one two three', getline(2)) 1781 %d 1782 " should fail when more than 950 characters are in a word 1783 call setline(1, repeat('x', 951) .. ' one two three') 1784 exe "normal! Gox\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>" 1785 call assert_equal(repeat('x', 951), getline(2)) 1786 1787 " Test for adding a very long word to an existing completion 1788 %d 1789 call setline(1, ['abc', repeat('x', 1016) .. '012345']) 1790 exe "normal! Goab\<C-P>\<C-X>\<C-P>" 1791 call assert_equal('abc ' .. repeat('x', 1016) .. '0123', getline(3)) 1792 bw! 1793 endfunc 1794 1795 " Test for some fields in the complete items used by complete() 1796 func Test_complete_items() 1797 func CompleteItems(idx) 1798 let items = [[#{word: "one", dup: 1, user_data: 'u1'}, #{word: "one", dup: 1, user_data: 'u2'}], 1799 \ [#{word: "one", dup: 0, user_data: 'u3'}, #{word: "one", dup: 0, user_data: 'u4'}], 1800 \ [#{word: "one", icase: 1, user_data: 'u7'}, #{word: "oNE", icase: 1, user_data: 'u8'}], 1801 \ [#{user_data: 'u9'}], 1802 \ [#{word: "", user_data: 'u10'}], 1803 \ [#{word: "", empty: 1, user_data: 'u11'}]] 1804 call complete(col('.'), items[a:idx]) 1805 return '' 1806 endfunc 1807 new 1808 exe "normal! i\<C-R>=CompleteItems(0)\<CR>\<C-N>\<C-Y>" 1809 call assert_equal('u2', v:completed_item.user_data) 1810 call assert_equal('one', getline(1)) 1811 exe "normal! o\<C-R>=CompleteItems(1)\<CR>\<C-Y>" 1812 call assert_equal('u3', v:completed_item.user_data) 1813 call assert_equal('one', getline(2)) 1814 exe "normal! o\<C-R>=CompleteItems(1)\<CR>\<C-N>" 1815 call assert_equal('', getline(3)) 1816 set completeopt=menu,noinsert 1817 exe "normal! o\<C-R>=CompleteItems(2)\<CR>one\<C-N>\<C-Y>" 1818 call assert_equal('oNE', getline(4)) 1819 call assert_equal('u8', v:completed_item.user_data) 1820 set completeopt& 1821 exe "normal! o\<C-R>=CompleteItems(3)\<CR>" 1822 call assert_equal('', getline(5)) 1823 exe "normal! o\<C-R>=CompleteItems(4)\<CR>" 1824 call assert_equal('', getline(6)) 1825 exe "normal! o\<C-R>=CompleteItems(5)\<CR>" 1826 call assert_equal('', getline(7)) 1827 call assert_equal('u11', v:completed_item.user_data) 1828 " pass invalid argument to complete() 1829 let cmd = "normal! o\<C-R>=complete(1, [[]])\<CR>" 1830 call assert_fails('exe cmd', 'E730:') 1831 bw! 1832 delfunc CompleteItems 1833 endfunc 1834 1835 " Test for the "refresh" item in the dict returned by an insert completion 1836 " function 1837 func Test_complete_item_refresh_always() 1838 let g:CallCount = 0 1839 func! Tcomplete(findstart, base) 1840 if a:findstart 1841 " locate the start of the word 1842 let line = getline('.') 1843 let start = col('.') - 1 1844 while start > 0 && line[start - 1] =~ '\a' 1845 let start -= 1 1846 endwhile 1847 return start 1848 else 1849 let g:CallCount += 1 1850 let res = ["update1", "update12", "update123"] 1851 return #{words: res, refresh: 'always'} 1852 endif 1853 endfunc 1854 set completeopt=menu,longest 1855 set completefunc=Tcomplete 1856 new 1857 exe "normal! iup\<C-X>\<C-U>\<BS>\<BS>\<BS>\<BS>\<BS>" 1858 call assert_equal('up', getline(1)) 1859 call assert_equal(6, g:CallCount) 1860 %d 1861 let g:CallCount = 0 1862 set complete=FTcomplete 1863 exe "normal! iup\<C-N>\<BS>\<BS>\<BS>\<BS>\<BS>" 1864 call assert_equal('up', getline(1)) 1865 call assert_equal(6, g:CallCount) 1866 %d 1867 let g:CallCount = 0 1868 set complete=F 1869 exe "normal! iup\<C-N>\<BS>\<BS>\<BS>\<BS>\<BS>" 1870 call assert_equal('up', getline(1)) 1871 call assert_equal(6, g:CallCount) 1872 %d 1873 let g:CallCount = 0 1874 set omnifunc=Tcomplete 1875 set complete=o 1876 exe "normal! iup\<C-N>\<BS>\<BS>\<BS>\<BS>\<BS>" 1877 call assert_equal('up', getline(1)) 1878 call assert_equal(6, g:CallCount) 1879 bw! 1880 set completeopt& 1881 set complete& 1882 set completefunc& 1883 delfunc Tcomplete 1884 endfunc 1885 1886 " Test for 'cpt' user func that fails (return -2/-3) when refresh:always 1887 func Test_cpt_func_refresh_always_fail() 1888 func! CompleteFail(retval, findstart, base) 1889 if a:findstart 1890 return a:retval 1891 endif 1892 call assert_equal(-999, a:findstart) " Should not reach here 1893 endfunc 1894 new 1895 set complete=Ffunction('CompleteFail'\\,\ [-2]) 1896 exe "normal! ia\<C-N>" 1897 %d 1898 set complete=Ffunction('CompleteFail'\\,\ [-3]) 1899 exe "normal! ia\<C-N>" 1900 bw! 1901 1902 func! CompleteFailIntermittent(retval, findstart, base) 1903 if a:findstart 1904 if g:CallCount == 2 1905 let g:CallCount += 1 1906 return a:retval 1907 endif 1908 return col('.') - 1 1909 endif 1910 let g:CallCount += 1 1911 let res = [[], ['foo', 'fbar'], ['foo1', 'foo2'], ['foofail'], ['fooo3']] 1912 return #{words: res[g:CallCount], refresh: 'always'} 1913 endfunc 1914 new 1915 set completeopt=menuone,noselect 1916 set complete=Ffunction('CompleteFailIntermittent'\\,\ [-2]) 1917 let g:CallCount = 0 1918 exe "normal! if\<C-N>\<c-r>=complete_info([\"items\"])\<cr>" 1919 call assert_match('''word'': ''foo''.*''word'': ''fbar''', getline(1)) 1920 call assert_equal(1, g:CallCount) 1921 %d 1922 let g:CallCount = 0 1923 exe "normal! if\<C-N>o\<c-r>=complete_info([\"items\", \"selected\"])\<cr>" 1924 call assert_match('''selected'': -1.*''word'': ''foo1''.*''word'': ''foo2''', getline(1)) 1925 call assert_equal(2, g:CallCount) 1926 %d 1927 set complete=Ffunction('CompleteFailIntermittent'\\,\ [-3]) 1928 let g:CallCount = 0 1929 exe "normal! if\<C-N>o\<c-r>=complete_info([\"items\", \"selected\"])\<cr>" 1930 call assert_match('''selected'': -1.*''word'': ''foo1''.*''word'': ''foo2''', getline(1)) 1931 call assert_equal(2, g:CallCount) 1932 %d 1933 set complete=Ffunction('CompleteFailIntermittent'\\,\ [-2]) 1934 " completion mode is dismissed when there are no matches in list 1935 let g:CallCount = 0 1936 exe "normal! if\<C-N>oo\<c-r>=complete_info([\"items\"])\<cr>" 1937 call assert_equal('foo{''items'': []}', getline(1)) 1938 call assert_equal(3, g:CallCount) 1939 %d 1940 let g:CallCount = 0 1941 exe "normal! if\<C-N>oo\<bs>\<c-r>=complete_info([\"items\"])\<cr>" 1942 call assert_equal('fo{''items'': []}', getline(1)) 1943 call assert_equal(3, g:CallCount) 1944 %d 1945 " completion mode continues when matches from other sources present 1946 set complete=.,Ffunction('CompleteFailIntermittent'\\,\ [-2]) 1947 call setline(1, 'fooo1') 1948 let g:CallCount = 0 1949 exe "normal! Gof\<C-N>oo\<c-r>=complete_info([\"items\", \"selected\"])\<cr>" 1950 call assert_equal('foo{''selected'': -1, ''items'': [{''word'': ''fooo1'', ''menu'': '''', ' 1951 \ . '''user_data'': '''', ''info'': '''', ''kind'': '''', ''abbr'': ''''}]}', 1952 \ getline(2)) 1953 call assert_equal(3, g:CallCount) 1954 %d 1955 call setline(1, 'fooo1') 1956 let g:CallCount = 0 1957 exe "normal! Gof\<C-N>oo\<bs>\<c-r>=complete_info([\"items\"])\<cr>" 1958 call assert_match('''word'': ''fooo1''.*''word'': ''fooo3''', getline(2)) 1959 call assert_equal(4, g:CallCount) 1960 %d 1961 " refresh will stop when -3 is returned 1962 set complete=.,,\ Ffunction('CompleteFailIntermittent'\\,\ [-3]) 1963 call setline(1, 'fooo1') 1964 let g:CallCount = 0 1965 exe "normal! Gof\<C-N>o\<bs>\<c-r>=complete_info([\"items\", \"selected\"])\<cr>" 1966 call assert_equal('f{''selected'': -1, ''items'': [{''word'': ''fooo1'', ''menu'': '''', ' 1967 \ . '''user_data'': '''', ''info'': '''', ''kind'': '''', ''abbr'': ''''}]}', 1968 \ getline(2)) 1969 call assert_equal(3, g:CallCount) 1970 %d 1971 call setline(1, 'fooo1') 1972 let g:CallCount = 0 1973 exe "normal! Gof\<C-N>oo\<bs>\<c-r>=complete_info([\"items\", \"selected\"])\<cr>" 1974 call assert_equal('fo{''selected'': -1, ''items'': [{''word'': ''fooo1'', ''menu'': '''', ' 1975 \ . '''user_data'': '''', ''info'': '''', ''kind'': '''', ''abbr'': ''''}]}', 1976 \ getline(2)) 1977 call assert_equal(3, g:CallCount) 1978 bw! 1979 1980 set complete& completeopt& 1981 delfunc CompleteFail 1982 delfunc CompleteFailIntermittent 1983 endfunc 1984 1985 " Select items before they are removed by refresh:always 1986 func Test_cpt_select_item_refresh_always() 1987 1988 func CompleteMenuWords() 1989 let info = complete_info(["items", "selected"]) 1990 call map(info.items, {_, v -> v.word}) 1991 return info 1992 endfunc 1993 1994 func! CompleteItemsSelect(compl, findstart, base) 1995 if a:findstart 1996 return col('.') - 1 1997 endif 1998 let g:CallCount += 1 1999 if g:CallCount == 2 2000 return #{words: a:compl, refresh: 'always'} 2001 endif 2002 let res = [[], ['fo', 'foobar'], [], ['foo1', 'foo2']] 2003 return #{words: res[g:CallCount], refresh: 'always'} 2004 endfunc 2005 2006 new 2007 set complete=.,Ffunction('CompleteItemsSelect'\\,\ [[]]) 2008 call setline(1, "foobarbar") 2009 let g:CallCount = 0 2010 exe "normal! Gof\<c-n>\<c-n>\<c-r>=CompleteMenuWords()\<cr>" 2011 call assert_equal('fo{''selected'': 1, ''items'': [''foobarbar'', ''fo'', ''foobar'']}', getline(2)) 2012 call assert_equal(1, g:CallCount) 2013 %d 2014 call setline(1, "foobarbar") 2015 let g:CallCount = 0 2016 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<c-r>=CompleteMenuWords()\<cr>" 2017 call assert_equal('fo{''selected'': 0, ''items'': [''fo'', ''foobar'', ''foobarbar'']}', getline(2)) 2018 call assert_equal(1, g:CallCount) 2019 %d 2020 call setline(1, "foobarbar") 2021 let g:CallCount = 0 2022 exe "normal! Gof\<c-n>\<c-n>o\<c-r>=CompleteMenuWords()\<cr>" 2023 call assert_equal('foo{''selected'': -1, ''items'': []}' , getline(2)) 2024 call assert_equal(1, g:CallCount) 2025 %d 2026 call setline(1, "foobarbar") 2027 let g:CallCount = 0 2028 exe "normal! Gof\<c-n>\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2029 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'']}', getline(2)) 2030 call assert_equal(2, g:CallCount) 2031 %d 2032 call setline(1, "foobarbar") 2033 let g:CallCount = 0 2034 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2035 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'']}', getline(2)) 2036 call assert_equal(2, g:CallCount) 2037 2038 %d 2039 set complete=.,Ffunction('CompleteItemsSelect'\\,\ [['foonext']]) 2040 call setline(1, "foobarbar") 2041 let g:CallCount = 0 2042 exe "normal! Gof\<c-n>\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2043 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'', ''foonext'']}', getline(2)) 2044 call assert_equal(2, g:CallCount) 2045 %d 2046 call setline(1, "foobarbar") 2047 let g:CallCount = 0 2048 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2049 call assert_equal('f{''selected'': -1, ''items'': [''foonext'', ''foobarbar'']}', getline(2)) 2050 call assert_equal(2, g:CallCount) 2051 2052 %d 2053 call setline(1, "foob") 2054 let g:CallCount = 0 2055 exe "normal! Gof\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2056 call assert_equal('foo{''selected'': 0, ''items'': [''foob'', ''foonext'']}', getline(2)) 2057 call assert_equal(2, g:CallCount) 2058 %d 2059 call setline(1, "foob") 2060 let g:CallCount = 0 2061 exe "normal! Gof\<c-n>\<bs>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2062 call assert_equal('fo{''selected'': 0, ''items'': [''foob'', ''foo1'', ''foo2'']}', getline(2)) 2063 call assert_equal(3, g:CallCount) 2064 2065 %d 2066 call setline(1, "foob") 2067 let g:CallCount = 0 2068 exe "normal! Gof\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2069 call assert_equal('foo{''selected'': 1, ''items'': [''foonext'', ''foob'']}', getline(2)) 2070 call assert_equal(2, g:CallCount) 2071 %d 2072 call setline(1, "foob") 2073 let g:CallCount = 0 2074 exe "normal! Gof\<c-p>\<bs>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2075 call assert_equal('fo{''selected'': 2, ''items'': [''foo1'', ''foo2'', ''foob'']}', getline(2)) 2076 call assert_equal(3, g:CallCount) 2077 2078 %d 2079 set complete=.,Ffunction('CompleteItemsSelect'\\,\ [['fo'\\,\ 'foonext']]) 2080 call setline(1, "foobarbar") 2081 let g:CallCount = 0 2082 exe "normal! Gof\<c-n>\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2083 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'', ''fo'', ''foonext'']}', getline(2)) 2084 call assert_equal(2, g:CallCount) 2085 %d 2086 call setline(1, "foobarbar") 2087 let g:CallCount = 0 2088 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>" 2089 call assert_equal('f{''selected'': -1, ''items'': [''fo'', ''foonext'', ''foobarbar'']}', getline(2)) 2090 call assert_equal(2, g:CallCount) 2091 bw! 2092 2093 set complete& 2094 delfunc CompleteMenuWords 2095 delfunc CompleteItemsSelect 2096 endfunc 2097 2098 " Test two functions together, each returning refresh:always 2099 func Test_cpt_multi_func_refresh_always() 2100 2101 func CompleteMenuMatches() 2102 let info = complete_info(["matches", "selected"]) 2103 call map(info.matches, {_, v -> v.word}) 2104 return info 2105 endfunc 2106 2107 func! CompleteItems1(findstart, base) 2108 if a:findstart 2109 return col('.') - 1 2110 endif 2111 let g:CallCount1 += 1 2112 let res = [[], [], ['foo1', 'foobar1'], [], ['foo11', 'foo12'], [], ['foo13', 'foo14']] 2113 return #{words: res[g:CallCount1], refresh: 'always'} 2114 endfunc 2115 2116 func! CompleteItems2(findstart, base) 2117 if a:findstart 2118 return col('.') - 1 2119 endif 2120 let g:CallCount2 += 1 2121 let res = [[], [], [], ['foo2', 'foobar2'], ['foo21', 'foo22'], ['foo23'], []] 2122 return #{words: res[g:CallCount2], refresh: 'always'} 2123 endfunc 2124 2125 set complete= 2126 exe "normal! if\<C-N>\<c-r>=CompleteMenuMatches()\<cr>" 2127 " \x0e is <c-n> 2128 call assert_equal("f\x0e" . '{''matches'': [], ''selected'': -1}', getline(1)) 2129 2130 set completeopt=menuone,noselect 2131 set complete=FCompleteItems1,FCompleteItems2 2132 2133 new 2134 let g:CallCount1 = 0 2135 let g:CallCount2 = 0 2136 exe "normal! if\<c-n>o\<c-n>o\<c-r>=CompleteMenuMatches()\<cr>" 2137 call assert_equal('foo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1)) 2138 call assert_equal(3, g:CallCount1) 2139 call assert_equal(3, g:CallCount2) 2140 %d 2141 let g:CallCount1 = 0 2142 let g:CallCount2 = 0 2143 exe "normal! if\<c-p>o\<c-p>o\<c-r>=CompleteMenuMatches()\<cr>" 2144 call assert_equal('foo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1)) 2145 call assert_equal(3, g:CallCount1) 2146 call assert_equal(3, g:CallCount2) 2147 %d 2148 let g:CallCount1 = 0 2149 let g:CallCount2 = 0 2150 exe "normal! if\<c-p>\<c-r>=CompleteMenuMatches()\<cr>" 2151 call assert_equal('f{''matches'': [], ''selected'': -1}', getline(1)) 2152 call assert_equal(1, g:CallCount1) 2153 call assert_equal(1, g:CallCount2) 2154 %d 2155 let g:CallCount1 = 1 2156 let g:CallCount2 = 1 2157 exe "normal! if\<c-n>\<c-r>=CompleteMenuMatches()\<cr>" 2158 call assert_equal('f{''matches'': [''foo1'', ''foobar1''], ''selected'': -1}', getline(1)) 2159 call assert_equal(2, g:CallCount2) 2160 call assert_equal(2, g:CallCount2) 2161 %d 2162 let g:CallCount1 = 1 2163 let g:CallCount2 = 1 2164 exe "normal! if\<c-n>o\<c-r>=CompleteMenuMatches()\<cr>" 2165 call assert_equal('fo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1)) 2166 call assert_equal(3, g:CallCount2) 2167 call assert_equal(3, g:CallCount2) 2168 %d 2169 let g:CallCount1 = 1 2170 let g:CallCount2 = 1 2171 exe "normal! if\<c-p>o\<c-r>=CompleteMenuMatches()\<cr>" 2172 call assert_equal('fo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1)) 2173 call assert_equal(3, g:CallCount2) 2174 call assert_equal(3, g:CallCount2) 2175 %d 2176 let g:CallCount1 = 1 2177 let g:CallCount2 = 1 2178 exe "normal! if\<c-n>oo\<c-r>=CompleteMenuMatches()\<cr>" 2179 call assert_equal('foo{''matches'': [''foo11'', ''foo12'', ''foo21'', ''foo22''], ''selected'': -1}', getline(1)) 2180 call assert_equal(4, g:CallCount2) 2181 call assert_equal(4, g:CallCount2) 2182 %d 2183 let g:CallCount1 = 1 2184 let g:CallCount2 = 1 2185 exe "normal! if\<c-n>oo\<bs>\<c-r>=CompleteMenuMatches()\<cr>" 2186 call assert_equal('fo{''matches'': [''foo23''], ''selected'': -1}', getline(1)) 2187 call assert_equal(5, g:CallCount2) 2188 call assert_equal(5, g:CallCount2) 2189 %d 2190 let g:CallCount1 = 1 2191 let g:CallCount2 = 1 2192 exe "normal! if\<c-p>oo\<bs>\<c-r>=CompleteMenuMatches()\<cr>" 2193 call assert_equal('fo{''matches'': [''foo23''], ''selected'': -1}', getline(1)) 2194 call assert_equal(5, g:CallCount2) 2195 call assert_equal(5, g:CallCount2) 2196 %d 2197 let g:CallCount1 = 1 2198 let g:CallCount2 = 1 2199 exe "normal! if\<c-n>oo\<bs>o\<c-r>=CompleteMenuMatches()\<cr>" 2200 call assert_equal('foo{''matches'': [''foo13'', ''foo14''], ''selected'': -1}', getline(1)) 2201 call assert_equal(6, g:CallCount2) 2202 call assert_equal(6, g:CallCount2) 2203 bw! 2204 2205 set complete& completeopt& 2206 delfunc CompleteMenuMatches 2207 delfunc CompleteItems1 2208 delfunc CompleteItems2 2209 endfunc 2210 2211 " Test for completing from a thesaurus file without read permission 2212 func Test_complete_unreadable_thesaurus_file() 2213 CheckUnix 2214 CheckNotRoot 2215 2216 call writefile(['about', 'above'], 'Xfile') 2217 call setfperm('Xfile', '---r--r--') 2218 new 2219 set complete=sXfile 2220 exe "normal! ia\<C-P>" 2221 call assert_equal('a', getline(1)) 2222 bw! 2223 call delete('Xfile') 2224 set complete& 2225 endfunc 2226 2227 " Test to ensure 'Scanning...' messages are not recorded in messages history 2228 func Test_z1_complete_no_history() 2229 new 2230 messages clear 2231 let currmess = execute('messages') 2232 setlocal dictionary=README.txt 2233 exe "normal owh\<C-X>\<C-K>" 2234 exe "normal owh\<C-N>" 2235 call assert_equal(currmess, execute('messages')) 2236 bwipe! 2237 endfunc 2238 2239 " A mapping is not used for the key after CTRL-X. 2240 func Test_no_mapping_for_ctrl_x_key() 2241 new 2242 inoremap <buffer> <C-K> <Cmd>let was_mapped = 'yes'<CR> 2243 setlocal dictionary=README.txt 2244 call feedkeys("aexam\<C-X>\<C-K> ", 'xt') 2245 call assert_equal('example ', getline(1)) 2246 call assert_false(exists('was_mapped')) 2247 bwipe! 2248 endfunc 2249 2250 " Test for different ways of setting a function in 'complete' option 2251 func Test_cpt_func_callback() 2252 func CompleteFunc1(callnr, findstart, base) 2253 call add(g:CompleteFunc1Args, [a:callnr, a:findstart, a:base]) 2254 return a:findstart ? 0 : [] 2255 endfunc 2256 func CompleteFunc2(findstart, base) 2257 call add(g:CompleteFunc2Args, [a:findstart, a:base]) 2258 return a:findstart ? 0 : [] 2259 endfunc 2260 2261 let lines =<< trim END 2262 #" Test for using a global function name 2263 set complete=Fg:CompleteFunc2 2264 new 2265 call setline(1, 'global') 2266 LET g:CompleteFunc2Args = [] 2267 call feedkeys("A\<C-N>\<Esc>", 'x') 2268 call assert_equal([[1, ''], [0, 'global']], g:CompleteFunc2Args) 2269 set complete& 2270 bw! 2271 2272 #" Test for using a function() 2273 set complete=Ffunction('g:CompleteFunc1'\\,\ [10]) 2274 new 2275 call setline(1, 'one') 2276 LET g:CompleteFunc1Args = [] 2277 call feedkeys("A\<C-N>\<Esc>", 'x') 2278 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:CompleteFunc1Args) 2279 set complete& 2280 bw! 2281 2282 #" Using a funcref variable 2283 set complete=Ffuncref('g:CompleteFunc1'\\,\ [11]) 2284 new 2285 call setline(1, 'two') 2286 LET g:CompleteFunc1Args = [] 2287 call feedkeys("A\<C-N>\<Esc>", 'x') 2288 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:CompleteFunc1Args) 2289 set complete& 2290 bw! 2291 2292 END 2293 call CheckLegacyAndVim9Success(lines) 2294 2295 " Test for using a script-local function name 2296 func s:CompleteFunc3(findstart, base) 2297 call add(g:CompleteFunc3Args, [a:findstart, a:base]) 2298 return a:findstart ? 0 : [] 2299 endfunc 2300 set complete=Fs:CompleteFunc3 2301 new 2302 call setline(1, 'script1') 2303 let g:CompleteFunc3Args = [] 2304 call feedkeys("A\<C-N>\<Esc>", 'x') 2305 call assert_equal([[1, ''], [0, 'script1']], g:CompleteFunc3Args) 2306 set complete& 2307 bw! 2308 2309 let &complete = 'Fs:CompleteFunc3' 2310 new 2311 call setline(1, 'script2') 2312 let g:CompleteFunc3Args = [] 2313 call feedkeys("A\<C-N>\<Esc>", 'x') 2314 call assert_equal([[1, ''], [0, 'script2']], g:CompleteFunc3Args) 2315 bw! 2316 delfunc s:CompleteFunc3 2317 set complete& 2318 2319 " In Vim9 script s: can be omitted 2320 let lines =<< trim END 2321 vim9script 2322 var CompleteFunc4Args = [] 2323 def CompleteFunc4(findstart: bool, base: string): any 2324 add(CompleteFunc4Args, [findstart, base]) 2325 return findstart ? 0 : [] 2326 enddef 2327 set complete=FCompleteFunc4 2328 new 2329 setline(1, 'script1') 2330 feedkeys("A\<C-N>\<Esc>", 'x') 2331 assert_equal([[1, ''], [0, 'script1']], CompleteFunc4Args) 2332 set complete& 2333 bw! 2334 END 2335 call CheckScriptSuccess(lines) 2336 2337 " Vim9 tests 2338 let lines =<< trim END 2339 vim9script 2340 2341 def Vim9CompleteFunc(callnr: number, findstart: number, base: string): any 2342 add(g:Vim9completeFuncArgs, [callnr, findstart, base]) 2343 return findstart ? 0 : [] 2344 enddef 2345 2346 # Test for using a def function with completefunc 2347 set complete=Ffunction('Vim9CompleteFunc'\\,\ [60]) 2348 new | only 2349 setline(1, 'one') 2350 g:Vim9completeFuncArgs = [] 2351 feedkeys("A\<C-N>\<Esc>", 'x') 2352 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9completeFuncArgs) 2353 bw! 2354 2355 # Test for using a global function name 2356 &complete = 'Fg:CompleteFunc2' 2357 new | only 2358 setline(1, 'two') 2359 g:CompleteFunc2Args = [] 2360 feedkeys("A\<C-N>\<Esc>", 'x') 2361 assert_equal([[1, ''], [0, 'two']], g:CompleteFunc2Args) 2362 bw! 2363 2364 # Test for using a script-local function name 2365 def LocalCompleteFunc(findstart: number, base: string): any 2366 add(g:LocalCompleteFuncArgs, [findstart, base]) 2367 return findstart ? 0 : [] 2368 enddef 2369 &complete = 'FLocalCompleteFunc' 2370 new | only 2371 setline(1, 'three') 2372 g:LocalCompleteFuncArgs = [] 2373 feedkeys("A\<C-N>\<Esc>", 'x') 2374 assert_equal([[1, ''], [0, 'three']], g:LocalCompleteFuncArgs) 2375 bw! 2376 END 2377 call CheckScriptSuccess(lines) 2378 2379 " cleanup 2380 set completefunc& complete& 2381 delfunc CompleteFunc1 2382 delfunc CompleteFunc2 2383 unlet g:CompleteFunc1Args g:CompleteFunc2Args 2384 %bw! 2385 endfunc 2386 2387 " Test for different ways of setting the 'completefunc' option 2388 func Test_completefunc_callback() 2389 func CompleteFunc1(callnr, findstart, base) 2390 call add(g:CompleteFunc1Args, [a:callnr, a:findstart, a:base]) 2391 return a:findstart ? 0 : [] 2392 endfunc 2393 func CompleteFunc2(findstart, base) 2394 call add(g:CompleteFunc2Args, [a:findstart, a:base]) 2395 return a:findstart ? 0 : [] 2396 endfunc 2397 2398 let lines =<< trim END 2399 #" Test for using a global function name 2400 LET &completefunc = 'g:CompleteFunc2' 2401 new 2402 call setline(1, 'global') 2403 LET g:CompleteFunc2Args = [] 2404 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2405 call assert_equal([[1, ''], [0, 'global']], g:CompleteFunc2Args) 2406 bw! 2407 2408 #" Test for using a function() 2409 set completefunc=function('g:CompleteFunc1',\ [10]) 2410 new 2411 call setline(1, 'one') 2412 LET g:CompleteFunc1Args = [] 2413 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2414 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:CompleteFunc1Args) 2415 bw! 2416 2417 #" Using a funcref variable to set 'completefunc' 2418 VAR Fn = function('g:CompleteFunc1', [11]) 2419 LET &completefunc = Fn 2420 new 2421 call setline(1, 'two') 2422 LET g:CompleteFunc1Args = [] 2423 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2424 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:CompleteFunc1Args) 2425 bw! 2426 2427 #" Using string(funcref_variable) to set 'completefunc' 2428 LET Fn = function('g:CompleteFunc1', [12]) 2429 LET &completefunc = string(Fn) 2430 new 2431 call setline(1, 'two') 2432 LET g:CompleteFunc1Args = [] 2433 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2434 call assert_equal([[12, 1, ''], [12, 0, 'two']], g:CompleteFunc1Args) 2435 bw! 2436 2437 #" Test for using a funcref() 2438 set completefunc=funcref('g:CompleteFunc1',\ [13]) 2439 new 2440 call setline(1, 'three') 2441 LET g:CompleteFunc1Args = [] 2442 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2443 call assert_equal([[13, 1, ''], [13, 0, 'three']], g:CompleteFunc1Args) 2444 bw! 2445 2446 #" Using a funcref variable to set 'completefunc' 2447 LET Fn = funcref('g:CompleteFunc1', [14]) 2448 LET &completefunc = Fn 2449 new 2450 call setline(1, 'four') 2451 LET g:CompleteFunc1Args = [] 2452 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2453 call assert_equal([[14, 1, ''], [14, 0, 'four']], g:CompleteFunc1Args) 2454 bw! 2455 2456 #" Using a string(funcref_variable) to set 'completefunc' 2457 LET Fn = funcref('g:CompleteFunc1', [15]) 2458 LET &completefunc = string(Fn) 2459 new 2460 call setline(1, 'four') 2461 LET g:CompleteFunc1Args = [] 2462 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2463 call assert_equal([[15, 1, ''], [15, 0, 'four']], g:CompleteFunc1Args) 2464 bw! 2465 2466 #" Test for using a lambda function with set 2467 VAR optval = "LSTART a, b LMIDDLE CompleteFunc1(16, a, b) LEND" 2468 LET optval = substitute(optval, ' ', '\\ ', 'g') 2469 exe "set completefunc=" .. optval 2470 new 2471 call setline(1, 'five') 2472 LET g:CompleteFunc1Args = [] 2473 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2474 call assert_equal([[16, 1, ''], [16, 0, 'five']], g:CompleteFunc1Args) 2475 bw! 2476 2477 #" Set 'completefunc' to a lambda expression 2478 LET &completefunc = LSTART a, b LMIDDLE CompleteFunc1(17, a, b) LEND 2479 new 2480 call setline(1, 'six') 2481 LET g:CompleteFunc1Args = [] 2482 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2483 call assert_equal([[17, 1, ''], [17, 0, 'six']], g:CompleteFunc1Args) 2484 bw! 2485 2486 #" Set 'completefunc' to string(lambda_expression) 2487 LET &completefunc = 'LSTART a, b LMIDDLE CompleteFunc1(18, a, b) LEND' 2488 new 2489 call setline(1, 'six') 2490 LET g:CompleteFunc1Args = [] 2491 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2492 call assert_equal([[18, 1, ''], [18, 0, 'six']], g:CompleteFunc1Args) 2493 bw! 2494 2495 #" Set 'completefunc' to a variable with a lambda expression 2496 VAR Lambda = LSTART a, b LMIDDLE CompleteFunc1(19, a, b) LEND 2497 LET &completefunc = Lambda 2498 new 2499 call setline(1, 'seven') 2500 LET g:CompleteFunc1Args = [] 2501 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2502 call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:CompleteFunc1Args) 2503 bw! 2504 2505 #" Set 'completefunc' to a string(variable with a lambda expression) 2506 LET Lambda = LSTART a, b LMIDDLE CompleteFunc1(20, a, b) LEND 2507 LET &completefunc = string(Lambda) 2508 new 2509 call setline(1, 'seven') 2510 LET g:CompleteFunc1Args = [] 2511 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2512 call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:CompleteFunc1Args) 2513 bw! 2514 2515 #" Test for using a lambda function with incorrect return value 2516 LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND 2517 LET &completefunc = Lambda 2518 new 2519 call setline(1, 'eight') 2520 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2521 bw! 2522 2523 #" Test for clearing the 'completefunc' option 2524 set completefunc='' 2525 set completefunc& 2526 call assert_fails("set completefunc=function('abc')", "E700:") 2527 call assert_fails("set completefunc=funcref('abc')", "E700:") 2528 2529 #" set 'completefunc' to a non-existing function 2530 set completefunc=CompleteFunc2 2531 call setline(1, 'five') 2532 call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:') 2533 call assert_fails("LET &completefunc = function('NonExistingFunc')", 'E700:') 2534 LET g:CompleteFunc2Args = [] 2535 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2536 call assert_equal([[1, ''], [0, 'five']], g:CompleteFunc2Args) 2537 bw! 2538 2539 #" :setlocal and :setglobal 2540 set complete=F completefunc& 2541 setlocal completefunc=function('g:CompleteFunc1',\ [22]) 2542 call setline(1, 'sun') 2543 LET g:CompleteFunc1Args = [] 2544 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2545 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:CompleteFunc1Args) 2546 LET g:CompleteFunc1Args = [] 2547 call feedkeys("A\<C-N>\<Esc>", 'x') 2548 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:CompleteFunc1Args) 2549 new 2550 call setline(1, 'sun') 2551 LET g:CompleteFunc1Args = [] 2552 call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E764:') 2553 call assert_equal([], g:CompleteFunc1Args) 2554 LET g:CompleteFunc1Args = [] 2555 call feedkeys("A\<C-N>\<Esc>", 'x') 2556 call assert_equal([], g:CompleteFunc1Args) 2557 bw! 2558 setglobal completefunc=function('g:CompleteFunc1',\ [23]) 2559 call setline(1, 'sun') 2560 LET g:CompleteFunc1Args = [] 2561 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2562 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:CompleteFunc1Args) 2563 LET g:CompleteFunc1Args = [] 2564 call feedkeys("A\<C-N>\<Esc>", 'x') 2565 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:CompleteFunc1Args) 2566 setlocal completefunc& 2567 call setline(1, 'sun') 2568 LET g:CompleteFunc1Args = [] 2569 call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E764:') 2570 call assert_equal([], g:CompleteFunc1Args) 2571 LET g:CompleteFunc1Args = [] 2572 call feedkeys("A\<C-N>\<Esc>", 'x') 2573 call assert_equal([], g:CompleteFunc1Args) 2574 new 2575 call setline(1, 'sun') 2576 LET g:CompleteFunc1Args = [] 2577 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2578 call assert_equal([[23, 1, ''], [23, 0, 'sun']], g:CompleteFunc1Args) 2579 LET g:CompleteFunc1Args = [] 2580 call feedkeys("A\<C-N>\<Esc>", 'x') 2581 call assert_equal([[23, 1, ''], [23, 0, 'sun']], g:CompleteFunc1Args) 2582 set complete& completefunc& 2583 :%bw! 2584 END 2585 call CheckLegacyAndVim9Success(lines) 2586 2587 " Test for using a script-local function name 2588 func s:CompleteFunc3(findstart, base) 2589 call add(g:CompleteFunc3Args, [a:findstart, a:base]) 2590 return a:findstart ? 0 : [] 2591 endfunc 2592 set completefunc=s:CompleteFunc3 2593 new 2594 call setline(1, 'script1') 2595 let g:CompleteFunc3Args = [] 2596 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2597 call assert_equal([[1, ''], [0, 'script1']], g:CompleteFunc3Args) 2598 bw! 2599 2600 let &completefunc = 's:CompleteFunc3' 2601 new 2602 call setline(1, 'script2') 2603 let g:CompleteFunc3Args = [] 2604 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2605 call assert_equal([[1, ''], [0, 'script2']], g:CompleteFunc3Args) 2606 bw! 2607 delfunc s:CompleteFunc3 2608 2609 " In Vim9 script s: can be omitted 2610 let lines =<< trim END 2611 vim9script 2612 var CompleteFunc4Args = [] 2613 def CompleteFunc4(findstart: bool, base: string): any 2614 add(CompleteFunc4Args, [findstart, base]) 2615 return findstart ? 0 : [] 2616 enddef 2617 set completefunc=CompleteFunc4 2618 new 2619 setline(1, 'script1') 2620 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2621 assert_equal([[1, ''], [0, 'script1']], CompleteFunc4Args) 2622 bw! 2623 END 2624 call CheckScriptSuccess(lines) 2625 2626 " invalid return value 2627 let &completefunc = {a -> 'abc'} 2628 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2629 2630 " Using Vim9 lambda expression in legacy context should fail 2631 set completefunc=(a,\ b)\ =>\ CompleteFunc1(21,\ a,\ b) 2632 new | only 2633 let g:CompleteFunc1Args = [] 2634 call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:') 2635 call assert_equal([], g:CompleteFunc1Args) 2636 2637 " set 'completefunc' to a partial with dict. This used to cause a crash. 2638 func SetCompleteFunc() 2639 let params = {'complete': function('g:DictCompleteFunc')} 2640 let &completefunc = params.complete 2641 endfunc 2642 func g:DictCompleteFunc(_) dict 2643 endfunc 2644 call SetCompleteFunc() 2645 new 2646 call SetCompleteFunc() 2647 bw 2648 call test_garbagecollect_now() 2649 new 2650 set completefunc= 2651 wincmd w 2652 set completefunc= 2653 %bw! 2654 delfunc g:DictCompleteFunc 2655 delfunc SetCompleteFunc 2656 2657 " Vim9 tests 2658 let lines =<< trim END 2659 vim9script 2660 2661 def Vim9CompleteFunc(callnr: number, findstart: number, base: string): any 2662 add(g:Vim9completeFuncArgs, [callnr, findstart, base]) 2663 return findstart ? 0 : [] 2664 enddef 2665 2666 # Test for using a def function with completefunc 2667 set completefunc=function('Vim9CompleteFunc',\ [60]) 2668 new | only 2669 setline(1, 'one') 2670 g:Vim9completeFuncArgs = [] 2671 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2672 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9completeFuncArgs) 2673 bw! 2674 2675 # Test for using a global function name 2676 &completefunc = g:CompleteFunc2 2677 new | only 2678 setline(1, 'two') 2679 g:CompleteFunc2Args = [] 2680 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2681 assert_equal([[1, ''], [0, 'two']], g:CompleteFunc2Args) 2682 bw! 2683 2684 # Test for using a script-local function name 2685 def LocalCompleteFunc(findstart: number, base: string): any 2686 add(g:LocalCompleteFuncArgs, [findstart, base]) 2687 return findstart ? 0 : [] 2688 enddef 2689 &completefunc = LocalCompleteFunc 2690 new | only 2691 setline(1, 'three') 2692 g:LocalCompleteFuncArgs = [] 2693 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x') 2694 assert_equal([[1, ''], [0, 'three']], g:LocalCompleteFuncArgs) 2695 bw! 2696 END 2697 call CheckScriptSuccess(lines) 2698 2699 " cleanup 2700 set completefunc& 2701 delfunc CompleteFunc1 2702 delfunc CompleteFunc2 2703 unlet g:CompleteFunc1Args g:CompleteFunc2Args 2704 %bw! 2705 endfunc 2706 2707 " Test for different ways of setting the 'omnifunc' option 2708 func Test_omnifunc_callback() 2709 func OmniFunc1(callnr, findstart, base) 2710 call add(g:OmniFunc1Args, [a:callnr, a:findstart, a:base]) 2711 return a:findstart ? 0 : [] 2712 endfunc 2713 func OmniFunc2(findstart, base) 2714 call add(g:OmniFunc2Args, [a:findstart, a:base]) 2715 return a:findstart ? 0 : [] 2716 endfunc 2717 2718 let lines =<< trim END 2719 #" Test for using a function name 2720 LET &omnifunc = 'g:OmniFunc2' 2721 new 2722 call setline(1, 'zero') 2723 LET g:OmniFunc2Args = [] 2724 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2725 call assert_equal([[1, ''], [0, 'zero']], g:OmniFunc2Args) 2726 bw! 2727 2728 #" Test for using a function() 2729 set omnifunc=function('g:OmniFunc1',\ [10]) 2730 new 2731 call setline(1, 'one') 2732 LET g:OmniFunc1Args = [] 2733 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2734 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:OmniFunc1Args) 2735 bw! 2736 2737 #" Using a funcref variable to set 'omnifunc' 2738 VAR Fn = function('g:OmniFunc1', [11]) 2739 LET &omnifunc = Fn 2740 new 2741 call setline(1, 'two') 2742 LET g:OmniFunc1Args = [] 2743 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2744 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:OmniFunc1Args) 2745 bw! 2746 2747 #" Using a string(funcref_variable) to set 'omnifunc' 2748 LET Fn = function('g:OmniFunc1', [12]) 2749 LET &omnifunc = string(Fn) 2750 new 2751 call setline(1, 'two') 2752 LET g:OmniFunc1Args = [] 2753 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2754 call assert_equal([[12, 1, ''], [12, 0, 'two']], g:OmniFunc1Args) 2755 bw! 2756 2757 #" Test for using a funcref() 2758 set omnifunc=funcref('g:OmniFunc1',\ [13]) 2759 new 2760 call setline(1, 'three') 2761 LET g:OmniFunc1Args = [] 2762 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2763 call assert_equal([[13, 1, ''], [13, 0, 'three']], g:OmniFunc1Args) 2764 bw! 2765 2766 #" Use let to set 'omnifunc' to a funcref 2767 LET Fn = funcref('g:OmniFunc1', [14]) 2768 LET &omnifunc = Fn 2769 new 2770 call setline(1, 'four') 2771 LET g:OmniFunc1Args = [] 2772 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2773 call assert_equal([[14, 1, ''], [14, 0, 'four']], g:OmniFunc1Args) 2774 bw! 2775 2776 #" Using a string(funcref) to set 'omnifunc' 2777 LET Fn = funcref("g:OmniFunc1", [15]) 2778 LET &omnifunc = string(Fn) 2779 new 2780 call setline(1, 'four') 2781 LET g:OmniFunc1Args = [] 2782 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2783 call assert_equal([[15, 1, ''], [15, 0, 'four']], g:OmniFunc1Args) 2784 bw! 2785 2786 #" Test for using a lambda function with set 2787 VAR optval = "LSTART a, b LMIDDLE OmniFunc1(16, a, b) LEND" 2788 LET optval = substitute(optval, ' ', '\\ ', 'g') 2789 exe "set omnifunc=" .. optval 2790 new 2791 call setline(1, 'five') 2792 LET g:OmniFunc1Args = [] 2793 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2794 call assert_equal([[16, 1, ''], [16, 0, 'five']], g:OmniFunc1Args) 2795 bw! 2796 2797 #" Set 'omnifunc' to a lambda expression 2798 LET &omnifunc = LSTART a, b LMIDDLE OmniFunc1(17, a, b) LEND 2799 new 2800 call setline(1, 'six') 2801 LET g:OmniFunc1Args = [] 2802 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2803 call assert_equal([[17, 1, ''], [17, 0, 'six']], g:OmniFunc1Args) 2804 bw! 2805 2806 #" Set 'omnifunc' to a string(lambda_expression) 2807 LET &omnifunc = 'LSTART a, b LMIDDLE OmniFunc1(18, a, b) LEND' 2808 new 2809 call setline(1, 'six') 2810 LET g:OmniFunc1Args = [] 2811 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2812 call assert_equal([[18, 1, ''], [18, 0, 'six']], g:OmniFunc1Args) 2813 bw! 2814 2815 #" Set 'omnifunc' to a variable with a lambda expression 2816 VAR Lambda = LSTART a, b LMIDDLE OmniFunc1(19, a, b) LEND 2817 LET &omnifunc = Lambda 2818 new 2819 call setline(1, 'seven') 2820 LET g:OmniFunc1Args = [] 2821 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2822 call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:OmniFunc1Args) 2823 bw! 2824 2825 #" Set 'omnifunc' to a string(variable with a lambda expression) 2826 LET Lambda = LSTART a, b LMIDDLE OmniFunc1(20, a, b) LEND 2827 LET &omnifunc = string(Lambda) 2828 new 2829 call setline(1, 'seven') 2830 LET g:OmniFunc1Args = [] 2831 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2832 call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:OmniFunc1Args) 2833 bw! 2834 2835 #" Test for using a lambda function with incorrect return value 2836 LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND 2837 LET &omnifunc = Lambda 2838 new 2839 call setline(1, 'eight') 2840 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2841 bw! 2842 2843 #" Test for clearing the 'omnifunc' option 2844 set omnifunc='' 2845 set omnifunc& 2846 call assert_fails("set omnifunc=function('abc')", "E700:") 2847 call assert_fails("set omnifunc=funcref('abc')", "E700:") 2848 2849 #" set 'omnifunc' to a non-existing function 2850 set omnifunc=OmniFunc2 2851 call setline(1, 'nine') 2852 call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:') 2853 call assert_fails("LET &omnifunc = function('NonExistingFunc')", 'E700:') 2854 LET g:OmniFunc2Args = [] 2855 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2856 call assert_equal([[1, ''], [0, 'nine']], g:OmniFunc2Args) 2857 bw! 2858 2859 #" :setlocal and :setglobal 2860 set complete=o omnifunc& 2861 setlocal omnifunc=function('g:OmniFunc1',\ [22]) 2862 call setline(1, 'sun') 2863 LET g:OmniFunc1Args = [] 2864 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2865 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:OmniFunc1Args) 2866 LET g:OmniFunc1Args = [] 2867 call feedkeys("A\<C-N>\<Esc>", 'x') 2868 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:OmniFunc1Args) 2869 new 2870 call setline(1, 'sun') 2871 LET g:OmniFunc1Args = [] 2872 call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E764:') 2873 call assert_equal([], g:OmniFunc1Args) 2874 LET g:OmniFunc1Args = [] 2875 call feedkeys("A\<C-N>\<Esc>", 'x') 2876 call assert_equal([], g:OmniFunc1Args) 2877 bw! 2878 setglobal omnifunc=function('g:OmniFunc1',\ [23]) 2879 call setline(1, 'sun') 2880 LET g:OmniFunc1Args = [] 2881 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2882 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:OmniFunc1Args) 2883 LET g:OmniFunc1Args = [] 2884 call feedkeys("A\<C-N>\<Esc>", 'x') 2885 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:OmniFunc1Args) 2886 setlocal omnifunc& 2887 call setline(1, 'sun') 2888 LET g:OmniFunc1Args = [] 2889 call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E764:') 2890 call assert_equal([], g:OmniFunc1Args) 2891 LET g:OmniFunc1Args = [] 2892 call feedkeys("A\<C-N>\<Esc>", 'x') 2893 call assert_equal([], g:OmniFunc1Args) 2894 new 2895 call setline(1, 'sun') 2896 LET g:OmniFunc1Args = [] 2897 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2898 call assert_equal([[23, 1, ''], [23, 0, 'sun']], g:OmniFunc1Args) 2899 LET g:OmniFunc1Args = [] 2900 call feedkeys("A\<C-N>\<Esc>", 'x') 2901 call assert_equal([[23, 1, ''], [23, 0, 'sun']], g:OmniFunc1Args) 2902 set complete& omnifunc& 2903 :%bw! 2904 END 2905 call CheckLegacyAndVim9Success(lines) 2906 2907 " Test for using a script-local function name 2908 func s:OmniFunc3(findstart, base) 2909 call add(g:OmniFunc3Args, [a:findstart, a:base]) 2910 return a:findstart ? 0 : [] 2911 endfunc 2912 set omnifunc=s:OmniFunc3 2913 new 2914 call setline(1, 'script1') 2915 let g:OmniFunc3Args = [] 2916 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2917 call assert_equal([[1, ''], [0, 'script1']], g:OmniFunc3Args) 2918 bw! 2919 2920 set complete=Fs:OmniFunc3 2921 new 2922 call setline(1, 'script1') 2923 let g:OmniFunc3Args = [] 2924 call feedkeys("A\<C-N>\<Esc>", 'x') 2925 call assert_equal([[1, ''], [0, 'script1']], g:OmniFunc3Args) 2926 bw! 2927 set complete& 2928 2929 let &omnifunc = 's:OmniFunc3' 2930 new 2931 call setline(1, 'script2') 2932 let g:OmniFunc3Args = [] 2933 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2934 call assert_equal([[1, ''], [0, 'script2']], g:OmniFunc3Args) 2935 bw! 2936 delfunc s:OmniFunc3 2937 2938 " invalid return value 2939 let &omnifunc = {a -> 'abc'} 2940 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2941 2942 " Using Vim9 lambda expression in legacy context should fail 2943 set omnifunc=(a,\ b)\ =>\ OmniFunc1(21,\ a,\ b) 2944 new | only 2945 let g:OmniFunc1Args = [] 2946 call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:') 2947 call assert_equal([], g:OmniFunc1Args) 2948 2949 " set 'omnifunc' to a partial with dict. This used to cause a crash. 2950 func SetOmniFunc() 2951 let params = {'omni': function('g:DictOmniFunc')} 2952 let &omnifunc = params.omni 2953 endfunc 2954 func g:DictOmniFunc(_) dict 2955 endfunc 2956 call SetOmniFunc() 2957 new 2958 call SetOmniFunc() 2959 bw 2960 call test_garbagecollect_now() 2961 new 2962 set omnifunc= 2963 wincmd w 2964 set omnifunc= 2965 %bw! 2966 delfunc g:DictOmniFunc 2967 delfunc SetOmniFunc 2968 2969 " Vim9 tests 2970 let lines =<< trim END 2971 vim9script 2972 2973 def Vim9omniFunc(callnr: number, findstart: number, base: string): any 2974 add(g:Vim9omniFunc_Args, [callnr, findstart, base]) 2975 return findstart ? 0 : [] 2976 enddef 2977 2978 # Test for using a def function with omnifunc 2979 set omnifunc=function('Vim9omniFunc',\ [60]) 2980 new | only 2981 setline(1, 'one') 2982 g:Vim9omniFunc_Args = [] 2983 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2984 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9omniFunc_Args) 2985 bw! 2986 2987 # Test for using a global function name 2988 &omnifunc = g:OmniFunc2 2989 new | only 2990 setline(1, 'two') 2991 g:OmniFunc2Args = [] 2992 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 2993 assert_equal([[1, ''], [0, 'two']], g:OmniFunc2Args) 2994 bw! 2995 2996 # Test for using a script-local function name 2997 def LocalOmniFunc(findstart: number, base: string): any 2998 add(g:LocalOmniFuncArgs, [findstart, base]) 2999 return findstart ? 0 : [] 3000 enddef 3001 &omnifunc = LocalOmniFunc 3002 new | only 3003 setline(1, 'three') 3004 g:LocalOmniFuncArgs = [] 3005 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x') 3006 assert_equal([[1, ''], [0, 'three']], g:LocalOmniFuncArgs) 3007 bw! 3008 END 3009 call CheckScriptSuccess(lines) 3010 3011 " cleanup 3012 set omnifunc& 3013 delfunc OmniFunc1 3014 delfunc OmniFunc2 3015 unlet g:OmniFunc1Args g:OmniFunc2Args 3016 %bw! 3017 endfunc 3018 3019 " Test for different ways of setting the 'thesaurusfunc' option 3020 func Test_thesaurusfunc_callback() 3021 func TsrFunc1(callnr, findstart, base) 3022 call add(g:TsrFunc1Args, [a:callnr, a:findstart, a:base]) 3023 return a:findstart ? 0 : [] 3024 endfunc 3025 func TsrFunc2(findstart, base) 3026 call add(g:TsrFunc2Args, [a:findstart, a:base]) 3027 return a:findstart ? 0 : ['sunday'] 3028 endfunc 3029 3030 let lines =<< trim END 3031 #" Test for using a function name 3032 LET &thesaurusfunc = 'g:TsrFunc2' 3033 new 3034 call setline(1, 'zero') 3035 LET g:TsrFunc2Args = [] 3036 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3037 call assert_equal([[1, ''], [0, 'zero']], g:TsrFunc2Args) 3038 bw! 3039 3040 #" Test for using a function() 3041 set thesaurusfunc=function('g:TsrFunc1',\ [10]) 3042 new 3043 call setline(1, 'one') 3044 LET g:TsrFunc1Args = [] 3045 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3046 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:TsrFunc1Args) 3047 bw! 3048 3049 #" Using a funcref variable to set 'thesaurusfunc' 3050 VAR Fn = function('g:TsrFunc1', [11]) 3051 LET &thesaurusfunc = Fn 3052 new 3053 call setline(1, 'two') 3054 LET g:TsrFunc1Args = [] 3055 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3056 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:TsrFunc1Args) 3057 bw! 3058 3059 #" Using a string(funcref_variable) to set 'thesaurusfunc' 3060 LET Fn = function('g:TsrFunc1', [12]) 3061 LET &thesaurusfunc = string(Fn) 3062 new 3063 call setline(1, 'two') 3064 LET g:TsrFunc1Args = [] 3065 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3066 call assert_equal([[12, 1, ''], [12, 0, 'two']], g:TsrFunc1Args) 3067 bw! 3068 3069 #" Test for using a funcref() 3070 set thesaurusfunc=funcref('g:TsrFunc1',\ [13]) 3071 new 3072 call setline(1, 'three') 3073 LET g:TsrFunc1Args = [] 3074 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3075 call assert_equal([[13, 1, ''], [13, 0, 'three']], g:TsrFunc1Args) 3076 bw! 3077 3078 #" Using a funcref variable to set 'thesaurusfunc' 3079 LET Fn = funcref('g:TsrFunc1', [14]) 3080 LET &thesaurusfunc = Fn 3081 new 3082 call setline(1, 'four') 3083 LET g:TsrFunc1Args = [] 3084 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3085 call assert_equal([[14, 1, ''], [14, 0, 'four']], g:TsrFunc1Args) 3086 bw! 3087 3088 #" Using a string(funcref_variable) to set 'thesaurusfunc' 3089 LET Fn = funcref('g:TsrFunc1', [15]) 3090 LET &thesaurusfunc = string(Fn) 3091 new 3092 call setline(1, 'four') 3093 LET g:TsrFunc1Args = [] 3094 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3095 call assert_equal([[15, 1, ''], [15, 0, 'four']], g:TsrFunc1Args) 3096 bw! 3097 3098 #" Test for using a lambda function 3099 VAR optval = "LSTART a, b LMIDDLE TsrFunc1(16, a, b) LEND" 3100 LET optval = substitute(optval, ' ', '\\ ', 'g') 3101 exe "set thesaurusfunc=" .. optval 3102 new 3103 call setline(1, 'five') 3104 LET g:TsrFunc1Args = [] 3105 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3106 call assert_equal([[16, 1, ''], [16, 0, 'five']], g:TsrFunc1Args) 3107 bw! 3108 3109 #" Test for using a lambda function with set 3110 LET &thesaurusfunc = LSTART a, b LMIDDLE TsrFunc1(17, a, b) LEND 3111 new 3112 call setline(1, 'six') 3113 LET g:TsrFunc1Args = [] 3114 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3115 call assert_equal([[17, 1, ''], [17, 0, 'six']], g:TsrFunc1Args) 3116 bw! 3117 3118 #" Set 'thesaurusfunc' to a string(lambda expression) 3119 LET &thesaurusfunc = 'LSTART a, b LMIDDLE TsrFunc1(18, a, b) LEND' 3120 new 3121 call setline(1, 'six') 3122 LET g:TsrFunc1Args = [] 3123 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3124 call assert_equal([[18, 1, ''], [18, 0, 'six']], g:TsrFunc1Args) 3125 bw! 3126 3127 #" Set 'thesaurusfunc' to a variable with a lambda expression 3128 VAR Lambda = LSTART a, b LMIDDLE TsrFunc1(19, a, b) LEND 3129 LET &thesaurusfunc = Lambda 3130 new 3131 call setline(1, 'seven') 3132 LET g:TsrFunc1Args = [] 3133 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3134 call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:TsrFunc1Args) 3135 bw! 3136 3137 #" Set 'thesaurusfunc' to a string(variable with a lambda expression) 3138 LET Lambda = LSTART a, b LMIDDLE TsrFunc1(20, a, b) LEND 3139 LET &thesaurusfunc = string(Lambda) 3140 new 3141 call setline(1, 'seven') 3142 LET g:TsrFunc1Args = [] 3143 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3144 call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:TsrFunc1Args) 3145 bw! 3146 3147 #" Test for using a lambda function with incorrect return value 3148 LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND 3149 LET &thesaurusfunc = Lambda 3150 new 3151 call setline(1, 'eight') 3152 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3153 bw! 3154 3155 #" Test for clearing the 'thesaurusfunc' option 3156 set thesaurusfunc='' 3157 set thesaurusfunc& 3158 call assert_fails("set thesaurusfunc=function('abc')", "E700:") 3159 call assert_fails("set thesaurusfunc=funcref('abc')", "E700:") 3160 3161 #" set 'thesaurusfunc' to a non-existing function 3162 set thesaurusfunc=TsrFunc2 3163 call setline(1, 'ten') 3164 call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:') 3165 call assert_fails("LET &thesaurusfunc = function('NonExistingFunc')", 'E700:') 3166 LET g:TsrFunc2Args = [] 3167 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3168 call assert_equal([[1, ''], [0, 'ten']], g:TsrFunc2Args) 3169 bw! 3170 3171 #" Use a buffer-local value and a global value 3172 set thesaurusfunc& 3173 setlocal thesaurusfunc=function('g:TsrFunc1',\ [22]) 3174 call setline(1, 'sun') 3175 LET g:TsrFunc1Args = [] 3176 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x") 3177 call assert_equal('sun', getline(1)) 3178 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:TsrFunc1Args) 3179 new 3180 call setline(1, 'sun') 3181 LET g:TsrFunc1Args = [] 3182 " Nvim: message is an actual error rather than message with error highlight 3183 silent! call feedkeys("A\<C-X>\<C-T>\<Esc>", "x") 3184 call assert_equal('sun', getline(1)) 3185 call assert_equal([], g:TsrFunc1Args) 3186 set thesaurusfunc=function('g:TsrFunc1',\ [23]) 3187 wincmd w 3188 call setline(1, 'sun') 3189 LET g:TsrFunc1Args = [] 3190 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x") 3191 call assert_equal('sun', getline(1)) 3192 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:TsrFunc1Args) 3193 :%bw! 3194 END 3195 call CheckLegacyAndVim9Success(lines) 3196 3197 " Test for using a script-local function name 3198 func s:TsrFunc3(findstart, base) 3199 call add(g:TsrFunc3Args, [a:findstart, a:base]) 3200 return a:findstart ? 0 : [] 3201 endfunc 3202 3203 set tsrfu=s:TsrFunc3 3204 new 3205 call setline(1, 'script1') 3206 let g:TsrFunc3Args = [] 3207 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3208 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) 3209 bw! 3210 3211 let &tsrfu = 's:TsrFunc3' 3212 new 3213 call setline(1, 'script2') 3214 let g:TsrFunc3Args = [] 3215 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3216 call assert_equal([[1, ''], [0, 'script2']], g:TsrFunc3Args) 3217 bw! 3218 3219 new | only 3220 set thesaurusfunc= 3221 setlocal thesaurusfunc=NoSuchFunc 3222 setglobal thesaurusfunc=s:TsrFunc3 3223 call assert_equal('NoSuchFunc', &thesaurusfunc) 3224 call assert_equal('NoSuchFunc', &l:thesaurusfunc) 3225 call assert_equal('s:TsrFunc3', &g:thesaurusfunc) 3226 new | only 3227 call assert_equal('s:TsrFunc3', &thesaurusfunc) 3228 call assert_equal('s:TsrFunc3', &g:thesaurusfunc) 3229 call assert_equal('', &l:thesaurusfunc) 3230 call setline(1, 'script1') 3231 let g:TsrFunc3Args = [] 3232 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3233 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) 3234 bw! 3235 3236 new | only 3237 set thesaurusfunc= 3238 setlocal thesaurusfunc=NoSuchFunc 3239 set thesaurusfunc=s:TsrFunc3 3240 call assert_equal('s:TsrFunc3', &thesaurusfunc) 3241 call assert_equal('s:TsrFunc3', &g:thesaurusfunc) 3242 call assert_equal('', &l:thesaurusfunc) 3243 call setline(1, 'script1') 3244 let g:TsrFunc3Args = [] 3245 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3246 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) 3247 setlocal bufhidden=wipe 3248 new | only! 3249 call assert_equal('s:TsrFunc3', &thesaurusfunc) 3250 call assert_equal('s:TsrFunc3', &g:thesaurusfunc) 3251 call assert_equal('', &l:thesaurusfunc) 3252 call setline(1, 'script1') 3253 let g:TsrFunc3Args = [] 3254 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3255 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args) 3256 bw! 3257 3258 delfunc s:TsrFunc3 3259 3260 " invalid return value 3261 let &thesaurusfunc = {a -> 'abc'} 3262 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3263 3264 " Using Vim9 lambda expression in legacy context should fail 3265 set thesaurusfunc=(a,\ b)\ =>\ TsrFunc1(21,\ a,\ b) 3266 new | only 3267 let g:TsrFunc1Args = [] 3268 call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:') 3269 call assert_equal([], g:TsrFunc1Args) 3270 bw! 3271 3272 " set 'thesaurusfunc' to a partial with dict. This used to cause a crash. 3273 func SetTsrFunc() 3274 let params = {'thesaurus': function('g:DictTsrFunc')} 3275 let &thesaurusfunc = params.thesaurus 3276 endfunc 3277 func g:DictTsrFunc(_) dict 3278 endfunc 3279 call SetTsrFunc() 3280 new 3281 call SetTsrFunc() 3282 bw 3283 call test_garbagecollect_now() 3284 new 3285 set thesaurusfunc= 3286 wincmd w 3287 %bw! 3288 delfunc SetTsrFunc 3289 3290 " set buffer-local 'thesaurusfunc' to a partial with dict. This used to 3291 " cause a crash. 3292 func SetLocalTsrFunc() 3293 let params = {'thesaurus': function('g:DictTsrFunc')} 3294 let &l:thesaurusfunc = params.thesaurus 3295 endfunc 3296 call SetLocalTsrFunc() 3297 call test_garbagecollect_now() 3298 call SetLocalTsrFunc() 3299 set thesaurusfunc= 3300 bw! 3301 delfunc g:DictTsrFunc 3302 delfunc SetLocalTsrFunc 3303 3304 " Vim9 tests 3305 let lines =<< trim END 3306 vim9script 3307 3308 def Vim9tsrFunc(callnr: number, findstart: number, base: string): any 3309 add(g:Vim9tsrFunc_Args, [callnr, findstart, base]) 3310 return findstart ? 0 : [] 3311 enddef 3312 3313 # Test for using a def function with thesaurusfunc 3314 set thesaurusfunc=function('Vim9tsrFunc',\ [60]) 3315 new | only 3316 setline(1, 'one') 3317 g:Vim9tsrFunc_Args = [] 3318 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3319 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9tsrFunc_Args) 3320 bw! 3321 3322 # Test for using a global function name 3323 &thesaurusfunc = g:TsrFunc2 3324 new | only 3325 setline(1, 'two') 3326 g:TsrFunc2Args = [] 3327 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3328 assert_equal([[1, ''], [0, 'two']], g:TsrFunc2Args) 3329 bw! 3330 3331 # Test for using a script-local function name 3332 def LocalTsrFunc(findstart: number, base: string): any 3333 add(g:LocalTsrFuncArgs, [findstart, base]) 3334 return findstart ? 0 : [] 3335 enddef 3336 &thesaurusfunc = LocalTsrFunc 3337 new | only 3338 setline(1, 'three') 3339 g:LocalTsrFuncArgs = [] 3340 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x') 3341 assert_equal([[1, ''], [0, 'three']], g:LocalTsrFuncArgs) 3342 bw! 3343 END 3344 call CheckScriptSuccess(lines) 3345 3346 " cleanup 3347 set thesaurusfunc& 3348 delfunc TsrFunc1 3349 delfunc TsrFunc2 3350 unlet g:TsrFunc1Args g:TsrFunc2Args 3351 %bw! 3352 endfunc 3353 3354 func FooBarComplete(findstart, base) 3355 if a:findstart 3356 return col('.') - 1 3357 else 3358 return ["Foo", "Bar", "}"] 3359 endif 3360 endfunc 3361 3362 func Test_complete_smartindent() 3363 new 3364 setlocal smartindent completefunc=FooBarComplete 3365 exe "norm! o{\<cr>\<c-x>\<c-u>\<c-p>}\<cr>\<esc>" 3366 let result = getline(1,'$') 3367 call assert_equal(['', '{','}',''], result) 3368 %d 3369 setlocal complete=FFooBarComplete 3370 exe "norm! o{\<cr>\<c-n>\<c-p>}\<cr>\<esc>" 3371 let result = getline(1,'$') 3372 call assert_equal(['', '{','}',''], result) 3373 %d 3374 setlocal complete=F 3375 exe "norm! o{\<cr>\<c-n>\<c-p>}\<cr>\<esc>" 3376 let result = getline(1,'$') 3377 call assert_equal(['', '{','}',''], result) 3378 bw! 3379 delfunction! FooBarComplete 3380 endfunc 3381 3382 func Test_complete_overrun() 3383 " this was going past the end of the copied text 3384 new 3385 sil norm si0s0 3386 bwipe! 3387 endfunc 3388 3389 func Test_infercase_very_long_line() 3390 " this was truncating the line when inferring case 3391 new 3392 let longLine = "blah "->repeat(300) 3393 let verylongLine = "blah "->repeat(400) 3394 call setline(1, verylongLine) 3395 call setline(2, longLine) 3396 set ic infercase 3397 exe "normal 2Go\<C-X>\<C-L>\<Esc>" 3398 call assert_equal(longLine, getline(3)) 3399 3400 " check that the too long text is NUL terminated 3401 %del 3402 norm o 3403 norm 1987ax 3404 exec "norm ox\<C-X>\<C-L>" 3405 call assert_equal(repeat('x', 1987), getline(3)) 3406 3407 bwipe! 3408 set noic noinfercase 3409 endfunc 3410 3411 func Test_ins_complete_add() 3412 " this was reading past the end of allocated memory 3413 new 3414 norm o 3415 norm 7o 3416 sil! norm o 3417 3418 bwipe! 3419 endfunc 3420 3421 func Test_ins_complete_end_of_line() 3422 " this was reading past the end of the line 3423 new 3424 norm 8oý 3425 sil! norm o 3426 3427 bwipe! 3428 endfunc 3429 3430 func s:Tagfunc(t,f,o) 3431 bwipe! 3432 return [] 3433 endfunc 3434 3435 " This was using freed memory, since 'complete' was in a wiped out buffer. 3436 " Also using a window that was closed. 3437 func Test_tagfunc_wipes_out_buffer() 3438 new 3439 set complete=.,t,w,b,u,i 3440 se tagfunc=s:Tagfunc 3441 sil norm i 3442 3443 bwipe! 3444 endfunc 3445 3446 func s:TagfuncComplete(t,f,o) 3447 call complete(1, ['ddd', 'eee', 'fff']) 3448 return [] 3449 endfunc 3450 3451 " 'tagfunc' calling complete() should not cause hang or E684. 3452 func Test_tagfunc_calls_complete() 3453 new 3454 call setline(1, ['aaa', 'bbb', 'ccc']) 3455 setlocal tagfunc=s:TagfuncComplete 3456 setlocal completeopt=menu,noselect 3457 3458 let v:errmsg = '' 3459 3460 " This used to hang. 3461 setlocal complete=.,t 3462 call feedkeys("Go\<C-N>\<C-E>\<Esc>", 'tx') 3463 call assert_equal('', getline('.')) 3464 call assert_equal('', v:errmsg) 3465 3466 " This used to cause E684. 3467 setlocal complete=t,. 3468 call feedkeys("cc\<C-N>\<C-E>\<Esc>", 'tx') 3469 call assert_equal('', getline('.')) 3470 call assert_equal('', v:errmsg) 3471 3472 bwipe! 3473 endfunc 3474 3475 func Test_ins_complete_popup_position() 3476 CheckScreendump 3477 3478 let lines =<< trim END 3479 vim9script 3480 set nowrap 3481 setline(1, ['one', 'two', 'this is line ', 'four']) 3482 prop_type_add('test', {highlight: 'Error'}) 3483 prop_add(3, 0, { 3484 text_align: 'above', 3485 text: 'The quick brown fox jumps over the lazy dog', 3486 type: 'test' 3487 }) 3488 END 3489 call writefile(lines, 'XinsPopup', 'D') 3490 let buf = RunVimInTerminal('-S XinsPopup', #{rows: 10}) 3491 3492 call term_sendkeys(buf, "3GA\<C-N>") 3493 call VerifyScreenDump(buf, 'Test_ins_complete_popup_position_1', {}) 3494 3495 call StopVimInTerminal(buf) 3496 endfunc 3497 3498 func GetCompleteInfo() 3499 let g:compl_info = complete_info() 3500 return '' 3501 endfunc 3502 3503 func Test_completion_restart() 3504 new 3505 set complete=. completeopt=menuone backspace=2 3506 call setline(1, 'workhorse workhorse') 3507 exe "normal $a\<C-N>\<BS>\<BS>\<C-R>=GetCompleteInfo()\<CR>" 3508 call assert_equal(1, len(g:compl_info['items'])) 3509 call assert_equal('workhorse', g:compl_info['items'][0]['word']) 3510 set complete& completeopt& backspace& 3511 bwipe! 3512 endfunc 3513 3514 func Test_complete_info_index() 3515 new 3516 call setline(1, ["aaa", "bbb", "ccc", "ddd", "eee", "fff"]) 3517 inoremap <buffer><F5> <C-R>=GetCompleteInfo()<CR> 3518 3519 " Ensure 'index' in complete_info() is coherent with the 'items' array. 3520 3521 set completeopt=menu,preview 3522 " Search forward 3523 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx') 3524 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word']) 3525 call assert_equal(6 , len(g:compl_info['items'])) 3526 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3527 call assert_equal("bbb", g:compl_info['items'][g:compl_info['selected']]['word']) 3528 call assert_equal(6 , len(g:compl_info['items'])) 3529 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3530 call assert_equal("ccc", g:compl_info['items'][g:compl_info['selected']]['word']) 3531 call assert_equal(6 , len(g:compl_info['items'])) 3532 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3533 call assert_equal("ddd", g:compl_info['items'][g:compl_info['selected']]['word']) 3534 call assert_equal(6 , len(g:compl_info['items'])) 3535 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3536 call assert_equal("eee", g:compl_info['items'][g:compl_info['selected']]['word']) 3537 call assert_equal(6 , len(g:compl_info['items'])) 3538 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3539 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) 3540 call assert_equal(6 , len(g:compl_info['items'])) 3541 " Search forward: unselected item 3542 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3543 call assert_equal(6 , len(g:compl_info['items'])) 3544 call assert_equal(-1 , g:compl_info['selected']) 3545 3546 " Search backward 3547 call feedkeys("Go\<C-X>\<C-P>\<F5>\<Esc>_dd", 'tx') 3548 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) 3549 call assert_equal(6 , len(g:compl_info['items'])) 3550 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3551 call assert_equal("eee", g:compl_info['items'][g:compl_info['selected']]['word']) 3552 call assert_equal(6 , len(g:compl_info['items'])) 3553 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3554 call assert_equal("ddd", g:compl_info['items'][g:compl_info['selected']]['word']) 3555 call assert_equal(6 , len(g:compl_info['items'])) 3556 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3557 call assert_equal("ccc", g:compl_info['items'][g:compl_info['selected']]['word']) 3558 call assert_equal(6 , len(g:compl_info['items'])) 3559 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3560 call assert_equal("bbb", g:compl_info['items'][g:compl_info['selected']]['word']) 3561 call assert_equal(6 , len(g:compl_info['items'])) 3562 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3563 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word']) 3564 call assert_equal(6 , len(g:compl_info['items'])) 3565 " search backwards: unselected item 3566 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3567 call assert_equal(6 , len(g:compl_info['items'])) 3568 call assert_equal(-1 , g:compl_info['selected']) 3569 3570 " switch direction: forwards, then backwards 3571 call feedkeys("Go\<C-X>\<C-N>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3572 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) 3573 call assert_equal(6 , len(g:compl_info['items'])) 3574 " switch direction: forwards, then backwards, then forwards again 3575 call feedkeys("Go\<C-X>\<C-N>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx') 3576 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-P>\<C-P>\<C-N>\<F5>\<Esc>_dd", 'tx') 3577 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word']) 3578 call assert_equal(6 , len(g:compl_info['items'])) 3579 3580 " switch direction: backwards, then forwards 3581 call feedkeys("Go\<C-X>\<C-P>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3582 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word']) 3583 call assert_equal(6 , len(g:compl_info['items'])) 3584 " switch direction: backwards, then forwards, then backwards again 3585 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-N>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx') 3586 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) 3587 call assert_equal(6 , len(g:compl_info['items'])) 3588 3589 " Add 'noselect', check that 'selected' is -1 when nothing is selected. 3590 set completeopt+=noselect 3591 " Search forward. 3592 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx') 3593 call assert_equal(-1, g:compl_info['selected']) 3594 3595 " Search backward. 3596 call feedkeys("Go\<C-X>\<C-P>\<F5>\<Esc>_dd", 'tx') 3597 call assert_equal(-1, g:compl_info['selected']) 3598 3599 call feedkeys("Go\<C-X>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx') 3600 call assert_equal(5, g:compl_info['selected']) 3601 call assert_equal(6 , len(g:compl_info['items'])) 3602 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word']) 3603 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx') 3604 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word']) 3605 call assert_equal(6 , len(g:compl_info['items'])) 3606 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx') 3607 call assert_equal(-1, g:compl_info['selected']) 3608 call assert_equal(6 , len(g:compl_info['items'])) 3609 3610 set completeopt& 3611 bwipe! 3612 endfunc 3613 3614 func Test_complete_changed_complete_info() 3615 CheckRunVimInTerminal 3616 " this used to crash vim, see #13929 3617 let lines =<< trim END 3618 set completeopt=menuone 3619 autocmd CompleteChanged * call complete_info(['items']) 3620 call feedkeys("iii\<cr>\<c-p>") 3621 END 3622 call writefile(lines, 'Xsegfault', 'D') 3623 let buf = RunVimInTerminal('-S Xsegfault', #{rows: 5}) 3624 call WaitForAssert({-> assert_match('^ii', term_getline(buf, 1))}, 1000) 3625 call StopVimInTerminal(buf) 3626 endfunc 3627 3628 func Test_completefunc_first_call_complete_add() 3629 new 3630 3631 func Complete(findstart, base) abort 3632 if a:findstart 3633 let col = col('.') 3634 call complete_add('#') 3635 return col - 1 3636 else 3637 return [] 3638 endif 3639 endfunc 3640 3641 set completeopt=longest completefunc=Complete 3642 " This used to cause heap-buffer-overflow 3643 call assert_fails('call feedkeys("ifoo#\<C-X>\<C-U>", "xt")', 'E840:') 3644 3645 delfunc Complete 3646 set completeopt& completefunc& 3647 bwipe! 3648 endfunc 3649 3650 func Test_complete_opt_fuzzy() 3651 func OnPumChange() 3652 let g:item = get(v:event, 'completed_item', {}) 3653 let g:word = get(g:item, 'word', v:null) 3654 let g:abbr = get(g:item, 'abbr', v:null) 3655 let g:selected = get(complete_info(['selected']), 'selected') 3656 endfunction 3657 3658 augroup AAAAA_Group 3659 au! 3660 autocmd CompleteChanged * :call OnPumChange() 3661 augroup END 3662 3663 let g:change = 0 3664 func Omni_test(findstart, base) 3665 if a:findstart 3666 return col(".") 3667 endif 3668 if g:change == 0 3669 return [#{word: "foo"}, #{word: "foobar"}, #{word: "fooBaz"}, #{word: "foobala"}, #{word: "你好吗"}, #{word: "我好"}] 3670 elseif g:change == 1 3671 return [#{word: "cp_match_array"}, #{word: "cp_str"}, #{word: "cp_score"}] 3672 else 3673 return [#{word: "for i = .."}, #{word: "bar"}, #{word: "foo"}, #{word: "for .. ipairs"}, #{word: "for .. pairs"}] 3674 endif 3675 endfunc 3676 3677 new 3678 set omnifunc=Omni_test 3679 set completeopt+=noinsert,fuzzy 3680 call feedkeys("Gi\<C-x>\<C-o>", 'tx') 3681 call assert_equal('foo', g:word) 3682 call feedkeys("S\<C-x>\<C-o>fb", 'tx') 3683 call assert_equal('fooBaz', g:word) 3684 call feedkeys("S\<C-x>\<C-o>fa", 'tx') 3685 call assert_equal('foobar', g:word) 3686 " select next 3687 call feedkeys("S\<C-x>\<C-o>fb\<C-n>", 'tx') 3688 call assert_equal('foobar', g:word) 3689 " can cyclically select next 3690 call feedkeys("S\<C-x>\<C-o>fb\<C-n>\<C-n>\<C-n>", 'tx') 3691 call assert_equal(v:null, g:word) 3692 " select prev 3693 call feedkeys("S\<C-x>\<C-o>fb\<C-p>", 'tx') 3694 call assert_equal(v:null, g:word) 3695 " can cyclically select prev 3696 call feedkeys("S\<C-x>\<C-o>fb\<C-p>\<C-p>\<C-p>\<C-p>", 'tx') 3697 call assert_equal('fooBaz', g:word) 3698 3699 func Comp() 3700 call complete(col('.'), ["fooBaz", "foobar", "foobala"]) 3701 return '' 3702 endfunc 3703 call feedkeys("i\<C-R>=Comp()\<CR>", 'tx') 3704 call assert_equal('fooBaz', g:word) 3705 3706 " respect noselect 3707 set completeopt+=noselect 3708 call feedkeys("S\<C-x>\<C-o>fb", 'tx') 3709 call assert_equal(v:null, g:word) 3710 call feedkeys("S\<C-x>\<C-o>fb\<C-n>", 'tx') 3711 call assert_equal('fooBaz', g:word) 3712 3713 " test case for nosort option 3714 set cot=menuone,menu,noinsert,fuzzy,nosort 3715 " "fooBaz" should have a higher score when the leader is "fb". 3716 " With "nosort", "foobar" should still be shown first in the popup menu. 3717 call feedkeys("S\<C-x>\<C-o>fb", 'tx') 3718 call assert_equal('foobar', g:word) 3719 call feedkeys("S\<C-x>\<C-o>好", 'tx') 3720 call assert_equal("你好吗", g:word) 3721 3722 set cot+=noselect 3723 call feedkeys("S\<C-x>\<C-o>好", 'tx') 3724 call assert_equal(v:null, g:word) 3725 call feedkeys("S\<C-x>\<C-o>好\<C-N>", 'tx') 3726 call assert_equal('你好吗', g:word) 3727 3728 " "nosort" shouldn't enable fuzzy filtering when "fuzzy" isn't present. 3729 set cot=menuone,noinsert,nosort 3730 call feedkeys("S\<C-x>\<C-o>fooB\<C-Y>", 'tx') 3731 call assert_equal('fooBaz', getline('.')) 3732 3733 set cot=menuone,fuzzy,nosort 3734 func CompAnother() 3735 call complete(col('.'), [#{word: "do" }, #{word: "echo"}, #{word: "for (${1:expr1}, ${2:expr2}, ${3:expr3}) {\n\t$0\n}", abbr: "for" }, #{word: "foo"}]) 3736 return '' 3737 endfunc 3738 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>", 'tx') 3739 call assert_equal("for", g:abbr) 3740 call assert_equal(2, g:selected) 3741 3742 set cot+=noinsert 3743 call feedkeys("i\<C-R>=CompAnother()\<CR>f", 'tx') 3744 call assert_equal("for", g:abbr) 3745 call assert_equal(2, g:selected) 3746 3747 set cot=menu,menuone,noselect,fuzzy 3748 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>\<C-N>\<C-N>", 'tx') 3749 call assert_equal("foo", g:word) 3750 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>", 'tx') 3751 call assert_equal("foo", g:word) 3752 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>\<C-P>", 'tx') 3753 call assert_equal("for", g:abbr) 3754 3755 %d 3756 set cot=menu,fuzzy 3757 call feedkeys("Sblue\<CR>bar\<CR>b\<C-X>\<C-P>\<C-Y>\<ESC>", 'tx') 3758 call assert_equal('blue', getline('.')) 3759 call feedkeys("Sb\<C-X>\<C-N>\<C-Y>\<ESC>", 'tx') 3760 call assert_equal('bar', getline('.')) 3761 call feedkeys("Sb\<C-X>\<C-P>\<C-N>\<C-Y>\<ESC>", 'tx') 3762 call assert_equal('b', getline('.')) 3763 3764 " chain completion 3765 call feedkeys("Slore spum\<CR>lor\<C-X>\<C-P>\<C-X>\<C-P>\<ESC>", 'tx') 3766 call assert_equal('lore spum', getline('.')) 3767 3768 " issue #15412 3769 call feedkeys("Salpha bravio charlie\<CR>alpha\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<ESC>", 'tx') 3770 call assert_equal('alpha bravio charlie', getline('.')) 3771 3772 set cot=fuzzy,menu,noinsert 3773 call feedkeys(":let g:change=2\<CR>") 3774 call feedkeys("S\<C-X>\<C-O>for\<C-N>\<C-N>\<C-N>", 'tx') 3775 call assert_equal('for', getline('.')) 3776 call feedkeys("S\<C-X>\<C-O>for\<C-P>", 'tx') 3777 call assert_equal('for', getline('.')) 3778 call feedkeys("S\<C-X>\<C-O>for\<C-P>\<C-P>", 'tx') 3779 call assert_equal('for .. ipairs', getline('.')) 3780 3781 call feedkeys(":let g:change=1\<CR>") 3782 call feedkeys("S\<C-X>\<C-O>c\<C-Y>", 'tx') 3783 call assert_equal('cp_str', getline('.')) 3784 3785 " Issue 18488: sort after collection when "fuzzy" (unless "nosort") 3786 %d 3787 set completeopt& 3788 set completeopt+=fuzzy,noselect 3789 func! PrintMenuWords() 3790 let info = complete_info(["items"]) 3791 call map(info.items, {_, v -> v.word}) 3792 return info 3793 endfunc 3794 call setline(1, ['func1', 'xfunc', 'func2']) 3795 call feedkeys("Gof\<C-N>\<C-R>=PrintMenuWords()\<CR>\<Esc>0", 'tx') 3796 call assert_equal('f{''items'': [''func1'', ''func2'', ''xfunc'']}', getline('.')) 3797 3798 " Issue #18802: Reset selected item after fuzzy sort 3799 %d 3800 call setline(1, ['aa', 'aaa', 'aaaa']) 3801 set completeopt=menuone,noinsert,fuzzy 3802 call feedkeys("Goa\<C-N>\<C-Y>\<Esc>", 'tx') 3803 call assert_equal('aa', getline('.')) 3804 call feedkeys("Goa\<C-P>\<C-Y>\<Esc>", 'tx') 3805 call assert_equal('aaaa', getline('.')) 3806 3807 " clean up 3808 set omnifunc= 3809 bw! 3810 set complete& completeopt& 3811 autocmd! AAAAA_Group 3812 augroup! AAAAA_Group 3813 delfunc OnPumChange 3814 delfunc Omni_test 3815 delfunc Comp 3816 delfunc PrintMenuWords 3817 unlet g:item 3818 unlet g:word 3819 unlet g:abbr 3820 endfunc 3821 3822 func Test_complete_fuzzy_collect() 3823 new 3824 redraw " need this to prevent NULL dereference in Nvim 3825 set completeopt+=fuzzy 3826 call setline(1, ['hello help hero h']) 3827 " Use "!" flag of feedkeys() so that ex_normal_busy is not set and 3828 " ins_compl_check_keys() is not skipped. 3829 " Add a "0" after the <Esc> to avoid waiting for an escape sequence. 3830 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') 3831 call assert_equal('hello help hero hello', getline('.')) 3832 set completeopt+=noinsert 3833 call setline(1, ['hello help hero h']) 3834 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') 3835 call assert_equal('hello help hero h', getline('.')) 3836 3837 set completeopt-=noinsert 3838 call setline(1, ['xyz yxz x']) 3839 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') 3840 call assert_equal('xyz yxz xyz', getline('.')) 3841 " can fuzzy get yxz when use Ctrl-N twice 3842 call setline(1, ['xyz yxz x']) 3843 call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!') 3844 call assert_equal('xyz yxz yxz', getline('.')) 3845 3846 call setline(1, ['你好 你']) 3847 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') 3848 call assert_equal('你好 你好', getline('.')) 3849 call setline(1, ['你的 我的 的']) 3850 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!') 3851 call assert_equal('你的 我的 你的', getline('.')) 3852 " can fuzzy get multiple-byte word when use Ctrl-N twice 3853 call setline(1, ['你的 我的 的']) 3854 call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!') 3855 call assert_equal('你的 我的 我的', getline('.')) 3856 3857 " check that "adding" expansion works 3858 call setline(1, ['hello world foo bar']) 3859 call feedkeys("Ohlo\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<Esc>0", 'tx!') 3860 call assert_equal('hello world foo bar', getline('.')) 3861 call feedkeys("Swld\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<Esc>0", 'tx!') 3862 call assert_equal('world foo bar', getline('.')) 3863 %delete 3864 3865 " fuzzy on file 3866 call writefile([''], 'fobar', 'D') 3867 call writefile([''], 'foobar', 'D') 3868 call setline(1, ['fob']) 3869 call cursor(1, 1) 3870 call feedkeys("A\<C-X>\<C-f>\<Esc>0", 'tx!') 3871 call assert_equal('fobar', getline('.')) 3872 call feedkeys("Sfob\<C-X>\<C-f>\<C-N>\<Esc>0", 'tx!') 3873 call assert_equal('foobar', getline('.')) 3874 call feedkeys("S../\<C-X>\<C-f>\<Esc>0", 'tx!') 3875 call assert_match('../*', getline('.')) 3876 call feedkeys("S../td\<C-X>\<C-f>\<Esc>0", 'tx!') 3877 call assert_match('../testdir', getline('.')) 3878 3879 " can get completion from other buffer 3880 vnew 3881 call setline(1, ["completeness,", "compatibility", "Composite", "Omnipotent"]) 3882 wincmd p 3883 call feedkeys("Somp\<C-N>\<Esc>0", 'tx!') 3884 call assert_equal('completeness', getline('.')) 3885 call feedkeys("Somp\<C-N>\<C-N>\<Esc>0", 'tx!') 3886 call assert_equal('compatibility', getline('.')) 3887 call feedkeys("Somp\<C-P>\<Esc>0", 'tx!') 3888 call assert_equal('Omnipotent', getline('.')) 3889 call feedkeys("Somp\<C-P>\<C-P>\<Esc>0", 'tx!') 3890 call assert_equal('Composite', getline('.')) 3891 call feedkeys("S omp\<C-N>\<Esc>0", 'tx!') 3892 call assert_equal(' completeness', getline('.')) 3893 3894 " fuzzy on whole line completion 3895 call setline(1, ["world is on fire", "no one can save me but you", 'user can execute', '']) 3896 call cursor(4, 1) 3897 call feedkeys("Swio\<C-X>\<C-L>\<Esc>0", 'tx!') 3898 call assert_equal('world is on fire', getline('.')) 3899 call feedkeys("Su\<C-X>\<C-L>\<C-P>\<Esc>0", 'tx!') 3900 call assert_equal('no one can save me but you', getline('.')) 3901 3902 " issue #15526 3903 set completeopt=menuone,menu,noselect,fuzzy 3904 call setline(1, ['Text', 'ToText', '']) 3905 call cursor(3, 1) 3906 call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!') 3907 call assert_equal('Tex', getline(line('.') - 1)) 3908 3909 call setline(1, ['fuzzy', 'fuzzycollect', 'completefuzzycollect']) 3910 call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!') 3911 call assert_equal('fuzzycollect', getline(line('.') - 1)) 3912 call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!') 3913 call assert_equal('completefuzzycollect', getline(line('.') - 1)) 3914 3915 " keywords in 'dictonary' 3916 call writefile(['hello', 'think'], 'Xtest_dict.txt', 'D') 3917 set dict=Xtest_dict.txt 3918 call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<CR>\<Esc>0", 'tx!') 3919 call assert_equal('hello', getline(line('.') - 1)) 3920 call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!') 3921 call assert_equal('think', getline(line('.') - 1)) 3922 3923 call setline(1, ['foo bar fuzzy', 'completefuzzycollect']) 3924 call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<C-Y>\<Esc>0", 'tx!') 3925 call assert_equal('completefuzzycollect', getline('.')) 3926 3927 %d _ 3928 call setline(1, ['fuzzy', 'fuzzy foo', "fuzzy bar", 'fuzzycollect']) 3929 call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<C-Y>\<Esc>0", 'tx!') 3930 call assert_equal('fuzzycollect', getline('.')) 3931 3932 " when 'fuzzy' is not set, and 'infercase' and 'ignorecase' are set, then 3933 " uppercase completes from lowercase words in dictonary 3934 set completeopt& 3935 set infercase ignorecase 3936 call writefile(['hello'], 'Xtest_case.txt', 'D') 3937 set dictionary=Xtest_case.txt 3938 call feedkeys("ggdGSH\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx') 3939 call assert_equal('Hello', getline('.')) 3940 call feedkeys("ggdGSHE\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx') 3941 call assert_equal('HELLO', getline('.')) 3942 3943 bw! 3944 bw! 3945 set dict& 3946 set completeopt& cpt& ignorecase& infercase& 3947 endfunc 3948 3949 " Issue #19434 3950 " Fuzzy whole-line completion should not loop infinitely when the cursor is in 3951 " the middle of the line (non-zero column). 3952 func Test_complete_fuzzy_wholeline_no_hang() 3953 new 3954 set completeopt=preview,fuzzy,noinsert,menuone 3955 call setline(1, [ 3956 \ '<!DOCTYPE html>', 3957 \ '<html lang="en-US">', 3958 \ ' <head>', 3959 \ ' </head>', 3960 \ ' <body>', 3961 \ ' <div class="page-landscape">', 3962 \ ' </div>', 3963 \ ' </body>', 3964 \ '</html>', 3965 \ ]) 3966 call cursor(6, 1) 3967 call feedkeys("faC\<C-X>\<C-L>\<Esc>0", 'tx!') 3968 call assert_equal(' <div cl', getline(6)) 3969 3970 bw! 3971 set completeopt& 3972 endfunc 3973 3974 " Issue #18752 3975 func Test_complete_fuzzy_collect_multiwin() 3976 new 3977 set completeopt=fuzzy 3978 3979 vnew 3980 call setline(1, ["completeness,", "compatibility", "Composite", "Omnipotent"]) 3981 wincmd p 3982 call feedkeys("Somp\<C-P>\<Esc>0", 'tx!') 3983 call assert_equal('Omnipotent', getline('.')) 3984 3985 bw! 3986 set completeopt& 3987 endfunc 3988 3989 func Test_cfc_with_longest() 3990 new 3991 set completeopt=menu,menuone,longest,fuzzy 3992 3993 " keyword 3994 exe "normal ggdGShello helio think h\<C-X>\<C-N>\<ESC>" 3995 call assert_equal("hello helio think hel", getline('.')) 3996 exe "normal hello helio think h\<C-X>\<C-P>\<ESC>" 3997 call assert_equal("hello helio think hel", getline('.')) 3998 3999 " skip non-consecutive prefixes 4000 exe "normal ggdGShello helio heo\<C-X>\<C-N>\<ESC>" 4001 call assert_equal("hello helio heo", getline('.')) 4002 4003 " dict 4004 call writefile(['help'], 'test_keyword.txt', 'D') 4005 set complete=ktest_keyword.txt 4006 exe "normal ggdGSh\<C-N>\<ESC>" 4007 " auto insert help when only have one match 4008 call assert_equal("help", getline('.')) 4009 call writefile(['hello', 'help', 'think'], 'xtest_keyword.txt', 'D') 4010 set complete=kxtest_keyword.txt 4011 " auto insert hel 4012 exe "normal ggdGSh\<C-N>\<ESC>" 4013 call assert_equal("hel", getline('.')) 4014 4015 " line start with a space 4016 call writefile([' hello'], 'test_case1.txt', 'D') 4017 set complete=ktest_case1.txt 4018 exe "normal ggdGSh\<C-N>\<ESC>" 4019 call assert_equal("hello", getline('.')) 4020 4021 " multiple matches 4022 set complete=ktest_case2.txt 4023 call writefile([' hello help what'], 'test_case2.txt', 'D') 4024 exe "normal ggdGSh\<C-N>\<C-N>\<C-N>\<C-N>\<ESC>" 4025 call assert_equal("what", getline('.')) 4026 4027 " multiple lines of matches 4028 set complete=ktest_case3.txt 4029 call writefile([' hello help what', 'hola', ' hey'], 'test_case3.txt', 'D') 4030 exe "normal ggdGSh\<C-N>\<C-N>\<ESC>" 4031 call assert_equal("hey", getline('.')) 4032 exe "normal ggdGSh\<C-N>\<C-N>\<C-N>\<C-N>\<ESC>" 4033 call assert_equal("hola", getline('.')) 4034 4035 set complete=ktest_case4.txt 4036 call writefile([' auto int enum register', 'why'], 'test_case4.txt', 'D') 4037 exe "normal ggdGSe\<C-N>\<C-N>\<ESC>" 4038 call assert_equal("enum", getline('.')) 4039 4040 set complete=ktest_case5.txt 4041 call writefile(['hello friends', 'go', 'hero'], 'test_case5.txt', 'D') 4042 exe "normal ggdGSh\<C-N>\<C-N>\<ESC>" 4043 call assert_equal("hero", getline('.')) 4044 set complete& 4045 4046 " file 4047 call writefile([''], 'hello', 'D') 4048 call writefile([''], 'helio', 'D') 4049 exe "normal ggdGS./h\<C-X>\<C-f>\<ESC>" 4050 call assert_equal('./hel', getline('.')) 4051 4052 " word 4053 call setline(1, ['what do you think', 'why i have that', '']) 4054 call cursor(3,1) 4055 call feedkeys("Sw\<C-X>\<C-l>\<C-N>\<Esc>0", 'tx!') 4056 call assert_equal('wh', getline('.')) 4057 4058 exe "normal ggdG" 4059 " auto complete when only one match 4060 exe "normal Shello\<CR>h\<C-X>\<C-N>\<esc>" 4061 call assert_equal('hello', getline('.')) 4062 exe "normal Sh\<C-N>\<C-P>\<esc>" 4063 call assert_equal('hello', getline('.')) 4064 4065 exe "normal Shello\<CR>h\<C-X>\<C-N>\<Esc>cch\<C-X>\<C-N>\<Esc>" 4066 call assert_equal('hello', getline('.')) 4067 4068 " continue search for new leader after insert common prefix 4069 exe "normal ohellokate\<CR>h\<C-X>\<C-N>k\<C-N>\<C-y>\<esc>" 4070 call assert_equal('hellokate', getline('.')) 4071 4072 bw! 4073 set completeopt& 4074 endfunc 4075 4076 func Test_completefuzzycollect_with_completeslash() 4077 CheckMSWindows 4078 4079 call writefile([''], 'fobar', 'D') 4080 let orig_shellslash = &shellslash 4081 set cpt& 4082 new 4083 set completeopt+=fuzzy 4084 set noshellslash 4085 4086 " Test with completeslash unset 4087 set completeslash= 4088 call setline(1, ['.\fob']) 4089 call feedkeys("A\<C-X>\<C-F>\<Esc>0", 'tx!') 4090 call assert_equal('.\fobar', getline('.')) 4091 4092 " Test with completeslash=backslash 4093 set completeslash=backslash 4094 call feedkeys("S.\\fob\<C-X>\<C-F>\<Esc>0", 'tx!') 4095 call assert_equal('.\fobar', getline('.')) 4096 4097 " Test with completeslash=slash 4098 set completeslash=slash 4099 call feedkeys("S.\\fob\<C-X>\<C-F>\<Esc>0", 'tx!') 4100 call assert_equal('./fobar', getline('.')) 4101 4102 " Reset and clean up 4103 let &shellslash = orig_shellslash 4104 set completeslash= 4105 %bw! 4106 endfunc 4107 4108 " Check that tie breaking is stable for completeopt+=fuzzy (which should 4109 " behave the same on different platforms). 4110 func Test_complete_fuzzy_match_tie() 4111 new 4112 set completeopt+=fuzzy,noselect 4113 call setline(1, ['aaabbccc', 'aaabbCCC', 'aaabbcccc', 'aaabbCCCC', '']) 4114 4115 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-Y>", 'tx') 4116 call assert_equal('aaabbccc', getline('.')) 4117 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-Y>", 'tx') 4118 call assert_equal('aaabbCCC', getline('.')) 4119 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx') 4120 call assert_equal('aaabbcccc', getline('.')) 4121 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx') 4122 call assert_equal('aaabbCCCC', getline('.')) 4123 4124 bwipe! 4125 set completeopt& 4126 endfunc 4127 4128 func Test_complete_backwards_default() 4129 new 4130 call append(1, ['foobar', 'foobaz']) 4131 new 4132 call feedkeys("i\<c-p>", 'tx') 4133 call assert_equal('foobaz', getline('.')) 4134 bw! 4135 bw! 4136 endfunc 4137 4138 func Test_complete_info_matches() 4139 let g:what = ['matches'] 4140 func ShownInfo() 4141 let g:compl_info = complete_info(g:what) 4142 return '' 4143 endfunc 4144 set completeopt+=noinsert 4145 4146 new 4147 call setline(1, ['aaa', 'aab', 'aba', 'abb']) 4148 inoremap <buffer><F5> <C-R>=ShownInfo()<CR> 4149 4150 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>dd", 'tx') 4151 call assert_equal([ 4152 \ {'word': 'aaa', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, 4153 \ {'word': 'aab', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, 4154 \ {'word': 'aba', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, 4155 \ {'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, 4156 \], g:compl_info['matches']) 4157 4158 call feedkeys("Goa\<C-X>\<C-N>b\<F5>\<Esc>dd", 'tx') 4159 call assert_equal([ 4160 \ {'word': 'aba', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, 4161 \ {'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, 4162 \], g:compl_info['matches']) 4163 4164 " items and matches both in what 4165 let g:what = ['items', 'matches'] 4166 call feedkeys("Goa\<C-X>\<C-N>b\<F5>\<Esc>dd", 'tx') 4167 call assert_equal([ 4168 \ {'word': 'aaa', 'menu': '', 'user_data': '', 'match': v:false, 'info': '', 'kind': '', 'abbr': ''}, 4169 \ {'word': 'aab', 'menu': '', 'user_data': '', 'match': v:false, 'info': '', 'kind': '', 'abbr': ''}, 4170 \ {'word': 'aba', 'menu': '', 'user_data': '', 'match': v:true, 'info': '', 'kind': '', 'abbr': ''}, 4171 \ {'word': 'abb', 'menu': '', 'user_data': '', 'match': v:true, 'info': '', 'kind': '', 'abbr': ''}, 4172 \], g:compl_info['items']) 4173 call assert_false(has_key(g:compl_info, 'matches')) 4174 4175 bw! 4176 unlet g:what 4177 delfunc ShownInfo 4178 set cot& 4179 endfunc 4180 4181 func Test_complete_info_completed() 4182 func ShownInfo() 4183 let g:compl_info = complete_info(['completed']) 4184 return '' 4185 endfunc 4186 set completeopt+=noinsert 4187 4188 new 4189 call setline(1, ['aaa', 'aab', 'aba', 'abb']) 4190 inoremap <buffer><F5> <C-R>=ShownInfo()<CR> 4191 4192 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>dd", 'tx') 4193 call assert_equal({'word': 'aaa', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, g:compl_info['completed']) 4194 4195 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<F5>\<Esc>dd", 'tx') 4196 call assert_equal({'word': 'aab', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, g:compl_info['completed']) 4197 4198 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>dd", 'tx') 4199 call assert_equal({'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, g:compl_info['completed']) 4200 4201 set completeopt+=noselect 4202 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>dd", 'tx') 4203 call assert_equal({}, g:compl_info) 4204 4205 bw! 4206 delfunc ShownInfo 4207 set cot& 4208 endfunc 4209 4210 func Test_complete_info_selected() 4211 set completeopt=menuone,noselect 4212 new 4213 call setline(1, ["ward", "werd", "wurd", "wxrd"]) 4214 4215 exe "normal! Gow\<c-n>u\<c-n>\<c-r>=complete_info().selected\<cr>" 4216 call assert_equal('wurd2', getline(5)) 4217 4218 exe "normal! Sw\<c-n>u\<c-n>\<c-r>=complete_info(['selected']).selected\<cr>" 4219 call assert_equal('wurd2', getline(5)) 4220 4221 exe "normal! Sw\<c-n>u\<c-n>\<c-r>=complete_info(['items', 'selected']).selected\<cr>" 4222 call assert_equal('wurd2', getline(5)) 4223 4224 exe "normal! Sw\<c-n>u\<c-n>\<c-r>=complete_info(['matches', 'selected']).selected\<cr>" 4225 call assert_equal('wurd0', getline(5)) 4226 4227 bw! 4228 set cot& 4229 endfunc 4230 4231 func Test_completeopt_preinsert() 4232 func Omni_test(findstart, base) 4233 if a:findstart 4234 return col(".") 4235 endif 4236 return [#{word: "fobar"}, #{word: "foobar"}, #{word: "你的"}, #{word: "你好世界"}] 4237 endfunc 4238 set omnifunc=Omni_test 4239 set completeopt=menu,menuone,preinsert 4240 func GetLine() 4241 let g:line = getline('.') 4242 let g:col = col('.') 4243 endfunc 4244 4245 new 4246 inoremap <buffer><F5> <C-R>=GetLine()<CR> 4247 call feedkeys("S\<C-X>\<C-O>f\<F5>\<ESC>", 'tx') 4248 call assert_equal("fobar", g:line) 4249 call assert_equal(2, g:col) 4250 4251 call feedkeys("S\<C-X>\<C-O>foo\<F5>\<ESC>", 'tx') 4252 call assert_equal("foobar", g:line) 4253 4254 call feedkeys("S\<C-X>\<C-O>foo\<BS>\<BS>\<BS>", 'tx') 4255 call assert_equal("", getline('.')) 4256 4257 " delete a character and input new leader 4258 call feedkeys("S\<C-X>\<C-O>foo\<BS>b\<F5>\<ESC>", 'tx') 4259 call assert_equal("fobar", g:line) 4260 call assert_equal(4, g:col) 4261 4262 " delete preinsert when prepare completion 4263 call feedkeys("S\<C-X>\<C-O>f\<Space>", 'tx') 4264 call assert_equal("f ", getline('.')) 4265 4266 call feedkeys("S\<C-X>\<C-O>你\<F5>\<ESC>", 'tx') 4267 call assert_equal("你的", g:line) 4268 call assert_equal(4, g:col) 4269 4270 call feedkeys("S\<C-X>\<C-O>你好\<F5>\<ESC>", 'tx') 4271 call assert_equal("你好世界", g:line) 4272 call assert_equal(7, g:col) 4273 4274 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>f\<F5>\<ESC>", 'tx') 4275 call assert_equal("hello fobar wo", g:line) 4276 call assert_equal(9, g:col) 4277 4278 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>f\<BS>\<F5>\<ESC>", 'tx') 4279 call assert_equal("hello wo", g:line) 4280 call assert_equal(8, g:col) 4281 4282 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>foo\<F5>\<ESC>", 'tx') 4283 call assert_equal("hello foobar wo", g:line) 4284 call assert_equal(11, g:col) 4285 4286 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>foo\<BS>b\<F5>\<ESC>", 'tx') 4287 call assert_equal("hello fobar wo", g:line) 4288 call assert_equal(11, g:col) 4289 4290 " confirm 4291 call feedkeys("S\<C-X>\<C-O>f\<C-Y>", 'tx') 4292 call assert_equal("fobar", getline('.')) 4293 call assert_equal(5, col('.')) 4294 4295 " cancel 4296 call feedkeys("S\<C-X>\<C-O>fo\<C-E>", 'tx') 4297 call assert_equal("fo", getline('.')) 4298 call assert_equal(2, col('.')) 4299 4300 call feedkeys("S hello hero\<CR>h\<C-X>\<C-N>\<F5>\<ESC>", 'tx') 4301 call assert_equal("hello", g:line) 4302 call assert_equal(2, col('.')) 4303 4304 call feedkeys("Sh\<C-X>\<C-N>\<C-Y>", 'tx') 4305 call assert_equal("hello", getline('.')) 4306 call assert_equal(5, col('.')) 4307 4308 " delete preinsert part 4309 call feedkeys("S\<C-X>\<C-O>fo ", 'tx') 4310 call assert_equal("fo ", getline('.')) 4311 call assert_equal(3, col('.')) 4312 4313 call feedkeys("She\<C-X>\<C-N>\<C-U>", 'tx') 4314 call assert_equal("", getline('.')) 4315 call assert_equal(1, col('.')) 4316 4317 call feedkeys("She\<C-X>\<C-N>\<C-W>", 'tx') 4318 call assert_equal("", getline('.')) 4319 call assert_equal(1, col('.')) 4320 4321 " whole line 4322 call feedkeys("Shello hero\<CR>\<C-X>\<C-L>\<F5>\<ESC>", 'tx') 4323 call assert_equal("hello hero", g:line) 4324 call assert_equal(1, g:col) 4325 4326 call feedkeys("Shello hero\<CR>he\<C-X>\<C-L>\<F5>\<ESC>", 'tx') 4327 call assert_equal("hello hero", g:line) 4328 call assert_equal(3, g:col) 4329 4330 call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>er\<F5>\<ESC>", 'tx') 4331 call assert_equal("hero", g:line) 4332 call assert_equal(4, g:col) 4333 4334 " can not work with fuzzy 4335 set cot+=fuzzy 4336 call feedkeys("S\<C-X>\<C-O>", 'tx') 4337 call assert_equal("fobar", getline('.')) 4338 call assert_equal(5, col('.')) 4339 4340 " test for fuzzy and noinsert 4341 set cot+=noinsert 4342 call feedkeys("S\<C-X>\<C-O>fb\<F5>\<ESC>", 'tx') 4343 call assert_equal("fb", g:line) 4344 call assert_equal(3, g:col) 4345 4346 call feedkeys("S\<C-X>\<C-O>你\<F5>\<ESC>", 'tx') 4347 call assert_equal("你", g:line) 4348 call assert_equal(4, g:col) 4349 4350 call feedkeys("S\<C-X>\<C-O>fb\<C-Y>", 'tx') 4351 call assert_equal("fobar", getline('.')) 4352 call assert_equal(5, col('.')) 4353 4354 " When the pum is not visible, the preinsert has no effect 4355 set cot=preinsert 4356 call feedkeys("Sfoo1 foo2\<CR>f\<C-X>\<C-N>bar", 'tx') 4357 call assert_equal("foo1bar", getline('.')) 4358 call assert_equal(7, col('.')) 4359 4360 set cot=preinsert,menuone 4361 call feedkeys("Sfoo1 foo2\<CR>f\<C-X>\<C-N>\<F5>\<ESC>", 'tx') 4362 call assert_equal("foo1", g:line) 4363 call assert_equal(2, g:col) 4364 4365 inoremap <buffer> <f3> <cmd>call complete(4, [{'word': "fobar"}, {'word': "foobar"}])<CR> 4366 call feedkeys("Swp.\<F3>\<F5>\<BS>\<ESC>", 'tx') 4367 call assert_equal("wp.fobar", g:line) 4368 call assert_equal(4, g:col) 4369 call assert_equal("wp.", getline('.')) 4370 4371 %delete _ 4372 let &l:undolevels = &l:undolevels 4373 normal! ifoo 4374 let &l:undolevels = &l:undolevels 4375 normal! obar 4376 let &l:undolevels = &l:undolevels 4377 normal! obaz 4378 let &l:undolevels = &l:undolevels 4379 4380 func CheckUndo() 4381 let g:errmsg = '' 4382 call assert_equal(['foo', 'bar', 'baz'], getline(1, '$')) 4383 undo 4384 call assert_equal(['foo', 'bar'], getline(1, '$')) 4385 undo 4386 call assert_equal(['foo'], getline(1, '$')) 4387 undo 4388 call assert_equal([''], getline(1, '$')) 4389 later 3 4390 call assert_equal(['foo', 'bar', 'baz'], getline(1, '$')) 4391 call assert_equal('', v:errmsg) 4392 endfunc 4393 4394 " Check that switching buffer with "preinsert" doesn't corrupt undo. 4395 new 4396 setlocal bufhidden=wipe 4397 inoremap <buffer> <F2> <Cmd>enew!<CR> 4398 call feedkeys("i\<C-X>\<C-O>\<F2>\<Esc>", 'tx') 4399 bwipe! 4400 call CheckUndo() 4401 4402 " Check that closing window with "preinsert" doesn't corrupt undo. 4403 new 4404 setlocal bufhidden=wipe 4405 inoremap <buffer> <F2> <Cmd>close!<CR> 4406 call feedkeys("i\<C-X>\<C-O>\<F2>\<Esc>", 'tx') 4407 call CheckUndo() 4408 4409 %delete _ 4410 delfunc CheckUndo 4411 4412 bw! 4413 set cot& 4414 set omnifunc& 4415 delfunc Omni_test 4416 endfunc 4417 4418 func Test_autocomplete_completeopt_preinsert() 4419 func Omni_test(findstart, base) 4420 if a:findstart 4421 return col(".") - 1 4422 endif 4423 return [#{word: "fobar"}, #{word: "foobar"}] 4424 endfunc 4425 set omnifunc=Omni_test complete+=o 4426 set completeopt=preinsert autocomplete 4427 func GetLine() 4428 let g:line = getline('.') 4429 let g:col = col('.') 4430 endfunc 4431 4432 call Ntest_override("char_avail", 1) 4433 new 4434 inoremap <buffer><F5> <C-R>=GetLine()<CR> 4435 call feedkeys("Sfo\<F5>\<ESC>", 'tx') 4436 call assert_equal("fobar", g:line) 4437 call assert_equal(3, g:col) 4438 4439 call feedkeys("Sfoo\<F5>\<ESC>", 'tx') 4440 call assert_equal("foobar", g:line) 4441 4442 call feedkeys("Sfoo\<BS>\<BS>\<BS>", 'tx') 4443 call assert_equal("", getline('.')) 4444 4445 " delete a character 4446 call feedkeys("Sfoo\<BS>b\<F5>\<ESC>", 'tx') 4447 call assert_equal("fobar", g:line) 4448 call assert_equal(4, g:col) 4449 4450 set complete& 4451 %d 4452 call setline(1, ['fobar', 'foobar']) 4453 4454 call feedkeys("Gofoo\<BS>\<BS>\<F5>\<ESC>", 'tx') 4455 call assert_equal("fobar", g:line) 4456 call assert_equal(2, g:col) 4457 4458 call feedkeys("Shello wo\<Left>\<Left>\<Left>f\<F5>\<ESC>", 'tx') 4459 call assert_equal("hello fobar wo", g:line) 4460 call assert_equal(9, g:col) 4461 4462 call feedkeys("Shello wo\<Left>\<Left>\<Left>f\<BS>\<F5>\<ESC>", 'tx') 4463 call assert_equal("hello wo", g:line) 4464 call assert_equal(8, g:col) 4465 4466 call feedkeys("Shello wo\<Left>\<Left>\<Left>foo\<F5>\<ESC>", 'tx') 4467 call assert_equal("hello foobar wo", g:line) 4468 call assert_equal(11, g:col) 4469 4470 call feedkeys("Shello wo\<Left>\<Left>\<Left>foo\<BS>b\<F5>\<ESC>", 'tx') 4471 call assert_equal("hello fobar wo", g:line) 4472 call assert_equal(11, g:col) 4473 4474 " confirm 4475 call feedkeys("Sf\<C-Y>", 'tx') 4476 call assert_equal("fobar", getline('.')) 4477 call assert_equal(5, col('.')) 4478 4479 " cancel 4480 call feedkeys("Sfo\<C-E>", 'tx') 4481 call assert_equal("fo", getline('.')) 4482 call assert_equal(2, col('.')) 4483 4484 " delete preinsert part 4485 call feedkeys("Sfo ", 'tx') 4486 call assert_equal("fo ", getline('.')) 4487 call assert_equal(3, col('.')) 4488 4489 " can not work with fuzzy 4490 set cot+=fuzzy 4491 call feedkeys("Sf", 'tx') 4492 call assert_equal("f", getline('.')) 4493 set cot-=fuzzy 4494 4495 " does not work with 'ignorecase' unless 'infercase' is also enabled 4496 %d 4497 call setline(1, ['FIX', 'fobar', 'foobar']) 4498 set ignorecase 4499 call feedkeys("Gof\<F5>\<ESC>", 'tx') 4500 call assert_equal("f", g:line) " should not produce 'FIX' 4501 set infercase 4502 call feedkeys("Gof\<F5>\<ESC>", 'tx') 4503 call assert_equal("fix", g:line) 4504 set ignorecase& infercase& 4505 4506 %delete _ 4507 let &l:undolevels = &l:undolevels 4508 normal! ifoo 4509 let &l:undolevels = &l:undolevels 4510 normal! obar 4511 let &l:undolevels = &l:undolevels 4512 normal! obaz 4513 let &l:undolevels = &l:undolevels 4514 4515 func CheckUndo() 4516 let g:errmsg = '' 4517 call assert_equal(['foo', 'bar', 'baz'], getline(1, '$')) 4518 undo 4519 call assert_equal(['foo', 'bar'], getline(1, '$')) 4520 undo 4521 call assert_equal(['foo'], getline(1, '$')) 4522 undo 4523 call assert_equal([''], getline(1, '$')) 4524 later 3 4525 call assert_equal(['foo', 'bar', 'baz'], getline(1, '$')) 4526 call assert_equal('', v:errmsg) 4527 endfunc 4528 4529 " Check that switching buffer with "preinsert" doesn't corrupt undo. 4530 new 4531 setlocal bufhidden=wipe 4532 inoremap <buffer> <F2> <Cmd>enew!<CR> 4533 call feedkeys("if\<F2>\<Esc>", 'tx') 4534 bwipe! 4535 call CheckUndo() 4536 4537 " Check that closing window with "preinsert" doesn't corrupt undo. 4538 new 4539 setlocal bufhidden=wipe 4540 inoremap <buffer> <F2> <Cmd>close!<CR> 4541 call feedkeys("if\<F2>\<Esc>", 'tx') 4542 call CheckUndo() 4543 4544 %delete _ 4545 delfunc CheckUndo 4546 4547 bw! 4548 set cot& 4549 set omnifunc& 4550 set autocomplete& 4551 call Ntest_override("char_avail", 0) 4552 delfunc Omni_test 4553 delfunc GetLine 4554 endfunc 4555 4556 " Check that mark positions are correct after triggering multiline completion. 4557 func Test_complete_multiline_marks() 4558 func Omni_test(findstart, base) 4559 if a:findstart 4560 return col(".") 4561 endif 4562 return [ 4563 \ #{word: "func ()\n\t\nend"}, 4564 \ #{word: "foobar"}, 4565 \ #{word: "你好\n\t\n我好"} 4566 \ ] 4567 endfunc 4568 set omnifunc=Omni_test 4569 4570 new 4571 let lines = mapnew(range(10), 'string(v:val)') 4572 call setline(1, lines) 4573 call setpos("'a", [0, 3, 1, 0]) 4574 4575 call feedkeys("A \<C-X>\<C-O>\<C-E>\<BS>", 'tx') 4576 call assert_equal(lines, getline(1, '$')) 4577 call assert_equal([0, 3, 1, 0], getpos("'a")) 4578 4579 call feedkeys("A \<C-X>\<C-O>\<C-N>\<C-E>\<BS>", 'tx') 4580 call assert_equal(lines, getline(1, '$')) 4581 call assert_equal([0, 3, 1, 0], getpos("'a")) 4582 4583 call feedkeys("A \<C-X>\<C-O>\<C-N>\<C-N>\<C-E>\<BS>", 'tx') 4584 call assert_equal(lines, getline(1, '$')) 4585 call assert_equal([0, 3, 1, 0], getpos("'a")) 4586 4587 call feedkeys("A \<C-X>\<C-O>\<C-N>\<C-N>\<C-N>\<C-E>\<BS>", 'tx') 4588 call assert_equal(lines, getline(1, '$')) 4589 call assert_equal([0, 3, 1, 0], getpos("'a")) 4590 4591 call feedkeys("A \<C-X>\<C-O>\<C-Y>", 'tx') 4592 call assert_equal(['0 func ()', "\t", 'end'] + lines[1:], getline(1, '$')) 4593 call assert_equal([0, 5, 1, 0], getpos("'a")) 4594 4595 bw! 4596 set omnifunc& 4597 delfunc Omni_test 4598 endfunc 4599 4600 func Test_complete_match_count() 4601 func! PrintMenuWords() 4602 let info = complete_info(["selected", "matches"]) 4603 call map(info.matches, {_, v -> v.word}) 4604 return info 4605 endfunc 4606 4607 new 4608 set cpt=.^0,w 4609 call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) 4610 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4611 call assert_equal('fo{''matches'': [''fo'', ''foo'', ''foobar'', ''fobarbaz''], ''selected'': 0}', getline(5)) 4612 5d 4613 set cpt=.^0,w 4614 exe "normal! Gof\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4615 call assert_equal('fobarbaz{''matches'': [''fo'', ''foo'', ''foobar'', ''fobarbaz''], ''selected'': 3}', getline(5)) 4616 5d 4617 set cpt=.^1,w 4618 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4619 call assert_equal('fo{''matches'': [''fo''], ''selected'': 0}', getline(5)) 4620 5d 4621 " max_matches is ignored for backward search 4622 exe "normal! Gof\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4623 call assert_equal('fobarbaz{''matches'': [''fo'', ''foo'', ''foobar'', ''fobarbaz''], ''selected'': 3}', getline(5)) 4624 5d 4625 set cpt=.^2,w 4626 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4627 call assert_equal('fo{''matches'': [''fo'', ''foo''], ''selected'': 0}', getline(5)) 4628 5d 4629 set cot=menuone,noselect 4630 set cpt=.^1,w 4631 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4632 call assert_equal('f{''matches'': [''fo''], ''selected'': -1}', getline(5)) 4633 " With non-matching items 4634 %d 4635 call setline(1, ["free", "freebar", "foo", "fobarbaz"]) 4636 set cpt=.^2,w 4637 exe "normal! Gofo\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4638 call assert_equal('fo{''matches'': [''foo'', ''fobarbaz''], ''selected'': -1}', getline(5)) 4639 set cot& 4640 4641 func ComplFunc(findstart, base) 4642 if a:findstart 4643 return col(".") 4644 endif 4645 return ["foo1", "foo2", "foo3", "foo4"] 4646 endfunc 4647 4648 %d 4649 set completefunc=ComplFunc 4650 set cpt=.^1,F^2 4651 call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) 4652 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4653 call assert_equal('fo{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 0}', getline(5)) 4654 5d 4655 set cpt=.^1,,,F^2,,, 4656 call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) 4657 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4658 call assert_equal('fo{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 0}', getline(5)) 4659 5d 4660 exe "normal! Gof\<c-n>\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4661 call assert_equal('foo1{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 1}', getline(5)) 4662 5d 4663 exe "normal! Gof\<c-n>\<c-n>\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4664 call assert_equal('foo2{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 2}', getline(5)) 4665 5d 4666 exe "normal! Gof\<c-n>\<c-n>\<c-n>\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4667 call assert_equal('f{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': -1}', getline(5)) 4668 5d 4669 exe "normal! Gof\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4670 call assert_equal('fo{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 0}', getline(5)) 4671 4672 5d 4673 exe "normal! Gof\<c-n>\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4674 call assert_equal('f{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': -1}', getline(5)) 4675 5d 4676 exe "normal! Gof\<c-n>\<c-p>\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4677 call assert_equal('foo2{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 2}', getline(5)) 4678 5d 4679 exe "normal! Gof\<c-n>\<c-p>\<c-p>\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4680 call assert_equal('foo1{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 1}', getline(5)) 4681 5d 4682 exe "normal! Gof\<c-n>\<c-p>\<c-p>\<c-p>\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4683 call assert_equal('fo{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': 0}', getline(5)) 4684 5d 4685 exe "normal! Gof\<c-n>\<c-p>\<c-p>\<c-p>\<c-p>\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4686 call assert_equal('f{''matches'': [''fo'', ''foo1'', ''foo2''], ''selected'': -1}', getline(5)) 4687 4688 %d 4689 call setline(1, ["foo"]) 4690 set cpt=FComplFunc^2,. 4691 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4692 call assert_equal('foo1{''matches'': [''foo1'', ''foo2'', ''foo''], ''selected'': 0}', getline(2)) 4693 bw! 4694 4695 " Test refresh:always with max_items 4696 let g:CallCount = 0 4697 func! CompleteItemsSelect(findstart, base) 4698 if a:findstart 4699 return col('.') - 1 4700 endif 4701 let g:CallCount += 1 4702 let res = [[], ['foobar'], ['foo1', 'foo2', 'foo3'], ['foo4', 'foo5', 'foo6']] 4703 return #{words: res[g:CallCount], refresh: 'always'} 4704 endfunc 4705 4706 new 4707 set complete=.,Ffunction('CompleteItemsSelect')^2 4708 call setline(1, "foobarbar") 4709 let g:CallCount = 0 4710 exe "normal! Gof\<c-n>\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4711 call assert_equal('foobar{''matches'': [''foobarbar'', ''foobar''], ''selected'': 1}', getline(2)) 4712 call assert_equal(1, g:CallCount) 4713 %d 4714 call setline(1, "foobarbar") 4715 let g:CallCount = 0 4716 exe "normal! Gof\<c-n>\<c-p>o\<c-r>=PrintMenuWords()\<cr>" 4717 call assert_equal('fo{''matches'': [''foobarbar'', ''foo1'', ''foo2''], ''selected'': -1}', getline(2)) 4718 call assert_equal(2, g:CallCount) 4719 %d 4720 call setline(1, "foobarbar") 4721 let g:CallCount = 0 4722 exe "normal! Gof\<c-n>\<c-p>o\<bs>\<c-r>=PrintMenuWords()\<cr>" 4723 call assert_equal('f{''matches'': [''foobarbar'', ''foo4'', ''foo5''], ''selected'': -1}', getline(2)) 4724 call assert_equal(3, g:CallCount) 4725 bw! 4726 4727 " Test 'fuzzy' with max_items 4728 new 4729 set completeopt=menu,noselect,fuzzy 4730 set complete=. 4731 call setline(1, ["abcd", "abac", "abdc"]) 4732 exe "normal! Goa\<c-n>c\<c-r>=PrintMenuWords()\<cr>" 4733 call assert_equal('ac{''matches'': [''abac'', ''abcd'', ''abdc''], ''selected'': -1}', getline(4)) 4734 exe "normal! Sa\<c-n>c\<c-n>\<c-n>\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4735 call assert_equal('abac{''matches'': [''abac'', ''abcd'', ''abdc''], ''selected'': 0}', getline(4)) 4736 execute "normal Sa\<c-n>c\<c-n>" 4737 call assert_equal('abac', getline(4)) 4738 execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" 4739 call assert_equal('abac', getline(4)) 4740 set complete=.^1 4741 exe "normal! Sa\<c-n>c\<c-n>\<c-n>\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4742 call assert_equal('abac{''matches'': [''abac''], ''selected'': 0}', getline(4)) 4743 execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>" 4744 call assert_equal('abac', getline(4)) 4745 set complete=.^2 4746 execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>\<c-n>" 4747 call assert_equal('abac', getline(4)) 4748 set complete=.^3 4749 execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" 4750 call assert_equal('abac', getline(4)) 4751 set complete=.^4 4752 execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" 4753 call assert_equal('abac', getline(4)) 4754 4755 func! ComplFunc(findstart, base) 4756 if a:findstart 4757 return col(".") 4758 endif 4759 return ["abcde", "abacr"] 4760 endfunc 4761 4762 set complete=.,FComplFunc^1 4763 execute "normal Sa\<c-n>c\<c-n>\<c-n>" 4764 call assert_equal('abacr', getline(4)) 4765 execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" 4766 call assert_equal('abac', getline(4)) 4767 set complete=.^1,FComplFunc^1 4768 execute "normal Sa\<c-n>c\<c-n>\<c-n>\<c-n>\<c-n>" 4769 call assert_equal('abac', getline(4)) 4770 bw! 4771 4772 " Items with '\n' that cause menu to shift, with no leader (issue #17394) 4773 func! ComplFunc(findstart, base) 4774 if a:findstart == 1 4775 return col('.') - 1 4776 endif 4777 return ["one\ntwo\nthree", "four five six", "hello\nworld\nhere"] 4778 endfunc 4779 set completeopt=menuone,popup,noselect,fuzzy infercase 4780 set complete=.^1,FComplFunc^5 4781 new 4782 call setline(1, ["foo", "bar", "baz"]) 4783 execute "normal Go\<c-n>\<c-n>\<c-n>" 4784 call assert_equal(['one', 'two', 'three'], getline(4, 6)) 4785 %d 4786 call setline(1, ["foo", "bar", "baz"]) 4787 execute "normal Go\<c-n>\<c-n>\<c-n>\<c-p>" 4788 call assert_equal('foo', getline(4)) 4789 execute "normal S\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" 4790 call assert_equal('foo', getline(4)) 4791 set complete=.^1,FComplFunc^2 4792 execute "normal S\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>\<c-n>" 4793 call assert_equal('foo', getline(4)) 4794 execute "normal S\<c-n>\<c-p>\<c-p>\<c-p>\<c-n>\<c-n>" 4795 call assert_equal('four five six', getline(4)) 4796 bw! 4797 4798 set completeopt& complete& infercase& 4799 delfunc PrintMenuWords 4800 delfunc ComplFunc 4801 delfunc CompleteItemsSelect 4802 endfunc 4803 4804 func Test_complete_append_selected_match_default() 4805 " when typing a normal character during completion, 4806 " completion is ended, see 4807 " :h popupmenu-completion ("There are three states:") 4808 func PrintMenuWords() 4809 let info = complete_info(["selected", "matches"]) 4810 call map(info.matches, {_, v -> v.word}) 4811 return info 4812 endfunc 4813 4814 new 4815 call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) 4816 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4817 call assert_equal('fo{''matches'': [''fo'', ''foo'', ''foobar'', ''fobarbaz''], ''selected'': 0}', getline(5)) 4818 %d 4819 call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) 4820 exe "normal! Gof\<c-n>o\<c-r>=PrintMenuWords()\<cr>" 4821 call assert_equal('foo{''matches'': [], ''selected'': -1}', getline(5)) 4822 %d 4823 set completeopt=menu,noselect 4824 call setline(1, ["fo", "foo", "foobar", "fobarbaz"]) 4825 exe "normal! Gof\<c-n>\<c-n>o\<c-r>=PrintMenuWords()\<cr>" 4826 call assert_equal('foo{''matches'': [], ''selected'': -1}', getline(5)) 4827 bw! 4828 4829 set completeopt& 4830 delfunc PrintMenuWords 4831 endfunc 4832 4833 " Test normal mode (^N/^P/^X^N/^X^P) with smartcase when 1) matches are first 4834 " found and 2) matches are filtered (when a character is typed). 4835 func Test_smartcase_normal_mode() 4836 4837 func! PrintMenu() 4838 let info = complete_info(["matches"]) 4839 call map(info.matches, {_, v -> v.word}) 4840 return info 4841 endfunc 4842 4843 func! TestInner(key) 4844 let pr = "\<c-r>=PrintMenu()\<cr>" 4845 4846 new 4847 set completeopt=menuone,noselect ignorecase smartcase 4848 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4849 exe $"normal! ggOF{a:key}{pr}" 4850 call assert_equal('F{''matches'': [''Fast'', ''FAST'', ''False'', 4851 \ ''FALSE'']}', getline(1)) 4852 %d 4853 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4854 exe $"normal! ggOF{a:key}a{pr}" 4855 call assert_equal('Fa{''matches'': [''Fast'', ''False'']}', getline(1)) 4856 %d 4857 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4858 exe $"normal! ggOF{a:key}a\<bs>{pr}" 4859 call assert_equal('F{''matches'': [''Fast'', ''FAST'', ''False'', 4860 \ ''FALSE'']}', getline(1)) 4861 %d 4862 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4863 exe $"normal! ggOF{a:key}ax{pr}" 4864 call assert_equal('Fax{''matches'': []}', getline(1)) 4865 %d 4866 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4867 exe $"normal! ggOF{a:key}ax\<bs>{pr}" 4868 call assert_equal('Fa{''matches'': [''Fast'', ''False'']}', getline(1)) 4869 4870 %d 4871 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4872 exe $"normal! ggOF{a:key}A{pr}" 4873 call assert_equal('FA{''matches'': [''FAST'', ''FALSE'']}', getline(1)) 4874 %d 4875 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4876 exe $"normal! ggOF{a:key}A\<bs>{pr}" 4877 call assert_equal('F{''matches'': [''Fast'', ''FAST'', ''False'', 4878 \ ''FALSE'']}', getline(1)) 4879 %d 4880 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4881 exe $"normal! ggOF{a:key}AL{pr}" 4882 call assert_equal('FAL{''matches'': [''FALSE'']}', getline(1)) 4883 %d 4884 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4885 exe $"normal! ggOF{a:key}ALx{pr}" 4886 call assert_equal('FALx{''matches'': []}', getline(1)) 4887 %d 4888 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4889 exe $"normal! ggOF{a:key}ALx\<bs>{pr}" 4890 call assert_equal('FAL{''matches'': [''FALSE'']}', getline(1)) 4891 4892 %d 4893 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4894 exe $"normal! ggOf{a:key}{pr}" 4895 call assert_equal('f{''matches'': [''Fast'', ''FAST'', ''False'', ''FALSE'', 4896 \ ''fast'', ''false'']}', getline(1)) 4897 %d 4898 call setline(1, ["Fast", "FAST", "False", "FALSE", "fast", "false"]) 4899 exe $"normal! ggOf{a:key}a{pr}" 4900 call assert_equal('fa{''matches'': [''Fast'', ''FAST'', ''False'', ''FALSE'', 4901 \ ''fast'', ''false'']}', getline(1)) 4902 4903 %d 4904 exe $"normal! ggOf{a:key}{pr}" 4905 call assert_equal('f{''matches'': []}', getline(1)) 4906 exe $"normal! ggOf{a:key}a\<bs>{pr}" 4907 call assert_equal('f{''matches'': []}', getline(1)) 4908 set ignorecase& smartcase& completeopt& 4909 bw! 4910 endfunc 4911 4912 call TestInner("\<c-n>") 4913 call TestInner("\<c-p>") 4914 call TestInner("\<c-x>\<c-n>") 4915 call TestInner("\<c-x>\<c-p>") 4916 delfunc PrintMenu 4917 delfunc TestInner 4918 endfunc 4919 4920 " Test 'nearest' flag of 'completeopt' 4921 func Test_nearest_cpt_option() 4922 4923 func! PrintMenuWords() 4924 let info = complete_info(["selected", "matches"]) 4925 call map(info.matches, {_, v -> v.word}) 4926 return info 4927 endfunc 4928 4929 new 4930 set completeopt+=nearest 4931 call setline(1, ["fo", "foo", "foobar"]) 4932 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4933 call assert_equal('foobar{''matches'': [''foobar'', ''foo'', ''fo''], ''selected'': 0}', getline(4)) 4934 %d 4935 call setline(1, ["fo", "foo", "foobar"]) 4936 exe "normal! Of\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4937 call assert_equal('foobar{''matches'': [''fo'', ''foo'', ''foobar''], ''selected'': 2}', getline(1)) 4938 %d 4939 4940 set completeopt=menu,noselect,nearest 4941 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4942 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4943 call assert_equal('f{''matches'': [''foobarbaz'', ''foobar'', ''foo'', ''fo''], ''selected'': -1}', getline(5)) 4944 %d 4945 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4946 exe "normal! Gof\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4947 call assert_equal('f{''matches'': [''foobarbaz'', ''foobar'', ''foo'', ''fo''], ''selected'': -1}', getline(5)) 4948 %d 4949 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4950 exe "normal! Of\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4951 call assert_equal('f{''matches'': [''fo'', ''foo'', ''foobar'', ''foobarbaz''], ''selected'': -1}', getline(1)) 4952 %d 4953 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4954 exe "normal! Of\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4955 call assert_equal('f{''matches'': [''fo'', ''foo'', ''foobar'', ''foobarbaz''], ''selected'': -1}', getline(1)) 4956 %d 4957 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4958 exe "normal! of\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4959 call assert_equal('f{''matches'': [''foo'', ''fo'', ''foobar'', ''foobarbaz''], ''selected'': -1}', getline(2)) 4960 %d 4961 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4962 exe "normal! of\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4963 call assert_equal('f{''matches'': [''foo'', ''fo'', ''foobar'', ''foobarbaz''], ''selected'': -1}', getline(2)) 4964 %d 4965 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4966 exe "normal! jof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4967 call assert_equal('f{''matches'': [''foobar'', ''foo'', ''foobarbaz'', ''fo''], ''selected'': -1}', getline(3)) 4968 %d 4969 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4970 exe "normal! jof\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4971 call assert_equal('f{''matches'': [''foobar'', ''foo'', ''foobarbaz'', ''fo''], ''selected'': -1}', getline(3)) 4972 %d 4973 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4974 exe "normal! 2jof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4975 call assert_equal('f{''matches'': [''foobarbaz'', ''foobar'', ''foo'', ''fo''], ''selected'': -1}', getline(4)) 4976 %d 4977 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 4978 exe "normal! 2jof\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4979 call assert_equal('f{''matches'': [''foobarbaz'', ''foobar'', ''foo'', ''fo''], ''selected'': -1}', getline(4)) 4980 4981 %d 4982 set completeopt=menuone,noselect,nearest 4983 call setline(1, "foo") 4984 exe "normal! Of\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4985 call assert_equal('f{''matches'': [''foo''], ''selected'': -1}', getline(1)) 4986 %d 4987 call setline(1, "foo") 4988 exe "normal! o\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4989 call assert_equal('{''matches'': [''foo''], ''selected'': -1}', getline(2)) 4990 %d 4991 exe "normal! o\<c-n>\<c-r>=PrintMenuWords()\<cr>" 4992 call assert_equal('', getline(1)) 4993 %d 4994 exe "normal! o\<c-p>\<c-r>=PrintMenuWords()\<cr>" 4995 call assert_equal('', getline(1)) 4996 4997 " Reposition match: node is at tail but score is too small 4998 %d 4999 call setline(1, ["foo1", "bar1", "bar2", "foo2", "foo1"]) 5000 exe "normal! of\<c-n>\<c-r>=PrintMenuWords()\<cr>" 5001 call assert_equal('f{''matches'': [''foo1'', ''foo2''], ''selected'': -1}', getline(2)) 5002 " Reposition match: node is in middle but score is too big 5003 %d 5004 call setline(1, ["foo1", "bar1", "bar2", "foo3", "foo1", "foo2"]) 5005 exe "normal! of\<c-n>\<c-r>=PrintMenuWords()\<cr>" 5006 call assert_equal('f{''matches'': [''foo1'', ''foo3'', ''foo2''], ''selected'': -1}', getline(2)) 5007 5008 " Multiple sources 5009 func F1(findstart, base) 5010 if a:findstart 5011 return col('.') - 1 5012 endif 5013 return ['foo4', 'foo5'] 5014 endfunc 5015 %d 5016 set complete+=FF1 5017 call setline(1, ["foo1", "foo2", "bar1", "foo3"]) 5018 exe "normal! 2jof\<c-n>\<c-r>=PrintMenuWords()\<cr>" 5019 call assert_equal('f{''matches'': [''foo3'', ''foo2'', ''foo1'', ''foo4'', ''foo5''], 5020 \ ''selected'': -1}', getline(4)) 5021 set complete-=FF1 5022 delfunc F1 5023 5024 set completeopt=menu,longest,nearest 5025 %d 5026 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 5027 exe "normal! of\<c-n>\<c-r>=PrintMenuWords()\<cr>" 5028 call assert_equal('fo{''matches'': [''foo'', ''fo'', ''foobar'', ''foobarbaz''], ''selected'': -1}', getline(2)) 5029 %d 5030 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 5031 exe "normal! 2jof\<c-p>\<c-r>=PrintMenuWords()\<cr>" 5032 call assert_equal('fo{''matches'': [''foobarbaz'', ''foobar'', ''foo'', ''fo''], ''selected'': -1}', getline(4)) 5033 bw! 5034 5035 set completeopt& 5036 delfunc PrintMenuWords 5037 endfunc 5038 5039 func Test_register_completion() 5040 let @a = "completion test apple application" 5041 let @b = "banana behavior better best" 5042 let @c = "complete completion compliment computer" 5043 let g:save_reg = '' 5044 func GetItems() 5045 let g:result = complete_info(['pum_visible']) 5046 endfunc 5047 5048 new 5049 call setline(1, "comp") 5050 call cursor(1, 4) 5051 call feedkeys("a\<C-X>\<C-R>\<C-N>\<C-N>\<Esc>", 'tx') 5052 call assert_equal("compliment", getline(1)) 5053 5054 inoremap <buffer><F2> <C-R>=GetItems()<CR> 5055 call feedkeys("S\<C-X>\<C-R>\<F2>\<ESC>", 'tx') 5056 call assert_equal(1, g:result['pum_visible']) 5057 5058 call setline(1, "app") 5059 call cursor(1, 3) 5060 call feedkeys("a\<C-X>\<C-R>\<C-N>\<Esc>", 'tx') 5061 call assert_equal("application", getline(1)) 5062 5063 " Test completion with case differences 5064 set ignorecase 5065 let @e = "TestCase UPPERCASE lowercase" 5066 call setline(1, "testc") 5067 call cursor(1, 5) 5068 call feedkeys("a\<C-X>\<C-R>\<Esc>", 'tx') 5069 call assert_equal("TestCase", getline(1)) 5070 5071 " Test clipboard registers if available 5072 if has('clipboard_working') 5073 let g:save_reg = getreg('*') 5074 call setreg('*', "clipboard selection unique words") 5075 call setline(1, "uni") 5076 call cursor(1, 3) 5077 call feedkeys("a\<C-X>\<C-R>\<Esc>", 'tx') 5078 call assert_equal("unique", getline(1)) 5079 call setreg('*', g:save_reg) 5080 5081 let g:save_reg = getreg('+') 5082 call setreg('+', "system clipboard special content") 5083 call setline(1, "spe") 5084 call cursor(1, 3) 5085 call feedkeys("a\<C-X>\<C-R>\<Esc>", 'tx') 5086 call assert_equal("special", getline(1)) 5087 call setreg('+', g:save_reg) 5088 5089 call setreg('*', g:save_reg) 5090 call setreg('a', "normal register") 5091 call setreg('*', "clipboard mixed content") 5092 call setline(1, "mix") 5093 call cursor(1, 3) 5094 call feedkeys("a\<C-X>\<C-R>\<Esc>", 'tx') 5095 call assert_equal("mixed", getline(1)) 5096 call setreg('*', g:save_reg) 5097 endif 5098 5099 " Test black hole register should be skipped 5100 let @_ = "blackhole content should not appear" 5101 call setline(1, "black") 5102 call cursor(1, 5) 5103 call feedkeys("a\<C-X>\<C-R>\<Esc>", 'tx') 5104 call assert_equal("black", getline(1)) 5105 5106 let @1 = "recent yank zero" 5107 call setline(1, "ze") 5108 call cursor(1, 2) 5109 call feedkeys("a\<C-X>\<C-R>\<Esc>", 'tx') 5110 call assert_equal("zero", getline(1)) 5111 5112 call feedkeys("Sze\<C-X>\<C-R>\<C-R>=string(complete_info(['mode']))\<CR>\<ESC>", "tx") 5113 call assert_equal("zero{'mode': 'register'}", getline(1)) 5114 5115 " Test consecutive CTRL-X CTRL-R (adding mode) 5116 " First CTRL-X CTRL-R should split into words, second should use full content 5117 let @f = "hello world test complete" 5118 call setline(1, "hel") 5119 call cursor(1, 3) 5120 call feedkeys("a\<C-X>\<C-R>\<C-N>\<Esc>", 'tx') 5121 call assert_equal("hello", getline(1)) 5122 5123 " Second consecutive CTRL-X CTRL-R should complete with full content 5124 call setline(1, "hello") 5125 call cursor(1, 5) 5126 call feedkeys("a\<C-X>\<C-R>\<C-X>\<C-R>\<Esc>", 'tx') 5127 call assert_equal("hello world test complete", getline(1)) 5128 5129 " Test consecutive completion with multi-line register 5130 let @g = "first line content\nsecond line here\nthird line data" 5131 call setline(1, "first") 5132 call cursor(1, 5) 5133 call feedkeys("a\<C-X>\<C-R>\<C-X>\<C-R>\<Esc>", 'tx') 5134 call assert_equal("first line content", getline(1)) 5135 5136 " Clean up 5137 bwipe! 5138 delfunc GetItems 5139 unlet g:result 5140 unlet g:save_reg 5141 set ignorecase& 5142 endfunc 5143 5144 " Test refresh:always with unloaded buffers (issue #17363) 5145 func Test_complete_unloaded_buf_refresh_always() 5146 func TestComplete(findstart, base) 5147 if a:findstart 5148 let line = getline('.') 5149 let start = col('.') - 1 5150 while start > 0 && line[start - 1] =~ '\a' 5151 let start -= 1 5152 endwhile 5153 return start 5154 else 5155 let g:CallCount += 1 5156 let res = ["update1", "update12", "update123"] 5157 return #{words: res, refresh: 'always'} 5158 endif 5159 endfunc 5160 5161 let g:CallCount = 0 5162 set completeopt=menu,longest 5163 set completefunc=TestComplete 5164 set complete=b,u,t,i,F 5165 badd foo1 5166 badd foo2 5167 new 5168 exe "normal! iup\<C-N>\<BS>\<BS>\<BS>\<BS>\<BS>" 5169 call assert_equal('up', getline(1)) 5170 call assert_equal(6, g:CallCount) 5171 5172 bd! foo1 5173 bd! foo2 5174 bw! 5175 set completeopt& 5176 set complete& 5177 set completefunc& 5178 delfunc TestComplete 5179 endfunc 5180 5181 " Verify that the order of matches from each source is consistent 5182 " during both ^N and ^P completions (Issue #17425). 5183 func Test_complete_with_multiple_function_sources() 5184 func F1(findstart, base) 5185 if a:findstart 5186 return col('.') - 1 5187 endif 5188 return ['one', 'two', 'three'] 5189 endfunc 5190 5191 func F2(findstart, base) 5192 if a:findstart 5193 return col('.') - 1 5194 endif 5195 return ['four', 'five', 'six'] 5196 endfunc 5197 5198 func F3(findstart, base) 5199 if a:findstart 5200 return col('.') - 1 5201 endif 5202 return ['seven', 'eight', 'nine'] 5203 endfunc 5204 5205 new 5206 setlocal complete=.,FF1,FF2,FF3 5207 inoremap <buffer> <F2> <Cmd>let b:matches = complete_info(["matches"]).matches<CR> 5208 call setline(1, ['xxx', 'yyy', 'zzz', '']) 5209 5210 call feedkeys("GS\<C-N>\<F2>\<Esc>0", 'tx!') 5211 call assert_equal([ 5212 \ 'xxx', 'yyy', 'zzz', 5213 \ 'one', 'two', 'three', 5214 \ 'four', 'five', 'six', 5215 \ 'seven', 'eight', 'nine', 5216 \ ], b:matches->mapnew('v:val.word')) 5217 5218 call feedkeys("GS\<C-P>\<F2>\<Esc>0", 'tx!') 5219 call assert_equal([ 5220 \ 'seven', 'eight', 'nine', 5221 \ 'four', 'five', 'six', 5222 \ 'one', 'two', 'three', 5223 \ 'xxx', 'yyy', 'zzz', 5224 \ ], b:matches->mapnew('v:val.word')) 5225 5226 %delete 5227 5228 call feedkeys("GS\<C-N>\<F2>\<Esc>0", 'tx!') 5229 call assert_equal([ 5230 \ 'one', 'two', 'three', 5231 \ 'four', 'five', 'six', 5232 \ 'seven', 'eight', 'nine', 5233 \ ], b:matches->mapnew('v:val.word')) 5234 5235 call feedkeys("GS\<C-P>\<F2>\<Esc>0", 'tx!') 5236 call assert_equal([ 5237 \ 'seven', 'eight', 'nine', 5238 \ 'four', 'five', 'six', 5239 \ 'one', 'two', 'three', 5240 \ ], b:matches->mapnew('v:val.word')) 5241 5242 bwipe! 5243 delfunc F1 5244 delfunc F2 5245 delfunc F3 5246 endfunc 5247 5248 func Test_complete_fuzzy_omnifunc_backspace() 5249 let g:do_complete = v:false 5250 func Omni_test(findstart, base) 5251 if a:findstart 5252 let g:do_complete = !g:do_complete 5253 endif 5254 if g:do_complete 5255 return a:findstart ? 0 : [#{word: a:base .. 'def'}, #{word: a:base .. 'ghi'}] 5256 endif 5257 return a:findstart ? -3 : {} 5258 endfunc 5259 5260 new 5261 redraw " need this to prevent NULL dereference in Nvim 5262 setlocal omnifunc=Omni_test 5263 setlocal completeopt=menuone,fuzzy,noinsert 5264 call setline(1, 'abc') 5265 call feedkeys("A\<C-X>\<C-O>\<BS>\<Esc>0", 'tx!') 5266 call assert_equal('ab', getline(1)) 5267 5268 bwipe! 5269 delfunc Omni_test 5270 unlet g:do_complete 5271 endfunc 5272 5273 " Test that option shortmess=c turns off completion messages 5274 func Test_shortmess() 5275 CheckScreendump 5276 5277 let lines =<< trim END 5278 call setline(1, ['hello', 'hullo', 'heee']) 5279 END 5280 5281 call writefile(lines, 'Xpumscript', 'D') 5282 let buf = RunVimInTerminal('-S Xpumscript', #{rows: 12}) 5283 call term_sendkeys(buf, "Goh\<C-N>") 5284 call TermWait(buf, 200) 5285 call VerifyScreenDump(buf, 'Test_shortmess_complmsg_1', {}) 5286 call term_sendkeys(buf, "\<ESC>:set shm+=c\<CR>") 5287 call term_sendkeys(buf, "Sh\<C-N>") 5288 call TermWait(buf, 200) 5289 call VerifyScreenDump(buf, 'Test_shortmess_complmsg_2', {}) 5290 5291 call StopVimInTerminal(buf) 5292 endfunc 5293 5294 " Test 'complete' containing F{func} that complete from nonkeyword 5295 func Test_nonkeyword_trigger() 5296 5297 " Trigger expansion even when another char is waiting in the typehead 5298 call Ntest_override("char_avail", 1) 5299 5300 let g:CallCount = 0 5301 func! NonKeywordComplete(findstart, base) 5302 let line = getline('.')->strpart(0, col('.') - 1) 5303 let nonkeyword2 = len(line) > 1 && match(line[-2:-2], '\k') != 0 5304 if a:findstart 5305 return nonkeyword2 ? col('.') - 3 : (col('.') - 2) 5306 else 5307 let g:CallCount += 1 5308 return [$"{a:base}foo", $"{a:base}bar"] 5309 endif 5310 endfunc 5311 5312 new 5313 inoremap <buffer> <F2> <Cmd>let b:matches = complete_info(["matches"]).matches<CR> 5314 inoremap <buffer> <F3> <Cmd>let b:selected = complete_info(["selected"]).selected<CR> 5315 call setline(1, ['abc', 'abcd', 'fo', 'b', '']) 5316 5317 " Test 1a: Nonkeyword before cursor lists words with at least two letters 5318 call feedkeys("GS=\<C-N>\<F2>\<Esc>0", 'tx!') 5319 call assert_equal(['abc', 'abcd', 'fo'], b:matches->mapnew('v:val.word')) 5320 call assert_equal('=abc', getline('.')) 5321 5322 " Test 1b: With F{func} nonkeyword collects matches 5323 set complete=.,FNonKeywordComplete 5324 for noselect in range(2) 5325 if noselect 5326 set completeopt+=noselect 5327 endif 5328 let g:CallCount = 0 5329 call feedkeys("S=\<C-N>\<F2>\<Esc>0", 'tx!') 5330 call assert_equal(['abc', 'abcd', 'fo', '=foo', '=bar'], b:matches->mapnew('v:val.word')) 5331 call assert_equal(1, g:CallCount) 5332 call assert_equal(noselect ? '=' : '=abc', getline('.')) 5333 let g:CallCount = 0 5334 call feedkeys("S->\<C-N>\<F2>\<Esc>0", 'tx!') 5335 call assert_equal(['abc', 'abcd', 'fo', '->foo', '->bar'], b:matches->mapnew('v:val.word')) 5336 call assert_equal(1, g:CallCount) 5337 call assert_equal(noselect ? '->' : '->abc', getline('.')) 5338 set completeopt& 5339 endfor 5340 5341 " Test 1c: Keyword collects from {func} 5342 let g:CallCount = 0 5343 call feedkeys("Sa\<C-N>\<F2>\<Esc>0", 'tx!') 5344 call assert_equal(['abc', 'abcd', 'afoo', 'abar'], b:matches->mapnew('v:val.word')) 5345 call assert_equal(1, g:CallCount) 5346 call assert_equal('abc', getline('.')) 5347 5348 set completeopt+=noselect 5349 let g:CallCount = 0 5350 call feedkeys("Sa\<C-N>\<F2>\<Esc>0", 'tx!') 5351 call assert_equal(['abc', 'abcd', 'afoo', 'abar'], b:matches->mapnew('v:val.word')) 5352 call assert_equal(1, g:CallCount) 5353 call assert_equal('a', getline('.')) 5354 5355 " Test 1d: Nonkeyword after keyword collects items again 5356 let g:CallCount = 0 5357 call feedkeys("Sa\<C-N>#\<C-N>\<F2>\<Esc>0", 'tx!') 5358 call assert_equal(['abc', 'abcd', 'fo', '#foo', '#bar'], b:matches->mapnew('v:val.word')) 5359 call assert_equal(2, g:CallCount) 5360 call assert_equal('a#', getline('.')) 5361 set completeopt& 5362 5363 " Test 2: Filter nonkeyword and keyword matches with different startpos 5364 set completeopt+=menuone,noselect 5365 call feedkeys("S#a\<C-N>b\<F2>\<F3>\<Esc>0", 'tx!') 5366 call assert_equal(['abc', 'abcd', '#abar'], b:matches->mapnew('v:val.word')) 5367 call assert_equal(-1, b:selected) 5368 call assert_equal('#ab', getline('.')) 5369 5370 set completeopt+=fuzzy 5371 call feedkeys("S#a\<C-N>b\<F2>\<F3>\<Esc>0", 'tx!') 5372 call assert_equal(['#abar', 'abc', 'abcd'], b:matches->mapnew('v:val.word')) 5373 call assert_equal(-1, b:selected) 5374 call assert_equal('#ab', getline('.')) 5375 set completeopt& 5376 5377 " Test 3: Navigate menu containing nonkeyword and keyword items 5378 call feedkeys("S->\<C-N>\<F2>\<Esc>0", 'tx!') 5379 call assert_equal(['abc', 'abcd', 'fo', '->foo', '->bar'], b:matches->mapnew('v:val.word')) 5380 call assert_equal('->abc', getline('.')) 5381 call feedkeys("S->" . repeat("\<C-N>", 3) . "\<Esc>0", 'tx!') 5382 call assert_equal('->fo', getline('.')) 5383 call feedkeys("S->" . repeat("\<C-N>", 4) . "\<Esc>0", 'tx!') 5384 call assert_equal('->foo', getline('.')) 5385 call feedkeys("S->" . repeat("\<C-N>", 4) . "\<C-P>\<Esc>0", 'tx!') 5386 call assert_equal('->fo', getline('.')) 5387 call feedkeys("S->" . repeat("\<C-N>", 5) . "\<Esc>0", 'tx!') 5388 call assert_equal('->bar', getline('.')) 5389 call feedkeys("S->" . repeat("\<C-N>", 5) . "\<C-P>\<Esc>0", 'tx!') 5390 call assert_equal('->foo', getline('.')) 5391 call feedkeys("S->" . repeat("\<C-N>", 6) . "\<Esc>0", 'tx!') 5392 call assert_equal('->', getline('.')) 5393 call feedkeys("S->" . repeat("\<C-N>", 7) . "\<Esc>0", 'tx!') 5394 call assert_equal('->abc', getline('.')) 5395 call feedkeys("S->" . repeat("\<C-P>", 7) . "\<Esc>0", 'tx!') 5396 call assert_equal('->fo', getline('.')) 5397 " Replace 5398 call feedkeys("S# x y z\<Esc>0lR\<C-N>\<Esc>0", 'tx!') 5399 call assert_equal('#abcy z', getline('.')) 5400 call feedkeys("S# x y z\<Esc>0lR" . repeat("\<C-P>", 4) . "\<Esc>0", 'tx!') 5401 call assert_equal('#bary z', getline('.')) 5402 5403 bw! 5404 call Ntest_override("char_avail", 0) 5405 delfunc NonKeywordComplete 5406 set complete& 5407 unlet g:CallCount 5408 endfunc 5409 5410 func Test_autocomplete_trigger() 5411 " Trigger expansion even when another char is waiting in the typehead 5412 call Ntest_override("char_avail", 1) 5413 5414 let g:CallCount = 0 5415 func! NonKeywordComplete(findstart, base) 5416 let line = getline('.')->strpart(0, col('.') - 1) 5417 let nonkeyword2 = len(line) > 1 && match(line[-2:-2], '\k') != 0 5418 if a:findstart 5419 return nonkeyword2 ? col('.') - 3 : (col('.') - 2) 5420 else 5421 let g:CallCount += 1 5422 return [$"{a:base}foo", $"{a:base}bar"] 5423 endif 5424 endfunc 5425 5426 new 5427 inoremap <buffer> <F2> <Cmd>let b:matches = complete_info(["matches"]).matches<CR> 5428 inoremap <buffer> <F3> <Cmd>let b:selected = complete_info(["matches", "selected"]).selected<CR> 5429 5430 call setline(1, ['abc', 'abcd', 'fo', 'b', '']) 5431 set autocomplete 5432 5433 " Test 1a: Nonkeyword doesn't open menu without F{func} when autocomplete 5434 call feedkeys("GS=\<F2>\<Esc>0", 'tx!') 5435 call assert_equal([], b:matches) 5436 call assert_equal('=', getline('.')) 5437 " ^N opens menu of keywords (of len > 1) 5438 call feedkeys("S=\<C-E>\<C-N>\<F2>\<Esc>0", 'tx!') 5439 call assert_equal(['abc', 'abcd', 'fo'], b:matches->mapnew('v:val.word')) 5440 call assert_equal('=abc', getline('.')) 5441 5442 " Test 1b: With F{func} nonkeyword collects matches 5443 set complete=.,FNonKeywordComplete 5444 let g:CallCount = 0 5445 call feedkeys("S=\<F2>\<Esc>0", 'tx!') 5446 call assert_equal(['=foo', '=bar'], b:matches->mapnew('v:val.word')) 5447 call assert_equal(1, g:CallCount) 5448 call assert_equal('=', getline('.')) 5449 let g:CallCount = 0 5450 call feedkeys("S->\<F2>\<Esc>0", 'tx!') 5451 call assert_equal(['->foo', '->bar'], b:matches->mapnew('v:val.word')) 5452 call assert_equal(2, g:CallCount) 5453 call assert_equal('->', getline('.')) 5454 5455 " Test 1c: Keyword after nonkeyword can collect both types of items 5456 let g:CallCount = 0 5457 call feedkeys("S#a\<F2>\<Esc>0", 'tx!') 5458 call assert_equal(['abcd', 'abc', '#afoo', '#abar'], b:matches->mapnew('v:val.word')) 5459 call assert_equal(2, g:CallCount) 5460 call assert_equal('#a', getline('.')) 5461 let g:CallCount = 0 5462 call feedkeys("S#a.\<F2>\<Esc>0", 'tx!') 5463 call assert_equal(['.foo', '.bar'], b:matches->mapnew('v:val.word')) 5464 call assert_equal(3, g:CallCount) 5465 call assert_equal('#a.', getline('.')) 5466 let g:CallCount = 0 5467 call feedkeys("S#a.a\<F2>\<Esc>0", 'tx!') 5468 call assert_equal(['abcd', 'abc', '.afoo', '.abar'], b:matches->mapnew('v:val.word')) 5469 call assert_equal(4, g:CallCount) 5470 call assert_equal('#a.a', getline('.')) 5471 5472 " Test 1d: Nonkeyword after keyword collects items again 5473 let g:CallCount = 0 5474 call feedkeys("Sa\<F2>\<Esc>0", 'tx!') 5475 call assert_equal(['abcd', 'abc', 'afoo', 'abar'], b:matches->mapnew('v:val.word')) 5476 call assert_equal(1, g:CallCount) 5477 call assert_equal('a', getline('.')) 5478 let g:CallCount = 0 5479 call feedkeys("Sa#\<F2>\<Esc>0", 'tx!') 5480 call assert_equal(['#foo', '#bar'], b:matches->mapnew('v:val.word')) 5481 call assert_equal(2, g:CallCount) 5482 call assert_equal('a#', getline('.')) 5483 5484 " Test 2: Filter nonkeyword and keyword matches with different startpos 5485 for fuzzy in range(2) 5486 if fuzzy 5487 set completeopt+=fuzzy 5488 endif 5489 call feedkeys("S#ab\<F2>\<F3>\<Esc>0", 'tx!') 5490 if fuzzy 5491 call assert_equal(['#abar', 'abc', 'abcd'], b:matches->mapnew('v:val.word')) 5492 else " Ordering of items is by 'nearest' to cursor by default 5493 call assert_equal(['abcd', 'abc', '#abar'], b:matches->mapnew('v:val.word')) 5494 endif 5495 call assert_equal(-1, b:selected) 5496 call assert_equal('#ab', getline('.')) 5497 call feedkeys("S#ab" . repeat("\<C-N>", 3) . "\<F3>\<Esc>0", 'tx!') 5498 call assert_equal(fuzzy ? '#abcd' : '#abar', getline('.')) 5499 call assert_equal(2, b:selected) 5500 5501 let g:CallCount = 0 5502 call feedkeys("GS#aba\<F2>\<Esc>0", 'tx!') 5503 call assert_equal(['#abar'], b:matches->mapnew('v:val.word')) 5504 call assert_equal(2, g:CallCount) 5505 call assert_equal('#aba', getline('.')) 5506 5507 let g:CallCount = 0 5508 call feedkeys("S#abc\<F2>\<Esc>0", 'tx!') 5509 if fuzzy 5510 call assert_equal(['abc', 'abcd'], b:matches->mapnew('v:val.word')) 5511 else 5512 call assert_equal(['abcd', 'abc'], b:matches->mapnew('v:val.word')) 5513 endif 5514 call assert_equal(2, g:CallCount) 5515 set completeopt& 5516 endfor 5517 5518 " Test 3: Navigate menu containing nonkeyword and keyword items 5519 call feedkeys("S#a\<F2>\<Esc>0", 'tx!') 5520 call assert_equal(['abcd', 'abc', '#afoo', '#abar'], b:matches->mapnew('v:val.word')) 5521 call feedkeys("S#a" . repeat("\<C-N>", 3) . "\<Esc>0", 'tx!') 5522 call assert_equal('#afoo', getline('.')) 5523 call feedkeys("S#a" . repeat("\<C-N>", 3) . "\<C-P>\<Esc>0", 'tx!') 5524 call assert_equal('#abc', getline('.')) 5525 5526 call feedkeys("S#a.a\<F2>\<Esc>0", 'tx!') 5527 call assert_equal(['abcd', 'abc', '.afoo', '.abar'], b:matches->mapnew('v:val.word')) 5528 call feedkeys("S#a.a" . repeat("\<C-N>", 2) . "\<Esc>0", 'tx!') 5529 call assert_equal('#a.abc', getline('.')) 5530 call feedkeys("S#a.a" . repeat("\<C-N>", 3) . "\<Esc>0", 'tx!') 5531 call assert_equal('#a.afoo', getline('.')) 5532 call feedkeys("S#a.a" . repeat("\<C-N>", 3) . "\<C-P>\<Esc>0", 'tx!') 5533 call assert_equal('#a.abc', getline('.')) 5534 call feedkeys("S#a.a" . repeat("\<C-P>", 6) . "\<Esc>0", 'tx!') 5535 call assert_equal('#a.abar', getline('.')) 5536 5537 " Test 4a: When autocomplete menu is active, ^X^N completes buffer keywords 5538 let g:CallCount = 0 5539 call feedkeys("S#a\<C-E>\<C-X>\<C-N>\<F2>\<Esc>0", 'tx!') 5540 call assert_equal(['abc', 'abcd'], b:matches->mapnew('v:val.word')) 5541 call assert_equal(2, g:CallCount) 5542 5543 " Test 4b: When autocomplete menu is active, ^X^O completes omnifunc 5544 let g:CallCount = 0 5545 set omnifunc=NonKeywordComplete 5546 call feedkeys("S#a\<C-X>\<C-O>\<F2>\<Esc>0", 'tx!') 5547 call assert_equal(['#afoo', '#abar'], b:matches->mapnew('v:val.word')) 5548 call assert_equal(3, g:CallCount) 5549 5550 " Test 4c: When autocomplete menu is active, ^E^N completes keyword 5551 call feedkeys("Sa\<C-E>\<F2>\<Esc>0", 'tx!') 5552 call assert_equal([], b:matches->mapnew('v:val.word')) 5553 let g:CallCount = 0 5554 call feedkeys("Sa\<C-E>\<C-N>\<F2>\<Esc>0", 'tx!') 5555 call assert_equal(['abc', 'abcd', 'afoo', 'abar'], b:matches->mapnew('v:val.word')) 5556 call assert_equal(2, g:CallCount) 5557 5558 " Test 4d: When autocomplete menu is active, ^X^L completes lines 5559 %d 5560 let g:CallCount = 0 5561 call setline(1, ["afoo bar", "barbar foo", "foo bar", "and"]) 5562 call feedkeys("Goa\<C-X>\<C-L>\<F2>\<Esc>0", 'tx!') 5563 call assert_equal(['afoo bar', 'and'], b:matches->mapnew('v:val.word')) 5564 call assert_equal(1, g:CallCount) 5565 5566 " Issue #18044 5567 %d 5568 call setline(1, ["first line", "second line"]) 5569 call feedkeys("Gof\<C-X>\<C-L>\<Esc>", 'tx!') 5570 call assert_equal("first line", getline(3)) 5571 call feedkeys("Sf\<C-X>\<C-L>\<C-X>\<C-L>\<Esc>", 'tx!') 5572 call assert_equal("second line", getline(4)) 5573 5574 " Test 5: When invalid prefix stops completion, backspace should restart it 5575 %d 5576 set complete& 5577 call setline(1, ["afoo bar", "barbar foo", "foo bar", "and"]) 5578 call feedkeys("Goabc\<F2>\<Esc>0", 'tx!') 5579 call assert_equal([], b:matches->mapnew('v:val.word')) 5580 call feedkeys("Sabc\<BS>\<BS>\<F2>\<Esc>0", 'tx!') 5581 call assert_equal(['and', 'afoo'], b:matches->mapnew('v:val.word')) 5582 call feedkeys("Szx\<BS>\<F2>\<Esc>0", 'tx!') 5583 call assert_equal([], b:matches->mapnew('v:val.word')) 5584 call feedkeys("Sazx\<Left>\<BS>\<F2>\<Esc>0", 'tx!') 5585 call assert_equal(['and', 'afoo'], b:matches->mapnew('v:val.word')) 5586 5587 " Test 6: <BS> should clear the selected item (PR #18265) 5588 %d 5589 call setline(1, ["foobarfoo", "foobar", "foobarbaz"]) 5590 call feedkeys("Gofo\<C-N>\<C-N>\<F2>\<F3>\<Esc>0", 'tx!') 5591 call assert_equal(['foobarbaz', 'foobar', 'foobarfoo'], b:matches->mapnew('v:val.word')) 5592 call assert_equal(1, b:selected) 5593 call feedkeys("Sfo\<C-N>\<C-N>\<BS>\<F2>\<F3>\<Esc>0", 'tx!') 5594 call assert_equal(['foobarbaz', 'foobar', 'foobarfoo'], b:matches->mapnew('v:val.word')) 5595 call assert_equal(-1, b:selected) 5596 call assert_equal('fooba', getline(4)) 5597 call feedkeys("Sfo\<C-N>\<C-N>\<BS>\<C-N>\<F2>\<F3>\<Esc>0", 'tx!') 5598 call assert_equal(['foobarbaz', 'foobar', 'foobarfoo'], b:matches->mapnew('v:val.word')) 5599 call assert_equal(0, b:selected) 5600 call assert_equal('foobarbaz', getline(4)) 5601 5602 " Test 7: Remove selection when menu contents change (PR #18265) 5603 %d 5604 call setline(1, ["foobar", "fodxyz", "fodabc"]) 5605 call feedkeys("Gofoo\<C-N>\<BS>\<BS>\<BS>\<BS>d\<F2>\<F3>\<Esc>0", 'tx!') 5606 call assert_equal(['fodabc', 'fodxyz'], b:matches->mapnew('v:val.word')) 5607 call assert_equal(-1, b:selected) 5608 5609 " Test 8: Ctrl_W / Ctrl_U (delete word/line) should restart autocompletion 5610 func! TestComplete(findstart, base) 5611 if a:findstart 5612 return col('.') - 1 5613 endif 5614 return ['fooze', 'faberge'] 5615 endfunc 5616 set omnifunc=TestComplete 5617 set complete+=o 5618 call feedkeys("Sprefix->fo\<F2>\<Esc>0", 'tx!') 5619 call assert_equal(['fodabc', 'fodxyz', 'foobar', 'fooze'], b:matches->mapnew('v:val.word')) 5620 call feedkeys("Sprefix->fo\<C-W>\<F2>\<Esc>0", 'tx!') 5621 call assert_equal(['fooze', 'faberge'], b:matches->mapnew('v:val.word')) 5622 call feedkeys("Sprefix->\<Esc>afo\<C-U>\<F2>\<Esc>0", 'tx!') 5623 call assert_equal(['fooze', 'faberge'], b:matches->mapnew('v:val.word')) 5624 5625 " Test 9: Trigger autocomplete immediately upon entering Insert mode 5626 " 'faberge' is filtered out because it doesn't start with the current prefix 5627 " 'foo'; non-prefix omnifunc matches are excluded from the PUM when leader 5628 " is NULL (compl_orig_text is used as a fallback filter). 5629 call feedkeys("Sprefix->foo\<Esc>a\<F2>\<Esc>0", 'tx!') 5630 call assert_equal(['foobar', 'fooze'], b:matches->mapnew('v:val.word')) 5631 call feedkeys("Sprefix->fooxx\<Esc>hcw\<F2>\<Esc>0", 'tx!') 5632 call assert_equal(['foobar', 'fooze'], b:matches->mapnew('v:val.word')) 5633 5634 bw! 5635 call Ntest_override("char_avail", 0) 5636 delfunc NonKeywordComplete 5637 delfunc TestComplete 5638 set autocomplete& omnifunc& complete& 5639 unlet g:CallCount 5640 endfunc 5641 5642 " Test autocomplete timing 5643 func Test_autocomplete_timer() 5644 5645 let g:CallCount = 0 5646 func! TestComplete(delay, check, refresh, findstart, base) 5647 if a:findstart 5648 return col('.') - 1 5649 else 5650 let g:CallCount += 1 5651 if a:delay 5652 sleep 310m " Exceed timeout 5653 endif 5654 if a:check 5655 while !complete_check() 5656 sleep 2m 5657 endwhile 5658 " return v:none " This should trigger after interrupted by timeout 5659 return [] 5660 endif 5661 let res = [["ab", "ac", "ad"], ["abb", "abc", "abd"], ["acb", "cc", "cd"]] 5662 if a:refresh 5663 return #{words: res[g:CallCount - 1], refresh: 'always'} 5664 endif 5665 return res[g:CallCount - 1] 5666 endif 5667 endfunc 5668 5669 " Trigger expansion even when another char is waiting in the typehead 5670 call Ntest_override("char_avail", 1) 5671 5672 new 5673 inoremap <buffer> <F2> <Cmd>let b:matches = complete_info(["matches"]).matches<CR> 5674 inoremap <buffer> <F3> <Cmd>let b:selected = complete_info(["selected"]).selected<CR> 5675 set autocomplete 5676 5677 call setline(1, ['abc', 'bcd', 'cde']) 5678 5679 " Test 1: When matches are found before timeout expires, it exits 5680 " 'collection' mode and transitions to 'filter' mode. 5681 set complete=.,Ffunction('TestComplete'\\,\ [0\\,\ 0\\,\ 0]) 5682 let g:CallCount = 0 5683 call feedkeys("Goa\<F2>\<Esc>0", 'tx!') 5684 call assert_equal(['abc', 'ab', 'ac', 'ad'], b:matches->mapnew('v:val.word')) 5685 call assert_equal(1, g:CallCount) 5686 5687 let g:CallCount = 0 5688 call feedkeys("Sab\<F2>\<Esc>0", 'tx!') 5689 call assert_equal(['abc', 'ab'], b:matches->mapnew('v:val.word')) 5690 call assert_equal(1, g:CallCount) 5691 5692 " Test 2: When timeout expires before all matches are found, it returns 5693 " with partial list but still transitions to 'filter' mode. 5694 set complete=.,Ffunction('TestComplete'\\,\ [1\\,\ 0\\,\ 0]) 5695 let g:CallCount = 0 5696 call feedkeys("Sab\<F2>\<Esc>0", 'tx!') 5697 call assert_equal(['abc', 'ab'], b:matches->mapnew('v:val.word')) 5698 call assert_equal(1, g:CallCount) 5699 5700 " Test 3: When interrupted by ^N before timeout expires, it remains in 5701 " 'collection' mode without transitioning. 5702 set complete=.,Ffunction('TestComplete'\\,\ [0\\,\ 1\\,\ 0]) 5703 let g:CallCount = 0 5704 call feedkeys("Sa\<C-N>b\<F2>\<Esc>0", 'tx!') 5705 call assert_equal(2, g:CallCount) 5706 5707 let g:CallCount = 0 5708 call feedkeys("Sa\<C-N>b\<C-N>c\<F2>\<Esc>0", 'tx!') 5709 call assert_equal(3, g:CallCount) 5710 5711 " Test 4: Simulate long running func that is stuck in complete_check() 5712 let g:CallCount = 0 5713 set complete=.,Ffunction('TestComplete'\\,\ [0\\,\ 1\\,\ 0]) 5714 call feedkeys("Sa\<F2>\<Esc>0", 'tx!') 5715 call assert_equal(['abc'], b:matches->mapnew('v:val.word')) 5716 call assert_equal(1, g:CallCount) 5717 5718 let g:CallCount = 0 5719 call feedkeys("Sab\<F2>\<Esc>0", 'tx!') 5720 call assert_equal(['abc'], b:matches->mapnew('v:val.word')) 5721 call assert_equal(1, g:CallCount) 5722 5723 " Test 5: refresh:always stays in 'collection' mode 5724 set complete=.,Ffunction('TestComplete'\\,\ [0\\,\ 0\\,\ 1]) 5725 let g:CallCount = 0 5726 call feedkeys("Sa\<F2>\<Esc>0", 'tx!') 5727 call assert_equal(['abc', 'ab', 'ac', 'ad'], b:matches->mapnew('v:val.word')) 5728 call assert_equal(1, g:CallCount) 5729 5730 let g:CallCount = 0 5731 call feedkeys("Sab\<F2>\<Esc>0", 'tx!') 5732 call assert_equal(['abc', 'abb', 'abd'], b:matches->mapnew('v:val.word')) 5733 call assert_equal(2, g:CallCount) 5734 5735 " Test 6: <c-n> and <c-p> navigate menu 5736 set complete=.,Ffunction('TestComplete'\\,\ [0\\,\ 0\\,\ 0]) 5737 let g:CallCount = 0 5738 call feedkeys("Sab\<c-n>\<F2>\<F3>\<Esc>0", 'tx!') 5739 call assert_equal(['abc', 'ab'], b:matches->mapnew('v:val.word')) 5740 call assert_equal(0, b:selected) 5741 call assert_equal(1, g:CallCount) 5742 call feedkeys("Sab\<c-n>\<c-n>\<F2>\<F3>\<Esc>0", 'tx!') 5743 call assert_equal(1, b:selected) 5744 call feedkeys("Sab\<c-n>\<c-p>\<F2>\<F3>\<Esc>0", 'tx!') 5745 call assert_equal(-1, b:selected) 5746 5747 " Test 7: Following 'cot' option values have no effect 5748 set completeopt=menu,menuone,noselect,noinsert,longest 5749 set complete=.,Ffunction('TestComplete'\\,\ [0\\,\ 0\\,\ 0]) 5750 let g:CallCount = 0 5751 call feedkeys("Sab\<c-n>\<F2>\<F3>\<Esc>0", 'tx!') 5752 call assert_equal(['abc', 'ab'], b:matches->mapnew('v:val.word')) 5753 call assert_equal(0, b:selected) 5754 call assert_equal(1, g:CallCount) 5755 call assert_equal('abc', getline(4)) 5756 set completeopt& 5757 5758 " Test 8: {func} completes after space, but not '.' 5759 set complete=.,Ffunction('TestComplete'\\,\ [0\\,\ 0\\,\ 0]) 5760 let g:CallCount = 0 5761 call feedkeys("S \<F2>\<F3>\<Esc>0", 'tx!') 5762 call assert_equal(['ab', 'ac', 'ad'], b:matches->mapnew('v:val.word')) 5763 call assert_equal(1, g:CallCount) 5764 set complete=. 5765 call feedkeys("S \<F2>\<F3>\<Esc>0", 'tx!') 5766 call assert_equal([], b:matches->mapnew('v:val.word')) 5767 5768 " Test 9: Matches nearest to the cursor are prioritized (by default) 5769 %d 5770 let g:CallCount = 0 5771 set complete=. 5772 call setline(1, ["fo", "foo", "foobar", "foobarbaz"]) 5773 call feedkeys("jof\<F2>\<Esc>0", 'tx!') 5774 call assert_equal(['foo', 'foobar', 'fo', 'foobarbaz'], b:matches->mapnew('v:val.word')) 5775 5776 bw! 5777 call Ntest_override("char_avail", 0) 5778 delfunc TestComplete 5779 set autocomplete& complete& 5780 unlet g:CallCount 5781 endfunc 5782 5783 func s:TestCompleteScriptLocal(findstart, base) 5784 if a:findstart 5785 return 1 5786 else 5787 return ['foo', 'foobar'] 5788 endif 5789 endfunc 5790 5791 " Issue 17869 5792 func Test_scriptlocal_autoload_func() 5793 let save_rtp = &rtp 5794 set rtp=Xruntime/some 5795 let dir = 'Xruntime/some/autoload' 5796 call mkdir(dir, 'pR') 5797 5798 let lines =<< trim END 5799 func compl#Func(findstart, base) 5800 if a:findstart 5801 return 1 5802 else 5803 return ['match', 'matchfoo'] 5804 endif 5805 endfunc 5806 END 5807 call writefile(lines, dir .. '/compl.vim') 5808 5809 call Ntest_override("char_avail", 1) 5810 new 5811 inoremap <buffer> <F2> <Cmd>let b:matches = complete_info(["matches"]).matches<CR> 5812 setlocal autocomplete 5813 5814 setlocal complete=.,Fcompl#Func 5815 call feedkeys("im\<F2>\<Esc>0", 'xt!') 5816 call assert_equal(['match', 'matchfoo'], b:matches->mapnew('v:val.word')) 5817 5818 setlocal complete=.,F<SID>TestCompleteScriptLocal 5819 call feedkeys("Sf\<F2>\<Esc>0", 'xt!') 5820 call assert_equal(['foo', 'foobar'], b:matches->mapnew('v:val.word')) 5821 5822 setlocal complete& 5823 bwipe! 5824 call Ntest_override("char_avail", 0) 5825 let &rtp = save_rtp 5826 endfunc 5827 5828 " Issue #17907 5829 func Test_omni_start_invalid_col() 5830 func OmniFunc(startcol, findstart, base) 5831 if a:findstart 5832 return a:startcol 5833 else 5834 return ['foo', 'foobar'] 5835 endif 5836 endfunc 5837 5838 new 5839 redraw " need this to prevent NULL dereference in Nvim 5840 set complete=o 5841 set omnifunc=funcref('OmniFunc',\ [-1]) 5842 call setline(1, ['baz ']) 5843 call feedkeys("A\<C-N>\<Esc>0", 'tx!') 5844 call assert_equal('baz foo', getline(1)) 5845 5846 set omnifunc=funcref('OmniFunc',\ [1000]) 5847 call setline(1, ['bar ']) 5848 call feedkeys("A\<C-N>\<Esc>0", 'tx!') 5849 call assert_equal('bar foo', getline(1)) 5850 bw! 5851 5852 delfunc OmniFunc 5853 set omnifunc& complete& 5854 endfunc 5855 5856 func Test_completetimeout_autocompletetimeout() 5857 func OmniFunc(findstart, base) 5858 if a:findstart 5859 return 1 5860 else 5861 return ['fooOmni'] 5862 endif 5863 endfunc 5864 5865 set omnifunc=OmniFunc 5866 call Ntest_override("char_avail", 1) 5867 inoremap <F2> <Cmd>let b:matches = complete_info(["matches"]).matches<CR> 5868 5869 call setline(1, ['foobar', 'foobarbaz']) 5870 new 5871 call setline(1, ['foo', 'foobaz', '']) 5872 set complete=.,o,w 5873 call feedkeys("G", 'xt!') 5874 5875 set autocomplete 5876 for tt in [1, 80, 1000, -1, 0] 5877 exec $'set autocompletetimeout={tt}' 5878 call feedkeys("\<Esc>Sf\<F2>\<Esc>0", 'xt!') 5879 call assert_equal(['foobaz', 'foo', 'fooOmni', 'foobar', 'foobarbaz'], b:matches->mapnew('v:val.word')) 5880 endfor 5881 set autocomplete& 5882 5883 for tt in [80, 1000, -1, 0] 5884 exec $'set completetimeout={tt}' 5885 call feedkeys("\<Esc>Sf\<C-N>\<F2>\<Esc>0", 'xt!') 5886 call assert_equal(['foo', 'foobaz', 'fooOmni', 'foobar', 'foobarbaz'], b:matches->mapnew('v:val.word')) 5887 endfor 5888 5889 " Clock does not have fine granularity, so checking 'elapsed time' is only 5890 " approximate. We can only test that some type of timeout is enforced. 5891 call setline(1, map(range(60000), '"foo" . v:val')) 5892 set completetimeout=1 5893 call feedkeys("Gof\<C-N>\<F2>\<Esc>0", 'xt!') 5894 let match_count = len(b:matches->mapnew('v:val.word')) 5895 call assert_true(match_count < 4000) 5896 5897 set completetimeout=1000 5898 call feedkeys("\<Esc>Sf\<C-N>\<F2>\<Esc>0", 'xt!') 5899 let match_count = len(b:matches->mapnew('v:val.word')) 5900 call assert_true(match_count > 2000) 5901 5902 set autocomplete 5903 set autocompletetimeout=81 5904 call feedkeys("\<Esc>Sf\<F2>\<Esc>0", 'xt!') 5905 let match_count = len(b:matches->mapnew('v:val.word')) 5906 call assert_true(match_count < 50000) 5907 5908 set complete& omnifunc& autocomplete& autocompletetimeout& completetimeout& 5909 bwipe! 5910 %d 5911 call Ntest_override("char_avail", 0) 5912 iunmap <F2> 5913 delfunc OmniFunc 5914 endfunc 5915 5916 func Test_autocompletedelay() 5917 CheckScreendump 5918 5919 let lines =<< trim [SCRIPT] 5920 call setline(1, ['foo', 'foobar', 'foobarbaz']) 5921 setlocal autocomplete 5922 [SCRIPT] 5923 call writefile(lines, 'XTest_autocomplete_delay', 'D') 5924 let buf = RunVimInTerminal('-S XTest_autocomplete_delay', {'rows': 10}) 5925 5926 call term_sendkeys(buf, "Gof") 5927 call VerifyScreenDump(buf, 'Test_autocompletedelay_1', {}) 5928 5929 call term_sendkeys(buf, "\<Esc>:set autocompletedelay=500\<CR>") 5930 call term_sendkeys(buf, "Sf") 5931 call VerifyScreenDump(buf, 'Test_autocompletedelay_2', {}) 5932 call term_sendkeys(buf, "o") 5933 call VerifyScreenDump(buf, 'Test_autocompletedelay_3', {}) 5934 sleep 500m 5935 call VerifyScreenDump(buf, 'Test_autocompletedelay_4', {}) 5936 call term_sendkeys(buf, "\<BS>") 5937 call VerifyScreenDump(buf, 'Test_autocompletedelay_5', {}) 5938 sleep 500m 5939 call VerifyScreenDump(buf, 'Test_autocompletedelay_6', {}) 5940 5941 " During delay wait, user can open menu using CTRL_N completion 5942 call term_sendkeys(buf, "\<Esc>:set completeopt=menuone\<CR>") 5943 call term_sendkeys(buf, "Sf\<C-N>") 5944 call VerifyScreenDump(buf, 'Test_autocompletedelay_7', {}) 5945 5946 " After the menu is open, ^N/^P and Up/Down should not delay 5947 call term_sendkeys(buf, "\<Esc>:set completeopt=menu noruler\<CR>") 5948 call term_sendkeys(buf, "\<Esc>Sf") 5949 sleep 500ms 5950 call term_sendkeys(buf, "\<C-N>") 5951 call VerifyScreenDump(buf, 'Test_autocompletedelay_8', {}) 5952 call term_sendkeys(buf, "\<Down>") 5953 call VerifyScreenDump(buf, 'Test_autocompletedelay_9', {}) 5954 5955 " When menu is not open Up/Down moves cursor to different line 5956 call term_sendkeys(buf, "\<Esc>Sf") 5957 call term_sendkeys(buf, "\<Up>") 5958 call VerifyScreenDump(buf, 'Test_autocompletedelay_10', {}) 5959 call term_sendkeys(buf, "\<Down>") 5960 call VerifyScreenDump(buf, 'Test_autocompletedelay_11', {}) 5961 5962 call term_sendkeys(buf, "\<esc>") 5963 call StopVimInTerminal(buf) 5964 endfunc 5965 5966 " Preinsert longest prefix when autocomplete 5967 func Test_autocomplete_longest() 5968 func GetLine() 5969 let g:line = getline('.') 5970 let g:col = col('.') 5971 let g:preinserted = preinserted() 5972 endfunc 5973 5974 call Ntest_override("char_avail", 1) 5975 new 5976 inoremap <buffer><F5> <C-R>=GetLine()<CR> 5977 set completeopt+=longest autocomplete 5978 call setline(1, ["foobar", "foozbar"]) 5979 call feedkeys("Go\<ESC>", 'tx') 5980 5981 func DoTest(typed, line, col) 5982 call feedkeys($"S{a:typed}\<F5>\<ESC>", 'tx') 5983 call assert_equal(a:line, g:line) 5984 call assert_equal(a:col, g:col) 5985 endfunc 5986 5987 call DoTest("f", 'foo', 2) 5988 call DoTest("fo", 'foo', 3) 5989 call DoTest("foo", 'foo', 4) 5990 call DoTest("foob", 'foobar', 5) 5991 call DoTest("foob\<BS>", 'foo', 4) 5992 call DoTest("foob\<BS>\<BS>", 'foo', 3) 5993 call DoTest("foo\<BS>", 'foo', 3) 5994 call DoTest("foo\<BS>\<BS>", 'foo', 2) 5995 call DoTest("foo\<BS>\<BS>\<BS>", '', 1) 5996 5997 call DoTest("foo \<BS>", 'foo', 4) 5998 call DoTest("foo \<BS>\<BS>", 'foo', 3) 5999 6000 call DoTest("f\<C-N>", 'foozbar', 8) 6001 call DoTest("f\<C-N>\<C-N>", 'foobar', 7) 6002 call DoTest("f\<C-N>\<C-N>\<C-N>", 'foo', 2) 6003 call DoTest("f\<C-N>\<C-N>\<C-N>\<C-N>", 'foozbar', 8) 6004 call DoTest("f\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 'foo', 2) 6005 call DoTest("f\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>\<C-P>", 'foobar', 7) 6006 call DoTest("f\<C-P>", 'foobar', 7) 6007 call DoTest("fo\<BS>\<C-P>", 'foobar', 7) 6008 6009 " <C-Y> to accept preinserted text 6010 inoremap <buffer><F6> <C-R>=pumvisible()<CR> 6011 call DoTest("zar\<C-O>0f", 'foozar', 2) 6012 call DoTest("zar\<C-O>0f\<C-Y>", 'foozar', 4) 6013 call DoTest("zar\<C-O>0f\<C-Y>\<F6>", 'foo1zar', 5) 6014 call DoTest("zar\<C-O>0f\<C-Y>\<BS>", 'foozar', 3) 6015 call DoTest("zar\<C-O>0f\<C-Y>\<BS>\<F6>", 'fo1zar', 4) 6016 6017 " Select items in menu 6018 call DoTest("zar\<C-O>0f\<C-N>", 'foozbarzar', 8) 6019 call DoTest("zar\<C-O>0f\<C-N>\<C-N>", 'foobarzar', 7) 6020 call DoTest("zar\<C-O>0f\<C-N>\<C-N>\<C-N>", 'foozar', 2) 6021 call DoTest("zar\<C-O>0f\<C-N>\<C-N>\<C-N>\<C-N>", 'foozbarzar', 8) 6022 call DoTest("zar\<C-O>0f\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 'foozar', 2) 6023 call DoTest("zar\<C-O>0f\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>\<C-P>", 'foobarzar', 7) 6024 call DoTest("zar\<C-O>0f\<C-P>", 'foobarzar', 7) 6025 6026 " Should not work with fuzzy 6027 set cot+=fuzzy 6028 call DoTest("f", 'f', 2) 6029 set cot-=fuzzy 6030 6031 " preinserted() 6032 call DoTest("f", 'foo', 2) 6033 call assert_equal(1, g:preinserted) 6034 call assert_equal(0, preinserted()) 6035 call DoTest("f\<BS>", '', 1) 6036 call assert_equal(0, g:preinserted) 6037 call DoTest("f ", 'f ', 3) 6038 call assert_equal(0, g:preinserted) 6039 call DoTest("foob", 'foobar', 5) 6040 call assert_equal(1, g:preinserted) 6041 call DoTest("foob\<BS>\<BS>x", 'fox', 4) 6042 call assert_equal(0, g:preinserted) 6043 6044 " Complete non-keyword 6045 func Omni(findstart, base) 6046 if a:findstart 6047 return 5 6048 else 6049 return ['xyz:'] 6050 endif 6051 endfunc 6052 set omnifunc=Omni 6053 set cpt+=o 6054 call DoTest("xyz:", "xyz:xyz:", 5) 6055 call DoTest("xyz:\<BS>\<BS>", "xyz:", 3) 6056 set omnifunc& cpt& 6057 delfunc Omni 6058 6059 " leader should match prefix of inserted word 6060 %delete 6061 set smartcase ignorecase 6062 call setline(1, ["FOO"]) 6063 call feedkeys($"Gof\<F5>\<Esc>", 'tx') 6064 call assert_equal('f', g:line) 6065 call feedkeys($"SF\<F5>\<Esc>", 'tx') 6066 call assert_equal('FOO', g:line) 6067 set smartcase& ignorecase& 6068 6069 " avoid repeating text that is already present after the cursor 6070 %delete 6071 call setline(1, ["foobarbaz", ""]) 6072 call feedkeys($"G", 'tx') 6073 call DoTest("baz\<C-O>0f", "foobarbaz", 2) 6074 call feedkeys($"Sxfoozar\<CR>\<Esc>", 'tx') 6075 call DoTest("baz\<C-O>0f", "foobarbaz", 2) 6076 call feedkeys($"Sfoozar\<CR>\<Esc>", 'tx') 6077 call DoTest("baz\<C-O>0f", "foobaz", 2) 6078 6079 " Verify that redo (dot) works 6080 %delete 6081 call setline(1, ["foobar", "foozbar", "foobaz", "changed", "change"]) 6082 call feedkeys($"/foo\<CR>", 'tx') 6083 call feedkeys($"cwch\<C-N>\<Esc>n.n.", 'tx') 6084 call assert_equal(repeat(['changed'], 3), getline(1, 3)) 6085 6086 " Select a match and delete up to text equal to another match 6087 %delete 6088 call setline(1, ["foobar", "foo"]) 6089 call feedkeys("Go\<ESC>", 'tx') 6090 call DoTest("f\<C-N>\<C-N>\<BS>\<BS>\<BS>\<BS>", 'foo', 3) 6091 6092 " Issue #18410: When both "preinsert" and "longest" are set, "preinsert" 6093 " takes precedence 6094 %delete 6095 set autocomplete completeopt+=longest,preinsert 6096 call setline(1, ['foobar', 'foofoo', 'foobaz', '']) 6097 call feedkeys("G", 'tx') 6098 call DoTest("f", 'foobar', 2) 6099 call assert_equal(1, g:preinserted) 6100 6101 " complete_info() 6102 %delete 6103 func GetPreinsert() 6104 let g:cinfo = complete_info(['preinserted_text']) 6105 return "" 6106 endfunc 6107 inoremap <buffer><F6> <C-R>=GetPreinsert()<CR> 6108 call setline(1, ["foo_bar_xyz", "foo__xyz"]) 6109 6110 set completeopt& completeopt+=preinsert 6111 call feedkeys("G4li\<F6>\<C-Y>", 'tx') 6112 call assert_equal("bar_xyz", g:cinfo.preinserted_text) 6113 6114 set completeopt& completeopt+=longest 6115 call feedkeys("Gof\<F6>\<ESC>", 'tx') 6116 call assert_equal("oo_bar_xyz", g:cinfo.preinserted_text) 6117 unlet g:cinfo 6118 delfunc GetPreinsert 6119 set completeopt& 6120 6121 " Undo 6122 %delete _ 6123 let &l:undolevels = &l:undolevels 6124 normal! ifoo 6125 let &l:undolevels = &l:undolevels 6126 normal! ofoobar 6127 let &l:undolevels = &l:undolevels 6128 normal! ofoobaz 6129 let &l:undolevels = &l:undolevels 6130 6131 func CheckUndo() 6132 let g:errmsg = '' 6133 call assert_equal(['foo', 'foobar', 'foobaz'], getline(1, '$')) 6134 undo 6135 call assert_equal(['foo', 'foobar'], getline(1, '$')) 6136 undo 6137 call assert_equal(['foo'], getline(1, '$')) 6138 undo 6139 call assert_equal([''], getline(1, '$')) 6140 later 3 6141 call assert_equal(['foo', 'foobar', 'foobaz'], getline(1, '$')) 6142 call assert_equal('', v:errmsg) 6143 endfunc 6144 6145 " Check that switching buffer with "longest" doesn't corrupt undo. 6146 new 6147 setlocal bufhidden=wipe 6148 inoremap <buffer> <F2> <Cmd>enew!<CR> 6149 call feedkeys("if\<F2>\<Esc>", 'tx') 6150 bwipe! 6151 call CheckUndo() 6152 6153 " Check that closing window with "longest" doesn't corrupt undo. 6154 new 6155 setlocal bufhidden=wipe 6156 inoremap <buffer> <F2> <Cmd>close!<CR> 6157 call feedkeys("if\<F2>\<Esc>", 'tx') 6158 call CheckUndo() 6159 6160 %delete _ 6161 delfunc CheckUndo 6162 6163 " Check that behavior of "longest" in manual completion is unchanged. 6164 for ac in [v:false, v:true] 6165 let &ac = ac 6166 set completeopt=menuone,longest 6167 call feedkeys("Ssign u\<C-X>\<C-V>", 'tx') 6168 call assert_equal('sign un', getline('.')) 6169 call feedkeys("Ssign u\<C-X>\<C-V>\<C-V>", 'tx') 6170 call assert_equal('sign undefine', getline('.')) 6171 call feedkeys("Ssign u\<C-X>\<C-V>\<C-V>\<C-V>", 'tx') 6172 call assert_equal('sign unplace', getline('.')) 6173 call feedkeys("Ssign u\<C-X>\<C-V>\<C-V>\<C-V>\<C-V>", 'tx') 6174 call assert_equal('sign u', getline('.')) 6175 %delete 6176 endfor 6177 6178 bw! 6179 set cot& autocomplete& 6180 delfunc GetLine 6181 delfunc DoTest 6182 call Ntest_override("char_avail", 0) 6183 endfunc 6184 6185 " Issue #18326 6186 func Test_fuzzy_select_item_when_acl() 6187 CheckScreendump 6188 let lines =<< trim [SCRIPT] 6189 call setline(1, ["v", "vi", "vim"]) 6190 set autocomplete completeopt=menuone,noinsert,fuzzy autocompletedelay=300 6191 [SCRIPT] 6192 call writefile(lines, 'XTest_autocomplete_delay', 'D') 6193 let buf = RunVimInTerminal('-S XTest_autocomplete_delay', {'rows': 10}) 6194 6195 call term_sendkeys(buf, "Govi") 6196 call VerifyScreenDump(buf, 'Test_fuzzy_autocompletedelay_1', {}) 6197 6198 call term_sendkeys(buf, "\<Esc>Sv") 6199 call VerifyScreenDump(buf, 'Test_fuzzy_autocompletedelay_2', {}) 6200 sleep 500m 6201 call term_sendkeys(buf, "i") 6202 call VerifyScreenDump(buf, 'Test_fuzzy_autocompletedelay_3', {}) 6203 6204 call term_sendkeys(buf, "\<esc>") 6205 call StopVimInTerminal(buf) 6206 endfunc 6207 6208 " Issue #18378: crash when fuzzy reorders items during refresh:always 6209 func Test_refresh_always_with_fuzzy() 6210 func ComplFunc1(findstart, base) 6211 if a:findstart 6212 return 1 6213 else 6214 return ['foo', 'foobar'] 6215 endif 6216 endfunc 6217 func ComplFunc2(findstart, base) 6218 if a:findstart 6219 return 1 6220 else 6221 return #{words: ['foo'], refresh: 'always'} 6222 endif 6223 endfunc 6224 set complete=.,FComplFunc1,FComplFunc2 6225 set autocomplete 6226 call Ntest_override("char_avail", 1) 6227 new 6228 call setline(1, ['fox']) 6229 exe "normal! Gofo" 6230 bw! 6231 delfunc ComplFunc1 6232 delfunc ComplFunc2 6233 set complete& autocomplete& 6234 call Ntest_override("char_avail", 0) 6235 endfunc 6236 6237 func Test_autocompletedelay_longest_preinsert() 6238 CheckScreendump 6239 let lines =<< trim [SCRIPT] 6240 call setline(1, ['autocomplete', 'autocomxxx']) 6241 set autocomplete completeopt+=longest autocompletedelay=500 6242 [SCRIPT] 6243 call writefile(lines, 'XTest_autocompletedelay', 'D') 6244 let buf = RunVimInTerminal('-S XTest_autocompletedelay', {'rows': 10}) 6245 6246 " No spurious characters when autocompletedelay is in effect 6247 call term_sendkeys(buf, "Goau") 6248 sleep 10m 6249 call term_sendkeys(buf, "toc") 6250 sleep 100m 6251 call VerifyScreenDump(buf, 'Test_autocompletedelay_longest_1', {}) 6252 sleep 500m 6253 call VerifyScreenDump(buf, 'Test_autocompletedelay_longest_2', {}) 6254 6255 " Deleting a char should still show longest text 6256 call term_sendkeys(buf, "\<Esc>Saut") 6257 sleep 10m 6258 call term_sendkeys(buf, "\<BS>") 6259 sleep 100m 6260 call VerifyScreenDump(buf, 'Test_autocompletedelay_longest_3', {}) 6261 sleep 500m 6262 call VerifyScreenDump(buf, 'Test_autocompletedelay_longest_4', {}) 6263 6264 " Preinsert 6265 call term_sendkeys(buf, "\<Esc>:set completeopt& completeopt+=preinsert\<CR>") 6266 6267 " Show preinserted text right away but display popup later 6268 call term_sendkeys(buf, "\<Esc>Sau") 6269 sleep 100m 6270 call VerifyScreenDump(buf, 'Test_autocompletedelay_preinsert_1', {}) 6271 sleep 500m 6272 call VerifyScreenDump(buf, 'Test_autocompletedelay_preinsert_2', {}) 6273 6274 call term_sendkeys(buf, "\<esc>") 6275 call StopVimInTerminal(buf) 6276 endfunc 6277 6278 " Issue 18493 6279 func Test_longest_preinsert_accept() 6280 call Ntest_override("char_avail", 1) 6281 new 6282 call setline(1, ['func1', 'xfunc', 'func2']) 6283 set completeopt+=noselect 6284 6285 call feedkeys("Gof\<C-N>\<Down>\<C-Y>", 'tx') 6286 call assert_equal('func1', getline('.')) 6287 6288 set completeopt+=longest autocomplete 6289 call feedkeys("Sf\<Down>\<C-Y>", 'tx') 6290 call assert_equal('func2', getline('.')) 6291 call feedkeys("Sf\<C-Y>", 'tx') 6292 call assert_equal('func', getline('.')) 6293 6294 set completeopt& autocomplete& 6295 bw! 6296 call Ntest_override("char_avail", 0) 6297 endfunc 6298 6299 " Issue 19114 6300 func Test_fuzzy_filenames_compl_autocompl() 6301 CheckScreendump 6302 let dir = 'Xtempdir' 6303 call mkdir(dir, 'pR') 6304 call writefile([], dir .. '/.name') 6305 call writefile([], dir .. '/name') 6306 call writefile([], dir .. '/test.vim') 6307 6308 let buf = RunVimInTerminal('', {'rows': 10}) 6309 call term_sendkeys(buf, ':call test_override("char_avail", 1)') 6310 call term_sendkeys(buf, "\<CR>") 6311 call term_sendkeys(buf, "iset ac cot=fuzzy,longest\<ESC>") 6312 call term_sendkeys(buf, ":source\<CR>") 6313 call term_sendkeys(buf, "o.na\<C-X>\<C-F>") " this used to cause segfault 6314 call TermWait(buf, 200) 6315 call VerifyScreenDump(buf, 'Test_fuzzy_filenames_compl_autocompl', {}) 6316 call StopVimInTerminal(buf) 6317 endfunc 6318 6319 " Issue 19130 6320 func Test_helptags_autocomplete_timeout() 6321 func! TestComplete(findstart, base) 6322 if a:findstart 6323 return col('.') - 1 6324 else 6325 sleep 310m " Exceed timeout 6326 return ["foo"] 6327 endif 6328 endfunc 6329 6330 call Ntest_override("char_avail", 1) 6331 new 6332 set autocomplete completeopt=fuzzy complete=.,FTestComplete 6333 call feedkeys("Goa\<Esc>0", 'tx!') 6334 call feedkeys(":h\<CR>", 'tx') " used to throw E149 exception 6335 call Ntest_override("char_avail", 0) 6336 set autocomplete& completeopt& complete& 6337 bw! 6338 endfunc 6339 6340 func Test_autocomplete_preinsert_null_leader() 6341 " Test that non-prefix matches from omnifunc are filtered when leader is NULL. 6342 " When autocomplete first fires, compl_leader is NULL. Previously the prefix 6343 " filter was bypassed, allowing non-prefix fuzzy matches to be incorrectly 6344 " shown in the PUM and preinserted. 6345 func NonPrefixOmni(findstart, base) 6346 if a:findstart 6347 return col(".") - 1 6348 endif 6349 " Return "key" (doesn't start with 'y') and "yellow" (starts with 'y'). 6350 " Simulates what a fuzzy omnifunc returns (e.g. vimcomplete#Complete with 6351 " wildoptions=fuzzy). 6352 return ["key", "yellow"] 6353 endfunc 6354 6355 call Ntest_override("char_avail", 1) 6356 new 6357 set omnifunc=NonPrefixOmni complete=o 6358 set completeopt=preinsert autocomplete 6359 6360 func GetState() 6361 let g:line = getline('.') 6362 let g:col = col('.') 6363 let g:matches = complete_info(['matches']).matches->mapnew('v:val.word') 6364 endfunc 6365 inoremap <buffer> <F5> <C-R>=GetState()<CR> 6366 6367 " Type 'y': "key" should be filtered out (doesn't start with 'y'), 6368 " "yellow" should be the only PUM entry and preinserted with cursor after 'y'. 6369 call feedkeys("iy\<F5>\<C-E>\<Esc>", 'tx') 6370 call assert_equal("yellow", g:line) 6371 call assert_equal(2, g:col) 6372 call assert_equal(['yellow'], g:matches) 6373 6374 bw! 6375 set omnifunc& complete& completeopt& autocomplete& 6376 call Ntest_override("char_avail", 0) 6377 delfunc NonPrefixOmni 6378 delfunc GetState 6379 endfunc 6380 6381 " Issue #19329: When register contents are inserted, remove preinserted text 6382 func Test_ins_register_preinsert_autocomplete() 6383 func TestOmni(findstart, base) 6384 if a:findstart 6385 return col(".") - 1 6386 endif 6387 return ["foo", "foobar"] 6388 endfunc 6389 6390 call Ntest_override("char_avail", 1) 6391 new 6392 set omnifunc=TestOmni complete^=o 6393 set completeopt=preinsert autocomplete 6394 6395 call feedkeys("ifoo \<C-R>\<C-P>=\"xyz\"\<CR>\<Esc>", 'tx') 6396 call assert_equal("foo xyz", getline('.')) 6397 bw! 6398 set omnifunc& complete& completeopt& autocomplete& 6399 call Ntest_override("char_avail", 0) 6400 delfunc TestOmni 6401 endfunc 6402 6403 " vim: shiftwidth=2 sts=2 expandtab nofoldenable