neovim

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

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 si”0s0
   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