completion_spec.lua (79237B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 local Screen = require('test.functional.ui.screen') 4 5 local assert_alive = n.assert_alive 6 local clear, feed = n.clear, n.feed 7 local eval, eq, ok = n.eval, t.eq, t.ok 8 local source, expect = n.source, n.expect 9 local fn = n.fn 10 local command = n.command 11 local api = n.api 12 local poke_eventloop = n.poke_eventloop 13 local exec_lua = n.exec_lua 14 15 describe('completion', function() 16 local screen 17 18 before_each(function() 19 clear() 20 source([[ 21 set completeopt-=noselect 22 " Avoid tags completion (if running test locally). 23 set complete-=t 24 ]]) 25 screen = Screen.new(60, 8) 26 screen:add_extra_attr_ids { 27 [100] = { foreground = Screen.colors.Gray0, background = Screen.colors.Yellow }, 28 [101] = { background = Screen.colors.Gray0 }, 29 [102] = { foreground = Screen.colors.SeaGreen }, 30 } 31 end) 32 33 it('ctrl-x_ctrl-f completes Windows drive letter', function() 34 t.skip(not t.is_os('win'), 'N/A for non-Windows') 35 feed('iblablaC:/W<C-x><C-f>') 36 screen:expect { 37 any = [[C:\Windows\]], 38 } 39 end) 40 41 describe('v:completed_item', function() 42 it('is empty dict until completion', function() 43 eq({}, eval('v:completed_item')) 44 end) 45 it('is empty dict if the candidate is not inserted', function() 46 feed('ifoo<ESC>o<C-x><C-n>') 47 screen:expect([[ 48 foo | 49 foo^ | 50 {1:~ }|*5 51 {5:-- Keyword Local completion (^N^P) The only match} | 52 ]]) 53 feed('<C-e>') 54 screen:expect([[ 55 foo | 56 ^ | 57 {1:~ }|*5 58 {5:-- INSERT --} | 59 ]]) 60 feed('<ESC>') 61 eq({}, eval('v:completed_item')) 62 end) 63 it('returns expected dict in normal completion', function() 64 feed('ifoo<ESC>o<C-x><C-n>') 65 eq('foo', eval('getline(2)')) 66 eq( 67 { word = 'foo', abbr = '', menu = '', info = '', kind = '', user_data = '' }, 68 eval('v:completed_item') 69 ) 70 end) 71 it('is readonly', function() 72 screen:try_resize(80, 8) 73 feed('ifoo<ESC>o<C-x><C-n><ESC>') 74 t.matches('E46%: ', t.pcall_err(command, 'let v:completed_item.word = "bar"')) 75 t.matches('E46%: ', t.pcall_err(command, 'let v:completed_item.abbr = "bar"')) 76 t.matches('E46%: ', t.pcall_err(command, 'let v:completed_item.menu = "bar"')) 77 t.matches('E46%: ', t.pcall_err(command, 'let v:completed_item.info = "bar"')) 78 t.matches('E46%: ', t.pcall_err(command, 'let v:completed_item.kind = "bar"')) 79 t.matches('E46%: ', t.pcall_err(command, 'let v:completed_item.user_data = "bar"')) 80 end) 81 it('returns expected dict in omni completion', function() 82 source([[ 83 function! TestOmni(findstart, base) abort 84 return a:findstart ? 0 : [{'word': 'foo', 'abbr': 'bar', 85 \ 'menu': 'baz', 'info': 'foobar', 'kind': 'foobaz'}, 86 \ {'word': 'word', 'abbr': 'abbr', 'menu': 'menu', 87 \ 'info': 'info', 'kind': 'kind'}] 88 endfunction 89 setlocal omnifunc=TestOmni 90 ]]) 91 feed('i<C-x><C-o>') 92 eq('foo', eval('getline(1)')) 93 screen:expect([[ 94 foo^ | 95 {12:bar foobaz baz }{1: }| 96 {4:abbr kind menu }{1: }| 97 {1:~ }|*4 98 {5:-- Omni completion (^O^N^P) }{6:match 1 of 2} | 99 ]]) 100 eq({ 101 word = 'foo', 102 abbr = 'bar', 103 menu = 'baz', 104 info = 'foobar', 105 kind = 'foobaz', 106 user_data = '', 107 }, eval('v:completed_item')) 108 end) 109 end) 110 111 describe('completeopt', function() 112 before_each(function() 113 source([[ 114 function! TestComplete() abort 115 call complete(1, ['foo']) 116 return '' 117 endfunction 118 ]]) 119 end) 120 121 it('inserts the first candidate if default', function() 122 command('set completeopt+=menuone') 123 feed('ifoo<ESC>o') 124 screen:expect([[ 125 foo | 126 ^ | 127 {1:~ }|*5 128 {5:-- INSERT --} | 129 ]]) 130 feed('<C-x>') 131 -- the ^X prompt, only test this once 132 screen:expect([[ 133 foo | 134 ^ | 135 {1:~ }|*5 136 {5:-- ^X mode (^]^D^E^F^I^K^L^N^O^P^Rs^U^V^Y)} | 137 ]]) 138 feed('<C-n>') 139 screen:expect([[ 140 foo | 141 foo^ | 142 {12:foo }{1: }| 143 {1:~ }|*4 144 {5:-- Keyword Local completion (^N^P) The only match} | 145 ]]) 146 feed('bar<ESC>') 147 eq('foobar', eval('getline(2)')) 148 feed('o<C-r>=TestComplete()<CR>') 149 screen:expect([[ 150 foo | 151 foobar | 152 foo^ | 153 {12:foo }{1: }| 154 {1:~ }|*3 155 {5:-- INSERT --} | 156 ]]) 157 eq('foo', eval('getline(3)')) 158 end) 159 it('selects the first candidate if noinsert', function() 160 command('set completeopt+=menuone,noinsert') 161 feed('ifoo<ESC>o<C-x><C-n>') 162 screen:expect([[ 163 foo | 164 ^ | 165 {12:foo }{1: }| 166 {1:~ }|*4 167 {5:-- Keyword Local completion (^N^P) The only match} | 168 ]]) 169 feed('<C-y>') 170 screen:expect([[ 171 foo | 172 foo^ | 173 {1:~ }|*5 174 {5:-- INSERT --} | 175 ]]) 176 feed('<ESC>') 177 eq('foo', eval('getline(2)')) 178 feed('o<C-r>=TestComplete()<CR>') 179 screen:expect([[ 180 foo |*2 181 ^ | 182 {12:foo }{1: }| 183 {1:~ }|*3 184 {5:-- INSERT --} | 185 ]]) 186 feed('<C-y><ESC>') 187 eq('foo', eval('getline(3)')) 188 end) 189 it('does not insert the first candidate if noselect', function() 190 command('set completeopt+=menuone,noselect') 191 feed('ifoo<ESC>o<C-x><C-n>') 192 screen:expect([[ 193 foo | 194 ^ | 195 {4:foo }{1: }| 196 {1:~ }|*4 197 {5:-- Keyword Local completion (^N^P) }{19:Back at original} | 198 ]]) 199 feed('b') 200 screen:expect([[ 201 foo | 202 b^ | 203 {1:~ }|*5 204 {5:-- Keyword Local completion (^N^P) }{19:Back at original} | 205 ]]) 206 feed('ar<ESC>') 207 eq('bar', eval('getline(2)')) 208 feed('o<C-r>=TestComplete()<CR>') 209 screen:expect([[ 210 foo | 211 bar | 212 ^ | 213 {4:foo }{1: }| 214 {1:~ }|*3 215 {5:-- INSERT --} | 216 ]]) 217 feed('bar<ESC>') 218 eq('bar', eval('getline(3)')) 219 end) 220 it('does not select/insert the first candidate if noselect and noinsert', function() 221 command('set completeopt+=menuone,noselect,noinsert') 222 feed('ifoo<ESC>o<C-x><C-n>') 223 screen:expect([[ 224 foo | 225 ^ | 226 {4:foo }{1: }| 227 {1:~ }|*4 228 {5:-- Keyword Local completion (^N^P) }{19:Back at original} | 229 ]]) 230 feed('<ESC>') 231 screen:expect([[ 232 foo | 233 ^ | 234 {1:~ }|*5 235 | 236 ]]) 237 eq('', eval('getline(2)')) 238 feed('o<C-r>=TestComplete()<CR>') 239 screen:expect([[ 240 foo | 241 | 242 ^ | 243 {4:foo }{1: }| 244 {1:~ }|*3 245 {5:-- INSERT --} | 246 ]]) 247 feed('<ESC>') 248 screen:expect([[ 249 foo | 250 | 251 ^ | 252 {1:~ }|*4 253 | 254 ]]) 255 eq('', eval('getline(3)')) 256 end) 257 it('does not change modified state if noinsert', function() 258 command('set completeopt+=menuone,noinsert') 259 command('setlocal nomodified') 260 feed('i<C-r>=TestComplete()<CR><ESC>') 261 eq(0, eval('&l:modified')) 262 end) 263 it('does not change modified state if noselect', function() 264 command('set completeopt+=menuone,noselect') 265 command('setlocal nomodified') 266 feed('i<C-r>=TestComplete()<CR><ESC>') 267 eq(0, eval('&l:modified')) 268 end) 269 end) 270 271 describe('completeopt+=noinsert does not add blank undo items', function() 272 before_each(function() 273 source([[ 274 function! TestComplete() abort 275 call complete(1, ['foo', 'bar']) 276 return '' 277 endfunction 278 ]]) 279 command('set completeopt+=noselect,noinsert') 280 command('inoremap <right> <c-r>=TestComplete()<cr>') 281 end) 282 283 local tests = { 284 ['<up>, <down>, <cr>'] = { '<down><cr>', '<up><cr>' }, 285 ['<c-n>, <c-p>, <c-y>'] = { '<c-n><c-y>', '<c-p><c-y>' }, 286 } 287 288 for name, seq in pairs(tests) do 289 it('using ' .. name, function() 290 feed('iaaa<esc>') 291 feed('A<right>' .. seq[1] .. '<esc>') 292 feed('A<right><esc>A<right><esc>') 293 feed('A<cr>bbb<esc>') 294 feed('A<right>' .. seq[2] .. '<esc>') 295 feed('A<right><esc>A<right><esc>') 296 feed('A<cr>ccc<esc>') 297 feed('A<right>' .. seq[1] .. '<esc>') 298 feed('A<right><esc>A<right><esc>') 299 300 local expected = { 301 { 'foo', 'bar', 'foo' }, 302 { 'foo', 'bar', 'ccc' }, 303 { 'foo', 'bar' }, 304 { 'foo', 'bbb' }, 305 { 'foo' }, 306 { 'aaa' }, 307 { '' }, 308 } 309 310 for i = 1, #expected do 311 if i > 1 then 312 feed('u') 313 end 314 eq(expected[i], eval('getline(1, "$")')) 315 end 316 317 for i = #expected, 1, -1 do 318 if i < #expected then 319 feed('<c-r>') 320 end 321 eq(expected[i], eval('getline(1, "$")')) 322 end 323 end) 324 end 325 end) 326 327 describe('with refresh:always and noselect', function() 328 before_each(function() 329 source([[ 330 function! TestCompletion(findstart, base) abort 331 if a:findstart 332 let line = getline('.') 333 let start = col('.') - 1 334 while start > 0 && line[start - 1] =~ '\a' 335 let start -= 1 336 endwhile 337 return start 338 else 339 let ret = [] 340 for m in split("January February March April May June July August September October November December") 341 if m =~ a:base " match by regex 342 call add(ret, m) 343 endif 344 endfor 345 return {'words':ret, 'refresh':'always'} 346 endif 347 endfunction 348 349 set completeopt=menuone,noselect 350 set completefunc=TestCompletion 351 ]]) 352 end) 353 354 it('completes on each input char', function() 355 feed('i<C-x><C-u>') 356 screen:expect([[ 357 ^ | 358 {4:January }{101: }{1: }| 359 {4:February }{101: }{1: }| 360 {4:March }{101: }{1: }| 361 {4:April }{12: }{1: }| 362 {4:May }{12: }{1: }| 363 {4:June }{12: }{1: }| 364 {5:-- User defined completion (^U^N^P) }{19:Back at original} | 365 ]]) 366 feed('u') 367 screen:expect([[ 368 u^ | 369 {4:January }{1: }| 370 {4:February }{1: }| 371 {4:June }{1: }| 372 {4:July }{1: }| 373 {4:August }{1: }| 374 {1:~ }| 375 {5:-- User defined completion (^U^N^P) }{19:Back at original} | 376 ]]) 377 feed('g') 378 screen:expect([[ 379 ug^ | 380 {4:August }{1: }| 381 {1:~ }|*5 382 {5:-- User defined completion (^U^N^P) }{19:Back at original} | 383 ]]) 384 feed('<Down>') 385 screen:expect([[ 386 ug^ | 387 {12:August }{1: }| 388 {1:~ }|*5 389 {5:-- User defined completion (^U^N^P) The only match} | 390 ]]) 391 feed('<C-y>') 392 screen:expect([[ 393 August^ | 394 {1:~ }|*6 395 {5:-- INSERT --} | 396 ]]) 397 expect('August') 398 end) 399 400 it('repeats correctly after backspace #2674', function() 401 feed('o<C-x><C-u>Ja') 402 screen:expect([[ 403 | 404 Ja^ | 405 {4:January }{1: }| 406 {1:~ }|*4 407 {5:-- User defined completion (^U^N^P) }{19:Back at original} | 408 ]]) 409 feed('<BS>') 410 screen:expect([[ 411 | 412 J^ | 413 {4:January }{1: }| 414 {4:June }{1: }| 415 {4:July }{1: }| 416 {1:~ }|*2 417 {5:-- User defined completion (^U^N^P) }{19:Back at original} | 418 ]]) 419 feed('<C-n>') 420 screen:expect([[ 421 | 422 January^ | 423 {12:January }{1: }| 424 {4:June }{1: }| 425 {4:July }{1: }| 426 {1:~ }|*2 427 {5:-- User defined completion (^U^N^P) }{6:match 1 of 3} | 428 ]]) 429 feed('<C-n>') 430 screen:expect([[ 431 | 432 June^ | 433 {4:January }{1: }| 434 {12:June }{1: }| 435 {4:July }{1: }| 436 {1:~ }|*2 437 {5:-- User defined completion (^U^N^P) }{6:match 2 of 3} | 438 ]]) 439 feed('<Esc>') 440 screen:expect([[ 441 | 442 Jun^e | 443 {1:~ }|*5 444 | 445 ]]) 446 feed('.') 447 screen:expect([[ 448 | 449 June | 450 Jun^e | 451 {1:~ }|*4 452 | 453 ]]) 454 expect([[ 455 456 June 457 June]]) 458 end) 459 460 it('Enter inserts newline at original text after adding leader', function() 461 feed('iJ<C-x><C-u>') 462 poke_eventloop() 463 feed('u') 464 poke_eventloop() 465 feed('<CR>') 466 expect([[ 467 Ju 468 ]]) 469 feed('J<C-x><C-u>') 470 poke_eventloop() 471 feed('<CR>') 472 expect([[ 473 Ju 474 J 475 ]]) 476 end) 477 end) 478 479 describe('with noselect but not refresh:always', function() 480 before_each(function() 481 source([[ 482 function! TestCompletion(findstart, base) abort 483 if a:findstart 484 let line = getline('.') 485 let start = col('.') - 1 486 while start > 0 && line[start - 1] =~ '\a' 487 let start -= 1 488 endwhile 489 return start 490 else 491 let ret = [] 492 for m in split("January February March April May June July August September October November December") 493 if m =~ a:base " match by regex 494 call add(ret, m) 495 endif 496 endfor 497 return {'words':ret} 498 endif 499 endfunction 500 501 set completeopt=menuone,noselect 502 set completefunc=TestCompletion 503 ]]) 504 end) 505 506 it('Enter inserts newline at original text after adding leader', function() 507 feed('iJ<C-x><C-u>') 508 poke_eventloop() 509 feed('u') 510 poke_eventloop() 511 feed('<CR>') 512 expect([[ 513 Ju 514 ]]) 515 feed('<Esc>') 516 poke_eventloop() 517 -- The behavior should be the same when completion has been interrupted, 518 -- which can happen interactively if the completion function is slow. 519 feed('ggVGSJ<C-x><C-u>u<CR>') 520 expect([[ 521 Ju 522 ]]) 523 end) 524 end) 525 526 describe('with a lot of items', function() 527 before_each(function() 528 source([[ 529 function! TestComplete() abort 530 call complete(1, map(range(0,100), "string(v:val)")) 531 return '' 532 endfunction 533 ]]) 534 command('set completeopt=menuone,noselect') 535 end) 536 537 it('works', function() 538 feed('i<C-r>=TestComplete()<CR>') 539 screen:expect([[ 540 ^ | 541 {4:0 }{101: }{1: }| 542 {4:1 }{12: }{1: }| 543 {4:2 }{12: }{1: }| 544 {4:3 }{12: }{1: }| 545 {4:4 }{12: }{1: }| 546 {4:5 }{12: }{1: }| 547 {5:-- INSERT --} | 548 ]]) 549 feed('7') 550 screen:expect([[ 551 7^ | 552 {4:7 }{101: }{1: }| 553 {4:70 }{101: }{1: }| 554 {4:71 }{101: }{1: }| 555 {4:72 }{12: }{1: }| 556 {4:73 }{12: }{1: }| 557 {4:74 }{12: }{1: }| 558 {5:-- INSERT --} | 559 ]]) 560 feed('<c-n>') 561 screen:expect([[ 562 7^ | 563 {12:7 }{101: }{1: }| 564 {4:70 }{101: }{1: }| 565 {4:71 }{101: }{1: }| 566 {4:72 }{12: }{1: }| 567 {4:73 }{12: }{1: }| 568 {4:74 }{12: }{1: }| 569 {5:-- INSERT --} | 570 ]]) 571 feed('<c-n>') 572 screen:expect([[ 573 70^ | 574 {4:7 }{101: }{1: }| 575 {12:70 }{101: }{1: }| 576 {4:71 }{101: }{1: }| 577 {4:72 }{12: }{1: }| 578 {4:73 }{12: }{1: }| 579 {4:74 }{12: }{1: }| 580 {5:-- INSERT --} | 581 ]]) 582 end) 583 584 it('can be navigated with <PageDown>, <PageUp>', function() 585 feed('i<C-r>=TestComplete()<CR>') 586 screen:expect([[ 587 ^ | 588 {4:0 }{101: }{1: }| 589 {4:1 }{12: }{1: }| 590 {4:2 }{12: }{1: }| 591 {4:3 }{12: }{1: }| 592 {4:4 }{12: }{1: }| 593 {4:5 }{12: }{1: }| 594 {5:-- INSERT --} | 595 ]]) 596 feed('<PageDown>') 597 screen:expect([[ 598 ^ | 599 {4:0 }{101: }{1: }| 600 {4:1 }{12: }{1: }| 601 {4:2 }{12: }{1: }| 602 {12:3 }{1: }| 603 {4:4 }{12: }{1: }| 604 {4:5 }{12: }{1: }| 605 {5:-- INSERT --} | 606 ]]) 607 feed('<PageDown>') 608 screen:expect([[ 609 ^ | 610 {4:5 }{101: }{1: }| 611 {4:6 }{12: }{1: }| 612 {12:7 }{1: }| 613 {4:8 }{12: }{1: }| 614 {4:9 }{12: }{1: }| 615 {4:10 }{12: }{1: }| 616 {5:-- INSERT --} | 617 ]]) 618 feed('<Down>') 619 screen:expect([[ 620 ^ | 621 {4:5 }{101: }{1: }| 622 {4:6 }{12: }{1: }| 623 {4:7 }{12: }{1: }| 624 {12:8 }{1: }| 625 {4:9 }{12: }{1: }| 626 {4:10 }{12: }{1: }| 627 {5:-- INSERT --} | 628 ]]) 629 feed('<PageUp>') 630 screen:expect([[ 631 ^ | 632 {4:2 }{101: }{1: }| 633 {4:3 }{12: }{1: }| 634 {12:4 }{1: }| 635 {4:5 }{12: }{1: }| 636 {4:6 }{12: }{1: }| 637 {4:7 }{12: }{1: }| 638 {5:-- INSERT --} | 639 ]]) 640 feed('<PageUp>') -- stop on first item 641 screen:expect([[ 642 ^ | 643 {12:0 }{101: }{1: }| 644 {4:1 }{12: }{1: }| 645 {4:2 }{12: }{1: }| 646 {4:3 }{12: }{1: }| 647 {4:4 }{12: }{1: }| 648 {4:5 }{12: }{1: }| 649 {5:-- INSERT --} | 650 ]]) 651 feed('<PageUp>') -- when on first item, unselect 652 screen:expect([[ 653 ^ | 654 {4:0 }{101: }{1: }| 655 {4:1 }{12: }{1: }| 656 {4:2 }{12: }{1: }| 657 {4:3 }{12: }{1: }| 658 {4:4 }{12: }{1: }| 659 {4:5 }{12: }{1: }| 660 {5:-- INSERT --} | 661 ]]) 662 feed('<PageUp>') -- when unselected, select last item 663 screen:expect([[ 664 ^ | 665 {4:95 }{12: }{1: }| 666 {4:96 }{12: }{1: }| 667 {4:97 }{12: }{1: }| 668 {4:98 }{12: }{1: }| 669 {4:99 }{12: }{1: }| 670 {12:100 }{101: }{1: }| 671 {5:-- INSERT --} | 672 ]]) 673 feed('<PageUp>') 674 screen:expect([[ 675 ^ | 676 {4:94 }{12: }{1: }| 677 {4:95 }{12: }{1: }| 678 {12:96 }{1: }| 679 {4:97 }{12: }{1: }| 680 {4:98 }{12: }{1: }| 681 {4:99 }{101: }{1: }| 682 {5:-- INSERT --} | 683 ]]) 684 feed('<cr>') 685 screen:expect([[ 686 96^ | 687 {1:~ }|*6 688 {5:-- INSERT --} | 689 ]]) 690 end) 691 end) 692 693 it('does not indent until an item is selected #8345', function() 694 -- Indents on "ind", unindents on "unind". 695 source([[ 696 function! TestIndent() 697 let line = getline(v:lnum) 698 if (line =~ '^\s*ind') 699 return indent(v:lnum-1) + shiftwidth() 700 elseif (line =~ '^\s*unind') 701 return indent(v:lnum-1) - shiftwidth() 702 else 703 return indent(v:lnum-1) 704 endif 705 endfunction 706 set indentexpr=TestIndent() 707 set indentkeys=o,O,!^F,=ind,=unind 708 set completeopt+=menuone 709 ]]) 710 711 -- Give some words to complete. 712 feed('iinc uninc indent unindent<CR>') 713 714 -- Does not indent when "ind" is typed. 715 feed('in<C-X><C-N>') 716 -- Completion list is generated incorrectly if we send everything at once 717 -- via nvim_input(). So poke_eventloop() before sending <BS>. #8480 718 poke_eventloop() 719 feed('<BS>d') 720 721 screen:expect([[ 722 inc uninc indent unindent | 723 ind^ | 724 {12:indent }{1: }| 725 {1:~ }|*4 726 {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | 727 ]]) 728 729 -- Indents when the item is selected 730 feed('<C-Y>') 731 screen:expect([[ 732 inc uninc indent unindent | 733 indent^ | 734 {1:~ }|*5 735 {5:-- INSERT --} | 736 ]]) 737 -- Indents when completion is exited using ESC. 738 feed('<CR>in<C-N><BS>d<Esc>') 739 screen:expect([[ 740 inc uninc indent unindent | 741 indent | 742 in^d | 743 {1:~ }|*4 744 | 745 ]]) 746 -- Works for unindenting too. 747 feed('ounin<C-X><C-N>') 748 poke_eventloop() 749 feed('<BS>d') 750 screen:expect([[ 751 inc uninc indent unindent | 752 indent | 753 ind | 754 unind^ | 755 {1:~ }{12: unindent }{1: }| 756 {1:~ }|*2 757 {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | 758 ]]) 759 -- Works when going back and forth. 760 feed('<BS>c') 761 screen:expect([[ 762 inc uninc indent unindent | 763 indent | 764 ind | 765 uninc^ | 766 {1:~ }{12: uninc }{1: }| 767 {1:~ }|*2 768 {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | 769 ]]) 770 feed('<BS>d') 771 screen:expect([[ 772 inc uninc indent unindent | 773 indent | 774 ind | 775 unind^ | 776 {1:~ }{12: unindent }{1: }| 777 {1:~ }|*2 778 {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | 779 ]]) 780 feed('<C-N><C-N><C-Y><Esc>') 781 screen:expect([[ 782 inc uninc indent unindent | 783 indent | 784 ind | 785 uninden^t | 786 {1:~ }|*3 787 | 788 ]]) 789 end) 790 791 it('disables folding during completion', function() 792 command('set foldmethod=indent') 793 feed('i<Tab>foo<CR><Tab>bar<Esc>gg') 794 screen:expect([[ 795 ^foo | 796 bar | 797 {1:~ }|*5 798 | 799 ]]) 800 feed('A<C-x><C-l>') 801 screen:expect([[ 802 foo^ | 803 bar | 804 {1:~ }|*5 805 {5:-- Whole line completion (^L^N^P) }{9:Pattern not found} | 806 ]]) 807 eq(-1, eval('foldclosed(1)')) 808 end) 809 810 it('popupmenu is not interrupted by events', function() 811 command('set complete=.') 812 813 feed('ifoobar fooegg<cr>f<c-p>') 814 screen:expect([[ 815 foobar fooegg | 816 fooegg^ | 817 {4:foobar }{1: }| 818 {12:fooegg }{1: }| 819 {1:~ }|*3 820 {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | 821 ]]) 822 823 assert_alive() 824 -- popupmenu still visible 825 screen:expect { 826 grid = [[ 827 foobar fooegg | 828 fooegg^ | 829 {4:foobar }{1: }| 830 {12:fooegg }{1: }| 831 {1:~ }|*3 832 {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | 833 ]], 834 unchanged = true, 835 } 836 837 feed('<c-p>') 838 -- Didn't restart completion: old matches still used 839 screen:expect([[ 840 foobar fooegg | 841 foobar^ | 842 {12:foobar }{1: }| 843 {4:fooegg }{1: }| 844 {1:~ }|*3 845 {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | 846 ]]) 847 end) 848 849 describe('lua completion', function() 850 it('expands when there is only one match', function() 851 feed(':lua CURRENT_TESTING_VAR = 1<CR>') 852 feed(':lua CURRENT_TESTING_<TAB>') 853 screen:expect { 854 grid = [[ 855 | 856 {1:~ }|*6 857 :lua CURRENT_TESTING_VAR^ | 858 ]], 859 } 860 end) 861 862 it('expands when there is only one match', function() 863 feed(':lua CURRENT_TESTING_FOO = 1<CR>') 864 feed(':lua CURRENT_TESTING_BAR = 1<CR>') 865 feed(':lua CURRENT_TESTING_<TAB>') 866 screen:expect { 867 grid = [[ 868 | 869 {1:~ }|*5 870 {100:CURRENT_TESTING_BAR}{3: CURRENT_TESTING_FOO }| 871 :lua CURRENT_TESTING_BAR^ | 872 ]], 873 unchanged = true, 874 } 875 end) 876 877 it('prefix is not included in completion for cmdline mode', function() 878 feed(':lua math.a<Tab>') 879 screen:expect([[ 880 | 881 {1:~ }|*5 882 {100:abs}{3: acos asin atan atan2 }| 883 :lua math.abs^ | 884 ]]) 885 feed('<Tab>') 886 screen:expect([[ 887 | 888 {1:~ }|*5 889 {3:abs }{100:acos}{3: asin atan atan2 }| 890 :lua math.acos^ | 891 ]]) 892 end) 893 894 it('prefix is not included in completion for i_CTRL-X_CTRL-V #19623', function() 895 feed('ilua math.a<C-X><C-V>') 896 screen:expect([[ 897 lua math.abs^ | 898 {1:~ }{12: abs }{1: }| 899 {1:~ }{4: acos }{1: }| 900 {1:~ }{4: asin }{1: }| 901 {1:~ }{4: atan }{1: }| 902 {1:~ }{4: atan2 }{1: }| 903 {1:~ }| 904 {5:-- Command-line completion (^V^N^P) }{6:match 1 of 5} | 905 ]]) 906 feed('<C-V>') 907 screen:expect([[ 908 lua math.acos^ | 909 {1:~ }{4: abs }{1: }| 910 {1:~ }{12: acos }{1: }| 911 {1:~ }{4: asin }{1: }| 912 {1:~ }{4: atan }{1: }| 913 {1:~ }{4: atan2 }{1: }| 914 {1:~ }| 915 {5:-- Command-line completion (^V^N^P) }{6:match 2 of 5} | 916 ]]) 917 end) 918 919 it('works when cursor is in the middle of cmdline #29586', function() 920 feed(':lua math.a(); 1<Left><Left><Left><Left><Left><Tab>') 921 screen:expect([[ 922 | 923 {1:~ }|*5 924 {100:abs}{3: acos asin atan atan2 }| 925 :lua math.abs^(); 1 | 926 ]]) 927 end) 928 929 it('provides completion from `getcompletion()`', function() 930 eq({ 'vim' }, fn.getcompletion('vi', 'lua')) 931 eq({ 'api' }, fn.getcompletion('vim.ap', 'lua')) 932 eq({ 'tbl_filter' }, fn.getcompletion('vim.tbl_fil', 'lua')) 933 eq({ 'vim' }, fn.getcompletion('print(vi', 'lua')) 934 eq({ 'abs', 'acos', 'asin', 'atan', 'atan2' }, fn.getcompletion('math.a', 'lua')) 935 eq({ 'abs', 'acos', 'asin', 'atan', 'atan2' }, fn.getcompletion('lua math.a', 'cmdline')) 936 -- fuzzy completion is not supported, so the result should be the same 937 command('set wildoptions+=fuzzy') 938 eq({ 'vim' }, fn.getcompletion('vi', 'lua')) 939 end) 940 941 it('completes _defer_require() modules', function() 942 -- vim.lsp.c<tab> -> vim.lsp.completion 943 ok(vim.tbl_contains(fn.getcompletion('lua vim.lsp.c', 'cmdline'), 'completion')) 944 -- vim.lsp.completion.g<tab> -> vim.lsp.completion.get 945 ok(vim.tbl_contains(fn.getcompletion('lua vim.lsp.completion.g', 'cmdline'), 'get')) 946 end) 947 end) 948 949 it('cmdline completion supports various string options', function() 950 eq('auto', fn.getcompletion('set foldcolumn=', 'cmdline')[2]) 951 eq({ 'nosplit', 'split' }, fn.getcompletion('set inccommand=', 'cmdline')) 952 eq({ 'ver:3,hor:6', 'hor:', 'ver:' }, fn.getcompletion('set mousescroll=', 'cmdline')) 953 eq('BS', fn.getcompletion('set termpastefilter=', 'cmdline')[2]) 954 eq('SpecialKey', fn.getcompletion('set winhighlight=', 'cmdline')[1]) 955 eq('SpecialKey', fn.getcompletion('set winhighlight=NonText:', 'cmdline')[1]) 956 end) 957 958 it('cmdline completion for -complete does not contain spaces', function() 959 for _, str in ipairs(fn.getcompletion('command -complete=', 'cmdline')) do 960 ok(not str:find(' '), 'string without spaces', str) 961 end 962 end) 963 964 it('cmdline completion for :restart', function() 965 eq('qall', fn.getcompletion('restart +qa', 'cmdline')[1]) 966 eq('edit', fn.getcompletion('restart +qall ed', 'cmdline')[1]) 967 eq('edit', fn.getcompletion('restart ed', 'cmdline')[1]) 968 end) 969 970 describe('from the commandline window', function() 971 it('is cleared after CTRL-C', function() 972 feed('q:') 973 feed('ifoo faa fee f') 974 screen:expect([[ 975 | 976 {2:[No Name] }| 977 {1::}foo faa fee f^ | 978 {1:~ }|*3 979 {3:[Command Line] }| 980 {5:-- INSERT --} | 981 ]]) 982 feed('<c-x><c-n>') 983 screen:expect([[ 984 | 985 {2:[No Name] }| 986 {1::}foo faa fee foo^ | 987 {1:~ }{12: foo }{1: }| 988 {1:~ }{4: faa }{1: }| 989 {1:~ }{4: fee }{1: }| 990 {3:[Command Line] }| 991 {5:-- Keyword Local completion (^N^P) }{6:match 1 of 3} | 992 ]]) 993 feed('<c-c>') 994 screen:expect([[ 995 | 996 {2:[No Name] }| 997 {1::}foo faa fee foo | 998 {1:~ }|*3 999 {3:[Command Line] }| 1000 :foo faa fee foo^ | 1001 ]]) 1002 end) 1003 end) 1004 1005 describe('with numeric items', function() 1006 before_each(function() 1007 source([[ 1008 function! TestComplete() abort 1009 call complete(1, g:_complist) 1010 return '' 1011 endfunction 1012 ]]) 1013 api.nvim_set_option_value('completeopt', 'menuone,noselect', {}) 1014 api.nvim_set_var('_complist', { 1015 { 1016 word = 0, 1017 abbr = 1, 1018 menu = 2, 1019 kind = 3, 1020 info = 4, 1021 icase = 5, 1022 dup = 6, 1023 empty = 7, 1024 }, 1025 }) 1026 end) 1027 1028 it('shows correct variant as word', function() 1029 feed('i<C-r>=TestComplete()<CR>') 1030 screen:expect([[ 1031 ^ | 1032 {4:1 3 2 }{1: }| 1033 {1:~ }|*5 1034 {5:-- INSERT --} | 1035 ]]) 1036 end) 1037 end) 1038 1039 it("'ignorecase' 'infercase' CTRL-X CTRL-N #6451", function() 1040 command('set ignorecase infercase') 1041 command('edit runtime/doc/credits.txt') 1042 feed('oX<C-X><C-N>') 1043 screen:expect { 1044 grid = [[ 1045 *credits.txt* Nvim | 1046 Xvi^ | 1047 {12:Xvi }{101: } | 1048 {4:Xvim }{101: } | 1049 {4:X11 }{12: } NVIM REFERENCE MANUAL | 1050 {4:Xnull }{12: } | 1051 {4:Xoxomoon }{12: } | 1052 {5:-- Keyword Local completion (^N^P) }{6:match 1 of 10} | 1053 ]], 1054 } 1055 end) 1056 1057 it('CompleteChanged autocommand', function() 1058 api.nvim_buf_set_lines(0, 0, 1, false, { 'foo', 'bar', 'foobar', '' }) 1059 source([[ 1060 set complete=. completeopt=noinsert,noselect,menuone 1061 function! OnPumChange() 1062 let g:event = copy(v:event) 1063 let g:item = get(v:event, 'completed_item', {}) 1064 let g:word = get(g:item, 'word', v:null) 1065 endfunction 1066 autocmd! CompleteChanged * :call OnPumChange() 1067 call cursor(4, 1) 1068 ]]) 1069 1070 -- v:event.size should be set with ext_popupmenu #20646 1071 screen:set_option('ext_popupmenu', true) 1072 feed('Sf<C-N>') 1073 screen:expect({ 1074 grid = [[ 1075 foo | 1076 bar | 1077 foobar | 1078 f^ | 1079 {1:~ }|*3 1080 {5:-- Keyword completion (^N^P) }{19:Back at original} | 1081 ]], 1082 popupmenu = { 1083 anchor = { 1, 3, 0 }, 1084 items = { { 'foo', '', '', '' }, { 'foobar', '', '', '' } }, 1085 pos = -1, 1086 }, 1087 }) 1088 eq( 1089 { completed_item = {}, width = 0, height = 2, size = 2, col = 0, row = 4, scrollbar = false }, 1090 eval('g:event') 1091 ) 1092 feed('oob') 1093 screen:expect({ 1094 grid = [[ 1095 foo | 1096 bar | 1097 foobar | 1098 foob^ | 1099 {1:~ }|*3 1100 {5:-- Keyword completion (^N^P) }{19:Back at original} | 1101 ]], 1102 popupmenu = { 1103 anchor = { 1, 3, 0 }, 1104 items = { { 'foobar', '', '', '' } }, 1105 pos = -1, 1106 }, 1107 }) 1108 eq( 1109 { completed_item = {}, width = 0, height = 1, size = 1, col = 0, row = 4, scrollbar = false }, 1110 eval('g:event') 1111 ) 1112 feed('<Esc>') 1113 screen:set_option('ext_popupmenu', false) 1114 1115 feed('Sf<C-N>') 1116 screen:expect([[ 1117 foo | 1118 bar | 1119 foobar | 1120 f^ | 1121 {4:foo }{1: }| 1122 {4:foobar }{1: }| 1123 {1:~ }| 1124 {5:-- Keyword completion (^N^P) }{19:Back at original} | 1125 ]]) 1126 eq( 1127 { completed_item = {}, width = 15, height = 2, size = 2, col = 0, row = 4, scrollbar = false }, 1128 eval('g:event') 1129 ) 1130 feed('<C-N>') 1131 screen:expect([[ 1132 foo | 1133 bar | 1134 foobar | 1135 foo^ | 1136 {12:foo }{1: }| 1137 {4:foobar }{1: }| 1138 {1:~ }| 1139 {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | 1140 ]]) 1141 eq('foo', eval('g:word')) 1142 feed('<C-N>') 1143 screen:expect([[ 1144 foo | 1145 bar | 1146 foobar | 1147 foobar^ | 1148 {4:foo }{1: }| 1149 {12:foobar }{1: }| 1150 {1:~ }| 1151 {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | 1152 ]]) 1153 eq('foobar', eval('g:word')) 1154 feed('<up>') 1155 screen:expect([[ 1156 foo | 1157 bar | 1158 foobar | 1159 foobar^ | 1160 {12:foo }{1: }| 1161 {4:foobar }{1: }| 1162 {1:~ }| 1163 {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | 1164 ]]) 1165 eq('foo', eval('g:word')) 1166 feed('<down>') 1167 screen:expect([[ 1168 foo | 1169 bar | 1170 foobar | 1171 foobar^ | 1172 {4:foo }{1: }| 1173 {12:foobar }{1: }| 1174 {1:~ }| 1175 {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | 1176 ]]) 1177 eq('foobar', eval('g:word')) 1178 feed('<esc>') 1179 end) 1180 1181 it('is stopped by :stopinsert from timer #12976', function() 1182 screen:try_resize(32, 14) 1183 command([[call setline(1, ['hello', 'hullo', 'heeee', ''])]]) 1184 feed('Gah<c-x><c-n>') 1185 screen:expect([[ 1186 hello | 1187 hullo | 1188 heeee | 1189 hello^ | 1190 {12:hello }{1: }| 1191 {4:hullo }{1: }| 1192 {4:heeee }{1: }| 1193 {1:~ }|*6 1194 {5:-- }{6:match 1 of 3} | 1195 ]]) 1196 command([[call timer_start(100, { -> execute('stopinsert') })]]) 1197 vim.uv.sleep(200) 1198 feed('k') -- cursor should move up in Normal mode 1199 screen:expect([[ 1200 hello | 1201 hullo | 1202 heee^e | 1203 hello | 1204 {1:~ }|*9 1205 | 1206 ]]) 1207 end) 1208 1209 -- oldtest: Test_complete_changed_complete_info() 1210 it('no crash calling complete_info() in CompleteChanged', function() 1211 source([[ 1212 set completeopt=menuone 1213 autocmd CompleteChanged * call complete_info(['items']) 1214 call feedkeys("iii\<cr>\<c-p>") 1215 ]]) 1216 screen:expect([[ 1217 ii | 1218 ii^ | 1219 {12:ii }{1: }| 1220 {1:~ }|*4 1221 {5:-- Keyword completion (^N^P) The only match} | 1222 ]]) 1223 assert_alive() 1224 end) 1225 1226 it('no crash if text changed by first call to complete function #17489', function() 1227 source([[ 1228 func Complete(findstart, base) abort 1229 if a:findstart 1230 let col = col('.') 1231 call complete_add('#') 1232 return col - 1 1233 else 1234 return [] 1235 endif 1236 endfunc 1237 1238 set completeopt=longest 1239 set completefunc=Complete 1240 ]]) 1241 feed('ifoo#<C-X><C-U>') 1242 assert_alive() 1243 end) 1244 1245 it('no crash using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function() 1246 feed('icolorscheme NOSUCHCOLORSCHEME<C-X><C-V>') 1247 expect('colorscheme NOSUCHCOLORSCHEME') 1248 assert_alive() 1249 end) 1250 1251 it('complete with f flag #25598', function() 1252 screen:try_resize(20, 9) 1253 command('set complete+=f | edit foo | edit bar |edit foa |edit .hidden') 1254 feed('i<C-n>') 1255 screen:expect { 1256 grid = [[ 1257 foo^ | 1258 {12:foo }{1: }| 1259 {4:bar }{1: }| 1260 {4:foa }{1: }| 1261 {4:.hidden }{1: }| 1262 {1:~ }|*3 1263 {5:-- }{6:match 1 of 4} | 1264 ]], 1265 } 1266 feed('<Esc>ccf<C-n>') 1267 screen:expect { 1268 grid = [[ 1269 foo^ | 1270 {12:foo }{1: }| 1271 {4:foa }{1: }| 1272 {1:~ }|*5 1273 {5:-- }{6:match 1 of 2} | 1274 ]], 1275 } 1276 end) 1277 1278 it('restores extmarks if original text is restored #23653', function() 1279 screen:try_resize(screen._width, 4) 1280 command([[ 1281 call setline(1, ['aaaa']) 1282 let ns_id = nvim_create_namespace('extmark') 1283 let mark_id = nvim_buf_set_extmark(0, ns_id, 0, 0, { 'end_col':2, 'hl_group':'Error' }) 1284 let mark = nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 }) 1285 inoremap <C-x> <C-r>=Complete()<CR> 1286 function Complete() abort 1287 call complete(1, [{ 'word': 'aaaaa' }]) 1288 return '' 1289 endfunction 1290 ]]) 1291 feed('A<C-X><C-E><Esc>') 1292 eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) 1293 feed('A<C-N>') 1294 eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) 1295 feed('<Esc>0Yppia<Esc>ggI<C-N>') 1296 screen:expect([[ 1297 aaaa{9:^aa}aa | 1298 {12:aaaa } | 1299 {4:aaaaa } | 1300 {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | 1301 ]]) 1302 feed('<C-N><C-N><Esc>') 1303 eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) 1304 feed('A<C-N>') 1305 eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) 1306 feed('<C-N>') 1307 screen:expect([[ 1308 aaaaa^ | 1309 {4:aaaa } | 1310 {12:aaaaa } | 1311 {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | 1312 ]]) 1313 feed('<C-E>') 1314 screen:expect([[ 1315 {9:aa}aa^ | 1316 aaaa | 1317 aaaaa | 1318 {5:-- INSERT --} | 1319 ]]) 1320 -- Also when completion leader is changed #31384 1321 feed('<Esc>hi<C-N><C-P>a') 1322 screen:expect({ 1323 grid = [[ 1324 {9:aa}a^aa | 1325 {4:aaaa } | 1326 {4:aaaaa } | 1327 {5:-- Keyword completion (^N^P) }{19:Back at original} | 1328 ]], 1329 }) 1330 -- But still grows with end_right_gravity #31437 1331 command( 1332 "call nvim_buf_set_extmark(0, ns_id, 1, 0, { 'end_col':2, 'hl_group':'Error', 'end_right_gravity': 1 })" 1333 ) 1334 feed('<Esc>ji<C-N>a') 1335 screen:expect({ 1336 grid = [[ 1337 {9:aa}aaa | 1338 {9:aaa}^aa | 1339 aaaaa | 1340 {5:-- INSERT --} | 1341 ]], 1342 }) 1343 end) 1344 1345 describe('nvim__complete_set', function() 1346 it("fails when 'completeopt' does not include popup", function() 1347 exec_lua([[ 1348 function _G.omni_test(findstart, base) 1349 if findstart == 1 then 1350 return vim.fn.col('.') - 1 1351 end 1352 return { { word = 'one' } } 1353 end 1354 vim.api.nvim_create_autocmd('CompleteChanged', { 1355 callback = function() 1356 local ok, err = pcall(vim.api.nvim__complete_set, 0, { info = '1info' }) 1357 if not ok then 1358 vim.g.err_msg = err 1359 end 1360 end, 1361 }) 1362 vim.opt.completeopt = 'menu,menuone' 1363 vim.opt.omnifunc = 'v:lua.omni_test' 1364 ]]) 1365 feed('S<C-X><C-O>') 1366 eq('completeopt option does not include popup', api.nvim_get_var('err_msg')) 1367 end) 1368 end) 1369 1370 it([[does not include buffer from non-focusable window for 'complete' "w"]], function() 1371 local buf = api.nvim_create_buf(false, true) 1372 local cfg = { focusable = false, relative = 'win', bufpos = { 1, 0 }, width = 1, height = 1 } 1373 local win = api.nvim_open_win(buf, false, cfg) 1374 api.nvim_buf_set_lines(buf, 0, -1, false, { 'foo' }) 1375 feed('i<C-N>') 1376 screen:expect([[ 1377 ^ | 1378 {4:f}{1: }| 1379 {1:~ }|*5 1380 {5:-- Keyword completion (^N^P) }{9:Pattern not found} | 1381 ]]) 1382 api.nvim_win_set_config(win, { focusable = true }) 1383 feed('<Esc>i<C-N>') 1384 screen:expect([[ 1385 foo^ | 1386 {4:f}{1: }| 1387 {1:~ }|*5 1388 {5:-- Keyword completion (^N^P) The only match} | 1389 ]]) 1390 end) 1391 1392 -- oldtest: Test_shortmess() 1393 it('shortmess+=c turns off completion messages', function() 1394 command('set ruler') 1395 command([[call setline(1, ['hello', 'hullo', 'heee'])]]) 1396 feed('Goh<C-N>') 1397 screen:expect([[ 1398 hello | 1399 hullo | 1400 heee | 1401 hello^ | 1402 {12:hello }{1: }| 1403 {4:hullo }{1: }| 1404 {4:heee }{1: }| 1405 {5:-- Keyword completion (^N^P) }{6:match 1 of 3} | 1406 ]]) 1407 feed('<Esc>') 1408 command('set shm+=c') 1409 feed('Sh<C-N>') 1410 screen:expect([[ 1411 hello | 1412 hullo | 1413 heee | 1414 hello^ | 1415 {12:hello }{1: }| 1416 {4:hullo }{1: }| 1417 {4:heee }{1: }| 1418 {5:-- INSERT --} 4,6 All | 1419 ]]) 1420 end) 1421 1422 -- oldtest: Test_autocompletedelay() 1423 it("'autocompletedelay' option", function() 1424 screen:try_resize(60, 10) 1425 source([[ 1426 call setline(1, ['foo', 'foobar', 'foobarbaz']) 1427 setlocal autocomplete 1428 ]]) 1429 screen:expect([[ 1430 ^foo | 1431 foobar | 1432 foobarbaz | 1433 {1:~ }|*6 1434 | 1435 ]]) 1436 screen.timeout = 400 1437 1438 feed('Gof') 1439 screen:expect([[ 1440 foo | 1441 foobar | 1442 foobarbaz | 1443 f^ | 1444 {4:foobarbaz }{1: }| 1445 {4:foobar }{1: }| 1446 {4:foo }{1: }| 1447 {1:~ }|*2 1448 {5:-- INSERT --} | 1449 ]]) 1450 1451 feed('<Esc>') 1452 command('set autocompletedelay=500') 1453 feed('Sf') 1454 screen:expect([[ 1455 foo | 1456 foobar | 1457 foobarbaz | 1458 f^ | 1459 {1:~ }|*5 1460 {5:-- INSERT --} | 1461 ]]) 1462 feed('o') 1463 screen:expect([[ 1464 foo | 1465 foobar | 1466 foobarbaz | 1467 fo^ | 1468 {1:~ }|*5 1469 {5:-- INSERT --} | 1470 ]]) 1471 vim.uv.sleep(500) 1472 screen:expect([[ 1473 foo | 1474 foobar | 1475 foobarbaz | 1476 fo^ | 1477 {4:foobarbaz }{1: }| 1478 {4:foobar }{1: }| 1479 {4:foo }{1: }| 1480 {1:~ }|*2 1481 {5:-- INSERT --} | 1482 ]]) 1483 feed('<BS>') 1484 screen:expect([[ 1485 foo | 1486 foobar | 1487 foobarbaz | 1488 f^ | 1489 {1:~ }|*5 1490 {5:-- INSERT --} | 1491 ]]) 1492 vim.uv.sleep(500) 1493 screen:expect([[ 1494 foo | 1495 foobar | 1496 foobarbaz | 1497 f^ | 1498 {4:foobarbaz }{1: }| 1499 {4:foobar }{1: }| 1500 {4:foo }{1: }| 1501 {1:~ }|*2 1502 {5:-- INSERT --} | 1503 ]]) 1504 1505 -- During delay wait, user can open menu using CTRL_N completion 1506 feed('<Esc>') 1507 command('set completeopt=menuone') 1508 feed('Sf<C-N>') 1509 screen:expect([[ 1510 foo | 1511 foobar | 1512 foobarbaz | 1513 foo^ | 1514 {12:foo }{1: }| 1515 {4:foobar }{1: }| 1516 {4:foobarbaz }{1: }| 1517 {1:~ }|*2 1518 {5:-- Keyword completion (^N^P) }{6:match 1 of 3} | 1519 ]]) 1520 1521 -- After the menu is open, ^N/^P and Up/Down should not delay 1522 feed('<Esc>') 1523 command('set completeopt=menu') 1524 feed('Sf') 1525 screen:expect([[ 1526 foo | 1527 foobar | 1528 foobarbaz | 1529 f^ | 1530 {1:~ }|*5 1531 {5:-- INSERT --} | 1532 ]]) 1533 vim.uv.sleep(500) 1534 screen:expect([[ 1535 foo | 1536 foobar | 1537 foobarbaz | 1538 f^ | 1539 {4:foobarbaz }{1: }| 1540 {4:foobar }{1: }| 1541 {4:foo }{1: }| 1542 {1:~ }|*2 1543 {5:-- INSERT --} | 1544 ]]) 1545 feed('<C-N>') 1546 screen:expect([[ 1547 foo | 1548 foobar | 1549 foobarbaz | 1550 foobarbaz^ | 1551 {12:foobarbaz }{1: }| 1552 {4:foobar }{1: }| 1553 {4:foo }{1: }| 1554 {1:~ }|*2 1555 {5:-- INSERT --} | 1556 ]]) 1557 feed('<Down>') 1558 screen:expect([[ 1559 foo | 1560 foobar | 1561 foobarbaz | 1562 foobarbaz^ | 1563 {4:foobarbaz }{1: }| 1564 {12:foobar }{1: }| 1565 {4:foo }{1: }| 1566 {1:~ }|*2 1567 {5:-- INSERT --} | 1568 ]]) 1569 1570 -- When menu is not open Up/Down moves cursor to different line 1571 feed('<Esc>Sf') 1572 screen:expect([[ 1573 foo | 1574 foobar | 1575 foobarbaz | 1576 f^ | 1577 {1:~ }|*5 1578 {5:-- INSERT --} | 1579 ]]) 1580 feed('<Up>') 1581 screen:expect([[ 1582 foo | 1583 foobar | 1584 f^oobarbaz | 1585 f | 1586 {1:~ }|*5 1587 {5:-- INSERT --} | 1588 ]]) 1589 feed('<Down>') 1590 screen:expect([[ 1591 foo | 1592 foobar | 1593 foobarbaz | 1594 f^ | 1595 {1:~ }|*5 1596 {5:-- INSERT --} | 1597 ]]) 1598 1599 feed('<esc>') 1600 end) 1601 1602 -- oldtest: Test_fuzzy_select_item_when_acl() 1603 it([[first item isn't selected with "fuzzy" and 'acl']], function() 1604 screen:try_resize(60, 10) 1605 source([[ 1606 call setline(1, ["v", "vi", "vim"]) 1607 set autocomplete completeopt=menuone,noinsert,fuzzy autocompletedelay=300 1608 ]]) 1609 1610 feed('Govi') 1611 screen:expect([[ 1612 v | 1613 vi | 1614 vim | 1615 vi^ | 1616 {4:vi }{1: }| 1617 {4:vim }{1: }| 1618 {1:~ }|*3 1619 {5:-- INSERT --} | 1620 ]]) 1621 1622 feed('<Esc>Sv') 1623 screen:expect([[ 1624 v | 1625 vi | 1626 vim | 1627 v^ | 1628 {4:v }{1: }| 1629 {4:vi }{1: }| 1630 {4:vim }{1: }| 1631 {1:~ }|*2 1632 {5:-- INSERT --} | 1633 ]]) 1634 feed('i') 1635 screen:expect([[ 1636 v | 1637 vi | 1638 vim | 1639 vi^ | 1640 {4:vi }{1: }| 1641 {4:vim }{1: }| 1642 {1:~ }|*3 1643 {5:-- INSERT --} | 1644 ]]) 1645 end) 1646 1647 -- oldtest: Test_autocompletedelay_longest_preinsert() 1648 it("'autocompletedelay' with 'completeopt' longest/preinsert", function() 1649 source([[ 1650 call setline(1, ['autocomplete', 'autocomxxx']) 1651 set autocomplete completeopt+=longest autocompletedelay=500 1652 ]]) 1653 screen:expect([[ 1654 ^autocomplete | 1655 autocomxxx | 1656 {1:~ }|*5 1657 | 1658 ]]) 1659 screen.timeout = 400 1660 1661 -- No spurious characters when autocompletedelay is in effect 1662 feed('Goau') 1663 screen:expect([[ 1664 autocomplete | 1665 autocomxxx | 1666 au{102:^tocom} | 1667 {1:~ }|*4 1668 {5:-- INSERT --} | 1669 ]]) 1670 feed('toc') 1671 screen:expect([[ 1672 autocomplete | 1673 autocomxxx | 1674 autoc{102:^om} | 1675 {1:~ }|*4 1676 {5:-- INSERT --} | 1677 ]]) 1678 vim.uv.sleep(500) 1679 screen:expect([[ 1680 autocomplete | 1681 autocomxxx | 1682 autoc{102:^om} | 1683 {4:autocomxxx }{1: }| 1684 {4:autocomplete }{1: }| 1685 {1:~ }|*2 1686 {5:-- INSERT --} | 1687 ]]) 1688 1689 -- Deleting a char should still show longest text 1690 feed('<Esc>Saut') 1691 screen:expect([[ 1692 autocomplete | 1693 autocomxxx | 1694 aut{102:^ocom} | 1695 {1:~ }|*4 1696 {5:-- INSERT --} | 1697 ]]) 1698 feed('<BS>') 1699 screen:expect([[ 1700 autocomplete | 1701 autocomxxx | 1702 au{102:^tocom} | 1703 {1:~ }|*4 1704 {5:-- INSERT --} | 1705 ]]) 1706 vim.uv.sleep(500) 1707 screen:expect([[ 1708 autocomplete | 1709 autocomxxx | 1710 au{102:^tocom} | 1711 {4:autocomxxx }{1: }| 1712 {4:autocomplete }{1: }| 1713 {1:~ }|*2 1714 {5:-- INSERT --} | 1715 ]]) 1716 1717 -- Preinsert 1718 command('set completeopt& completeopt+=preinsert') 1719 1720 -- Show preinserted text right away but display popup later 1721 feed('<Esc>Sau') 1722 screen:expect([[ 1723 autocomplete | 1724 autocomxxx | 1725 au{102:^tocomplete} | 1726 {1:~ }|*4 1727 {5:-- INSERT --} | 1728 ]]) 1729 vim.uv.sleep(500) 1730 screen:expect([[ 1731 autocomplete | 1732 autocomxxx | 1733 au{102:^tocomplete} | 1734 {12:autocomplete }{1: }| 1735 {4:autocomxxx }{1: }| 1736 {1:~ }|*2 1737 {5:-- INSERT --} | 1738 ]]) 1739 end) 1740 1741 -- oldtest: Test_fuzzy_filenames_compl_autocompl() 1742 it('fuzzy file name does not crash with autocomplete', function() 1743 feed('iset ac cot=fuzzy,longest<Esc>') 1744 command('source') 1745 feed('o') 1746 poke_eventloop() 1747 feed('.') 1748 poke_eventloop() 1749 feed('n') 1750 poke_eventloop() 1751 feed('a') 1752 poke_eventloop() 1753 feed('<C-X><C-F>') -- this used to cause segfault 1754 screen:expect([[ 1755 set ac cot=fuzzy,longest | 1756 .na^ | 1757 {1:~ }|*5 1758 {5:-- File name completion (^F^N^P) }{9:Pattern not found} | 1759 ]]) 1760 end) 1761 end)