neovim

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

test_findfile.vim (28193B)


      1 " Test findfile() and finddir()
      2 
      3 source check.vim
      4 source vim9.vim
      5 
      6 let s:files = [ 'Xfinddir1/foo',
      7      \         'Xfinddir1/bar',
      8      \         'Xfinddir1/Xdir2/foo',
      9      \         'Xfinddir1/Xdir2/foobar',
     10      \         'Xfinddir1/Xdir2/Xdir3/bar',
     11      \         'Xfinddir1/Xdir2/Xdir3/barfoo' ]
     12 
     13 func CreateFiles()
     14  call mkdir('Xfinddir1/Xdir2/Xdir3/Xdir2', 'p')
     15  for f in s:files
     16    call writefile([], f)
     17  endfor
     18 endfunc
     19 
     20 func CleanFiles()
     21  " Safer to delete each file even if it's more verbose
     22  " than doing a recursive delete('Xfinddir1', 'rf').
     23  for f in s:files
     24    call delete(f)
     25  endfor
     26 
     27  call delete('Xfinddir1/Xdir2/Xdir3/Xdir2', 'd')
     28  call delete('Xfinddir1/Xdir2/Xdir3', 'd')
     29  call delete('Xfinddir1/Xdir2', 'd')
     30  call delete('Xfinddir1', 'd')
     31 endfunc
     32 
     33 " Test findfile({name} [, {path} [, {count}]])
     34 func Test_findfile()
     35  let save_path = &path
     36  let save_shellslash = &shellslash
     37  let save_dir = getcwd()
     38  set shellslash
     39  call CreateFiles()
     40  cd Xfinddir1
     41  e Xdir2/foo
     42 
     43  " With ,, in path, findfile() searches in current directory.
     44  set path=,,
     45  call assert_equal('foo', findfile('foo'))
     46  call assert_equal('bar', findfile('bar'))
     47  call assert_equal('',    findfile('foobar'))
     48 
     49  " Directories should not be found (finddir() finds them).
     50  call assert_equal('', findfile('Xdir2'))
     51 
     52  " With . in 'path', findfile() searches relatively to current file.
     53  set path=.
     54  call assert_equal('Xdir2/foo',    findfile('foo'))
     55  call assert_equal('',             findfile('bar'))
     56  call assert_equal('Xdir2/foobar', 'foobar'->findfile())
     57 
     58  " Empty {path} 2nd argument is the same as no 2nd argument.
     59  call assert_equal('Xdir2/foo', findfile('foo', ''))
     60  call assert_equal('',          findfile('bar', ''))
     61 
     62  " Test with *
     63  call assert_equal('Xdir2/foo',       findfile('foo', '*'))
     64  call assert_equal('',                findfile('bar', '*'))
     65  call assert_equal('Xdir2/Xdir3/bar', findfile('bar', '*/*'))
     66  call assert_equal('Xdir2/Xdir3/bar', findfile('bar', 'Xdir2/*'))
     67  call assert_equal('Xdir2/Xdir3/bar', findfile('bar', 'Xdir*/Xdir3'))
     68  call assert_equal('Xdir2/Xdir3/bar', findfile('bar', '*2/*3'))
     69 
     70  " Test with **
     71  call assert_equal('bar',             findfile('bar', '**'))
     72  call assert_equal('Xdir2/Xdir3/bar', findfile('bar', '**/Xdir3'))
     73  call assert_equal('Xdir2/Xdir3/bar', findfile('bar', 'Xdir2/**'))
     74 
     75  call assert_equal('Xdir2/Xdir3/barfoo', findfile('barfoo', '**2'))
     76  call assert_equal('',                   findfile('barfoo', '**1'))
     77  call assert_equal('Xdir2/foobar',       findfile('foobar', '**1'))
     78 
     79  " Test with {count} 3rd argument.
     80  call assert_equal('bar',                      findfile('bar', '**', 0))
     81  call assert_equal('bar',                      findfile('bar', '**', 1))
     82  call assert_equal('Xdir2/Xdir3/bar',          findfile('bar', '**', 2))
     83  call assert_equal('',                         findfile('bar', '**', 3))
     84  call assert_equal(['bar', 'Xdir2/Xdir3/bar'], findfile('bar', '**', -1))
     85 
     86  " Test upwards search.
     87  cd Xdir2/Xdir3
     88  call assert_equal('bar',                findfile('bar', ';'))
     89  call assert_match('.*/Xfinddir1/Xdir2/foo', findfile('foo', ';'))
     90  call assert_match('.*/Xfinddir1/Xdir2/foo', findfile('foo', ';', 1))
     91  call assert_match('.*/Xfinddir1/foo',       findfile('foo', ';', 2))
     92  call assert_match('.*/Xfinddir1/foo',       findfile('foo', ';', 2))
     93  call assert_match('.*/Xfinddir1/Xdir2/foo', findfile('foo', 'Xdir2;', 1))
     94  call assert_equal('',                   findfile('foo', 'Xdir2;', 2))
     95 
     96  " List l should have at least 2 values (possibly more if foo file
     97  " happens to be found upwards above Xfinddir1).
     98  let l = findfile('foo', ';', -1)
     99  call assert_match('.*/Xfinddir1/Xdir2/foo', l[0])
    100  call assert_match('.*/Xfinddir1/foo',       l[1])
    101 
    102  " Test upwards search with stop-directory.
    103  cd Xdir2
    104  let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/Xdir3/', -1)
    105  call assert_equal(1, len(l))
    106  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    107  let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/Xdir3', -1)
    108  call assert_equal(1, len(l))
    109  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    110  let l = findfile('bar', ';../', -1)
    111  call assert_equal(1, len(l))
    112  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    113  let l = findfile('bar', ';..', -1)
    114  call assert_equal(1, len(l))
    115  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    116 
    117  let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/', -1)
    118  call assert_equal(1, len(l))
    119  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    120  let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2', -1)
    121  call assert_equal(1, len(l))
    122  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    123  let l = findfile('bar', ';../../', -1)
    124  call assert_equal(1, len(l))
    125  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    126  let l = findfile('bar', ';../..', -1)
    127  call assert_equal(1, len(l))
    128  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    129 
    130  let l = findfile('bar', ';' . save_dir . '/Xfinddir1/', -1)
    131  call assert_equal(2, len(l))
    132  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    133  call assert_match('.*/Xfinddir1/bar',             l[1])
    134  let l = findfile('bar', ';' . save_dir . '/Xfinddir1', -1)
    135  call assert_equal(2, len(l))
    136  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    137  call assert_match('.*/Xfinddir1/bar',             l[1])
    138  let l = findfile('bar', ';../../../', -1)
    139  call assert_equal(2, len(l))
    140  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    141  call assert_match('.*/Xfinddir1/bar',             l[1])
    142  let l = findfile('bar', ';../../..', -1)
    143  call assert_equal(2, len(l))
    144  call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
    145  call assert_match('.*/Xfinddir1/bar',             l[1])
    146 
    147  " Test combined downwards and upwards search from Xdir2/.
    148  cd ../..
    149  call assert_equal('Xdir3/bar',    findfile('bar', '**;', 1))
    150  call assert_match('.*/Xfinddir1/bar', findfile('bar', '**;', 2))
    151 
    152  bwipe!
    153  call chdir(save_dir)
    154  call CleanFiles()
    155  let &path = save_path
    156  let &shellslash = save_shellslash
    157 endfunc
    158 
    159 func Test_findfile_error()
    160  call assert_fails('call findfile([])', 'E730:')
    161  call assert_fails('call findfile("x", [])', 'E730:')
    162  call assert_fails('call findfile("x", "", [])', 'E745:')
    163  call assert_fails('call findfile("x", "**x")', 'E343:')
    164  call assert_fails('call findfile("x", repeat("x", 5000))', 'E854:')
    165 endfunc
    166 
    167 " Test finddir({name} [, {path} [, {count}]])
    168 func Test_finddir()
    169  let save_path = &path
    170  let save_shellslash = &shellslash
    171  let save_dir = getcwd()
    172  set path=,,
    173  set shellslash
    174  call CreateFiles()
    175  cd Xfinddir1
    176 
    177  call assert_equal('Xdir2', finddir('Xdir2'))
    178  call assert_equal('',      'Xdir3'->finddir())
    179 
    180  " Files should not be found (findfile() finds them).
    181  call assert_equal('', finddir('foo'))
    182 
    183  call assert_equal('Xdir2',       finddir('Xdir2', '**'))
    184  call assert_equal('Xdir2/Xdir3', finddir('Xdir3', '**'))
    185 
    186  call assert_equal('Xdir2',               finddir('Xdir2', '**', 1))
    187  call assert_equal('Xdir2/Xdir3/Xdir2',   finddir('Xdir2', '**', 2))
    188  call assert_equal(['Xdir2',
    189        \            'Xdir2/Xdir3/Xdir2'], finddir('Xdir2', '**', -1))
    190 
    191  call assert_equal('Xdir2',       finddir('Xdir2', '**1'))
    192  call assert_equal('Xdir2',       finddir('Xdir2', '**0'))
    193  call assert_equal('Xdir2/Xdir3', finddir('Xdir3', '**1'))
    194  call assert_equal('',            finddir('Xdir3', '**0'))
    195 
    196  " Test upwards dir search.
    197  cd Xdir2/Xdir3
    198  call assert_match('.*/Xfinddir1', finddir('Xfinddir1', ';'))
    199 
    200  " Test upwards search with stop-directory.
    201  call assert_match('.*/Xfinddir1', finddir('Xfinddir1', ';' . save_dir . '/'))
    202  call assert_equal('',         finddir('Xfinddir1', ';' . save_dir . '/Xfinddir1/'))
    203 
    204  " Test combined downwards and upwards dir search from Xdir2/.
    205  cd ..
    206  call assert_match('.*/Xfinddir1',       finddir('Xfinddir1', '**;', 1))
    207  call assert_equal('Xdir3/Xdir2',    finddir('Xdir2', '**;', 1))
    208  call assert_match('.*/Xfinddir1/Xdir2', finddir('Xdir2', '**;', 2))
    209  call assert_equal('Xdir3',          finddir('Xdir3', '**;', 1))
    210 
    211  call chdir(save_dir)
    212  call CleanFiles()
    213  let &path = save_path
    214  let &shellslash = save_shellslash
    215 endfunc
    216 
    217 func Test_finddir_error()
    218  call assert_fails('call finddir([])', 'E730:')
    219  call assert_fails('call finddir("x", [])', 'E730:')
    220  call assert_fails('call finddir("x", "", [])', 'E745:')
    221  call assert_fails('call finddir("x", "**x")', 'E343:')
    222  call assert_fails('call finddir("x", repeat("x", 5000))', 'E854:')
    223 endfunc
    224 
    225 func Test_findfile_with_suffixesadd()
    226  let save_path = &path
    227  let save_dir = getcwd()
    228  set path=,,
    229  call mkdir('Xfinddir1', 'pR')
    230  cd Xfinddir1
    231 
    232  call writefile([], 'foo.c', 'D')
    233  call writefile([], 'bar.cpp', 'D')
    234  call writefile([], 'baz.cc', 'D')
    235  call writefile([], 'foo.o', 'D')
    236  call writefile([], 'bar.o', 'D')
    237  call writefile([], 'baz.o', 'D')
    238 
    239  set suffixesadd=.c,.cpp
    240  call assert_equal('foo.c', findfile('foo'))
    241  call assert_equal('./foo.c', findfile('./foo'))
    242  call assert_equal('bar.cpp', findfile('bar'))
    243  call assert_equal('./bar.cpp', findfile('./bar'))
    244  call assert_equal('', findfile('baz'))
    245  call assert_equal('', findfile('./baz'))
    246  set suffixesadd+=.cc
    247  call assert_equal('baz.cc', findfile('baz'))
    248  call assert_equal('./baz.cc', findfile('./baz'))
    249 
    250  set suffixesadd&
    251  call chdir(save_dir)
    252  let &path = save_path
    253 endfunc
    254 
    255 " Test for the :find, :sfind and :tabfind commands
    256 func Test_find_cmd()
    257  new
    258  let save_path = &path
    259  let save_dir = getcwd()
    260  set path=.,./**/*
    261  call CreateFiles()
    262  cd Xfinddir1
    263 
    264  " Test for :find
    265  find foo
    266  call assert_equal('foo', expand('%:.'))
    267  2find foo
    268  call assert_equal('Xdir2/foo', expand('%:.'))
    269  call assert_fails('3find foo', 'E347:')
    270 
    271  " Test for :sfind
    272  enew
    273  sfind barfoo
    274  call assert_equal('Xdir2/Xdir3/barfoo', expand('%:.'))
    275  call assert_equal(3, winnr('$'))
    276  close
    277  call assert_fails('sfind baz', 'E345:')
    278  call assert_equal(2, winnr('$'))
    279 
    280  " Test for :tabfind
    281  enew
    282  tabfind foobar
    283  call assert_equal('Xdir2/foobar', expand('%:.'))
    284  call assert_equal(2, tabpagenr('$'))
    285  tabclose
    286  call assert_fails('tabfind baz', 'E345:')
    287  call assert_equal(1, tabpagenr('$'))
    288 
    289  call chdir(save_dir)
    290  exe 'cd ' . save_dir
    291  call CleanFiles()
    292  let &path = save_path
    293  close
    294 
    295  call assert_fails('find', 'E471:')
    296  call assert_fails('sfind', 'E471:')
    297  call assert_fails('tabfind', 'E471:')
    298 endfunc
    299 
    300 func Test_find_non_existing_path()
    301  new
    302  let save_path = &path
    303  let save_dir = getcwd()
    304  call mkdir('dir1/dir2', 'p')
    305  call writefile([], 'dir1/file.txt')
    306  call writefile([], 'dir1/dir2/base.txt')
    307  call chdir('dir1/dir2')
    308  e base.txt
    309  set path=../include
    310 
    311  call assert_fails(':find file.txt', 'E345:')
    312 
    313  call chdir(save_dir)
    314  bw!
    315  call delete('dir1/dir2/base.txt', 'rf')
    316  call delete('dir1/dir2', 'rf')
    317  call delete('dir1/file.txt', 'rf')
    318  call delete('dir1', 'rf')
    319  let &path = save_path
    320 endfunc
    321 
    322 " Test for 'findfunc'
    323 func Test_findfunc()
    324  CheckUnix
    325  call assert_equal('', &findfunc)
    326  call writefile(['aFile'], 'Xfindfunc1.c', 'D')
    327  call writefile(['bFile'], 'Xfindfunc2.c', 'D')
    328  call writefile(['cFile'], 'Xfindfunc3.c', 'D')
    329 
    330  " basic tests
    331  func FindFuncBasic(pat, cmdcomplete)
    332    let fnames = ['Xfindfunc1.c', 'Xfindfunc2.c', 'Xfindfunc3.c']
    333    return fnames->copy()->filter('v:val =~? a:pat')
    334  endfunc
    335 
    336  set findfunc=FindFuncBasic
    337  find Xfindfunc3
    338  call assert_match('Xfindfunc3.c', @%)
    339  bw!
    340  2find Xfind
    341  call assert_match('Xfindfunc2.c', @%)
    342  bw!
    343  call assert_fails('4find Xfind', 'E347: No more file "Xfind" found in path')
    344  call assert_fails('find foobar', 'E345: Can''t find file "foobar" in path')
    345 
    346  sfind Xfindfunc2.c
    347  call assert_match('Xfindfunc2.c', @%)
    348  call assert_equal(2, winnr('$'))
    349  %bw!
    350  call assert_fails('sfind foobar', 'E345: Can''t find file "foobar" in path')
    351 
    352  tabfind Xfindfunc3.c
    353  call assert_match('Xfindfunc3.c', @%)
    354  call assert_equal(2, tabpagenr())
    355  %bw!
    356  call assert_fails('tabfind foobar', 'E345: Can''t find file "foobar" in path')
    357 
    358  " Test garbage collection
    359  call test_garbagecollect_now()
    360  find Xfindfunc2
    361  call assert_match('Xfindfunc2.c', @%)
    362  bw!
    363  delfunc FindFuncBasic
    364  call test_garbagecollect_now()
    365  call assert_fails('find Xfindfunc2', 'E117: Unknown function: FindFuncBasic')
    366 
    367  " Buffer-local option
    368  func GlobalFindFunc(pat, cmdcomplete)
    369    return ['global']
    370  endfunc
    371  func LocalFindFunc(pat, cmdcomplete)
    372    return ['local']
    373  endfunc
    374  set findfunc=GlobalFindFunc
    375  new
    376  setlocal findfunc=LocalFindFunc
    377  find xxxx
    378  call assert_equal('local', @%)
    379  wincmd w
    380  find xxxx
    381  call assert_equal('global', @%)
    382  aboveleft new
    383  call assert_equal("GlobalFindFunc", &findfunc)
    384  wincmd k
    385  aboveleft new
    386  call assert_equal("GlobalFindFunc", &findfunc)
    387  %bw!
    388  delfunc GlobalFindFunc
    389  delfunc LocalFindFunc
    390 
    391  " Assign an expression
    392  set findfunc=[]
    393  call assert_fails('find xxxx', 'E117: Unknown function: []')
    394 
    395  " Error cases
    396 
    397  " Function that doesn't take any arguments
    398  func FindFuncNoArg()
    399  endfunc
    400  set findfunc=FindFuncNoArg
    401  call assert_fails('find Xfindfunc1.c', 'E118: Too many arguments for function: FindFuncNoArg')
    402  delfunc FindFuncNoArg
    403 
    404  " Syntax error in the function
    405  func FindFuncSyntaxError(pat, cmdcomplete)
    406    return l
    407  endfunc
    408  set findfunc=FindFuncSyntaxError
    409  call assert_fails('find Xfindfunc1.c', 'E121: Undefined variable: l')
    410  delfunc FindFuncSyntaxError
    411 
    412  " Find function throws an error
    413  func FindFuncWithThrow(pat, cmdcomplete)
    414    throw 'find error'
    415  endfunc
    416  set findfunc=FindFuncWithThrow
    417  call assert_fails('find Xfindfunc1.c', 'find error')
    418  delfunc FindFuncWithThrow
    419 
    420  " Try using a null function
    421  "call assert_fails('let &findfunc = test_null_function()', 'E129: Function name required')
    422 
    423  " Try to create a new window from the find function
    424  func FindFuncNewWindow(pat, cmdexpand)
    425    new
    426    return ["foo"]
    427  endfunc
    428  set findfunc=FindFuncNewWindow
    429  call assert_fails('find Xfindfunc1.c', 'E565: Not allowed to change text or change window')
    430  delfunc FindFuncNewWindow
    431 
    432  " Try to modify the current buffer from the find function
    433  func FindFuncModifyBuf(pat, cmdexpand)
    434    call setline(1, ['abc'])
    435    return ["foo"]
    436  endfunc
    437  set findfunc=FindFuncModifyBuf
    438  call assert_fails('find Xfindfunc1.c', 'E565: Not allowed to change text or change window')
    439  delfunc FindFuncModifyBuf
    440 
    441  " Return the wrong type from the function
    442  func FindFuncWrongRet(pat, cmdexpand)
    443    return 'foo'
    444  endfunc
    445  set findfunc=FindFuncWrongRet
    446  call assert_fails('find Xfindfunc1.c', "E1514: 'findfunc' did not return a List type")
    447  delfunc FindFuncWrongRet
    448 
    449  set findfunc&
    450 endfunc
    451 
    452 " Test for using a script-local function for 'findfunc'
    453 func Test_findfunc_scriptlocal_func()
    454  func! s:FindFuncScript(pat, cmdexpand)
    455    let g:FindFuncArg = a:pat
    456    return ['xxx']
    457  endfunc
    458 
    459  set findfunc=s:FindFuncScript
    460  call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
    461  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    462  new | only
    463  let g:FindFuncArg = ''
    464  find abc
    465  call assert_equal('abc', g:FindFuncArg)
    466  bw!
    467 
    468  set findfunc=<SID>FindFuncScript
    469  call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
    470  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    471  new | only
    472  let g:FindFuncArg = ''
    473  find abc
    474  call assert_equal('abc', g:FindFuncArg)
    475  bw!
    476 
    477  let &findfunc = 's:FindFuncScript'
    478  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    479  new | only
    480  let g:FindFuncArg = ''
    481  find abc
    482  call assert_equal('abc', g:FindFuncArg)
    483  bw!
    484 
    485  let &findfunc = '<SID>FindFuncScript'
    486  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    487  new | only
    488  let g:FindFuncArg = ''
    489  find abc
    490  call assert_equal('abc', g:FindFuncArg)
    491  bw!
    492 
    493  set findfunc=
    494  setglobal findfunc=s:FindFuncScript
    495  setlocal findfunc=
    496  call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
    497  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    498  call assert_equal('', &l:findfunc)
    499  new | only
    500  let g:FindFuncArg = ''
    501  find abc
    502  call assert_equal('abc', g:FindFuncArg)
    503  bw!
    504 
    505  new | only
    506  set findfunc=
    507  setglobal findfunc=
    508  setlocal findfunc=s:FindFuncScript
    509  call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
    510  call assert_equal(expand('<SID>') .. 'FindFuncScript', &l:findfunc)
    511  call assert_equal('', &g:findfunc)
    512  let g:FindFuncArg = ''
    513  find abc
    514  call assert_equal('abc', g:FindFuncArg)
    515  bw!
    516 
    517  new | only
    518  set findfunc=
    519  setlocal findfunc=NoSuchFunc
    520  setglobal findfunc=s:FindFuncScript
    521  call assert_equal('NoSuchFunc', &findfunc)
    522  call assert_equal('NoSuchFunc', &l:findfunc)
    523  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    524  new | only
    525  call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
    526  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    527  call assert_equal('', &l:findfunc)
    528  let g:FindFuncArg = ''
    529  find abc
    530  call assert_equal('abc', g:FindFuncArg)
    531  bw!
    532 
    533  new | only
    534  set findfunc=
    535  setlocal findfunc=NoSuchFunc
    536  set findfunc=s:FindFuncScript
    537  call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
    538  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    539  call assert_equal('', &l:findfunc)
    540  let g:FindFuncArg = ''
    541  find abc
    542  call assert_equal('abc', g:FindFuncArg)
    543  new | only
    544  call assert_equal(expand('<SID>') .. 'FindFuncScript', &findfunc)
    545  call assert_equal(expand('<SID>') .. 'FindFuncScript', &g:findfunc)
    546  call assert_equal('', &l:findfunc)
    547  let g:FindFuncArg = ''
    548  find abc
    549  call assert_equal('abc', g:FindFuncArg)
    550  bw!
    551 
    552  set findfunc=
    553  delfunc s:FindFuncScript
    554 endfunc
    555 
    556 " Test for expanding the argument to the :find command using 'findfunc'
    557 func Test_findfunc_expand_arg()
    558  let s:fnames = ['Xfindfunc1.c', 'Xfindfunc2.c', 'Xfindfunc3.c']
    559 
    560  " 'findfunc' that accepts a regular expression
    561  func FindFuncRegexp(pat, cmdcomplete)
    562    return s:fnames->copy()->filter('v:val =~? a:pat')
    563  endfunc
    564 
    565  " 'findfunc' that accepts a glob
    566  func FindFuncGlob(pat_arg, cmdcomplete)
    567    let pat = glob2regpat(a:cmdcomplete ? $'*{a:pat_arg}*' : a:pat_arg)
    568    return s:fnames->copy()->filter('v:val =~? pat')
    569  endfunc
    570 
    571  for regexp in [v:true, v:false]
    572    let &findfunc = regexp ? 'FindFuncRegexp' : 'FindFuncGlob'
    573 
    574    call feedkeys(":find \<Tab>\<C-B>\"\<CR>", "xt")
    575    call assert_equal('"find Xfindfunc1.c', @:)
    576 
    577    call feedkeys(":find Xfind\<Tab>\<Tab>\<C-B>\"\<CR>", "xt")
    578    call assert_equal('"find Xfindfunc2.c', @:)
    579 
    580    call assert_equal(s:fnames, getcompletion('find ', 'cmdline'))
    581    call assert_equal(s:fnames, getcompletion('find Xfind', 'cmdline'))
    582 
    583    let pat = regexp ? 'X.*1\.c' : 'X*1.c'
    584    call feedkeys($":find {pat}\<Tab>\<C-B>\"\<CR>", "xt")
    585    call assert_equal('"find Xfindfunc1.c', @:)
    586    call assert_equal(['Xfindfunc1.c'], getcompletion($'find {pat}', 'cmdline'))
    587 
    588    call feedkeys(":find 3\<Tab>\<C-B>\"\<CR>", "xt")
    589    call assert_equal('"find Xfindfunc3.c', @:)
    590    call assert_equal(['Xfindfunc3.c'], getcompletion($'find 3', 'cmdline'))
    591 
    592    call feedkeys(":find Xfind\<C-A>\<C-B>\"\<CR>", "xt")
    593    call assert_equal('"find Xfindfunc1.c Xfindfunc2.c Xfindfunc3.c', @:)
    594 
    595    call feedkeys(":find abc\<Tab>\<C-B>\"\<CR>", "xt")
    596    call assert_equal('"find abc', @:)
    597    call assert_equal([], getcompletion('find abc', 'cmdline'))
    598  endfor
    599 
    600  set findfunc&
    601  delfunc! FindFuncRegexp
    602  delfunc! FindFuncGlob
    603  unlet s:fnames
    604 endfunc
    605 
    606 " Test for different ways of setting the 'findfunc' option
    607 func Test_findfunc_callback()
    608  new
    609  func FindFunc1(pat, cmdexpand)
    610    let g:FindFunc1Args = [a:pat, a:cmdexpand]
    611    return ['findfunc1']
    612  endfunc
    613 
    614  let lines =<< trim END
    615    #" Test for using a function name
    616    LET &findfunc = 'g:FindFunc1'
    617    LET g:FindFunc1Args = []
    618    find abc1
    619    call assert_equal(['abc1', v:false], g:FindFunc1Args)
    620 
    621    #" Test for using a function()
    622    set findfunc=function('g:FindFunc1')
    623    LET g:FindFunc1Args = []
    624    find abc2
    625    call assert_equal(['abc2', v:false], g:FindFunc1Args)
    626 
    627    #" Using a funcref variable to set 'findfunc'
    628    VAR Fn = function('g:FindFunc1')
    629    LET &findfunc = Fn
    630    LET g:FindFunc1Args = []
    631    find abc3
    632    call assert_equal(['abc3', v:false], g:FindFunc1Args)
    633 
    634    #" Using a string(funcref_variable) to set 'findfunc'
    635    LET Fn = function('g:FindFunc1')
    636    LET &findfunc = string(Fn)
    637    LET g:FindFunc1Args = []
    638    find abc4
    639    call assert_equal(['abc4', v:false], g:FindFunc1Args)
    640 
    641    #" Test for using a funcref()
    642    set findfunc=funcref('g:FindFunc1')
    643    LET g:FindFunc1Args = []
    644    find abc5
    645    call assert_equal(['abc5', v:false], g:FindFunc1Args)
    646 
    647    #" Using a funcref variable to set 'findfunc'
    648    LET Fn = funcref('g:FindFunc1')
    649    LET &findfunc = Fn
    650    LET g:FindFunc1Args = []
    651    find abc6
    652    call assert_equal(['abc6', v:false], g:FindFunc1Args)
    653 
    654    #" Using a string(funcref_variable) to set 'findfunc'
    655    LET Fn = funcref('g:FindFunc1')
    656    LET &findfunc = string(Fn)
    657    LET g:FindFunc1Args = []
    658    find abc7
    659    call assert_equal(['abc7', v:false], g:FindFunc1Args)
    660 
    661    #" Test for using a lambda function using set
    662    VAR optval = "LSTART pat, cmdexpand LMIDDLE FindFunc1(pat, cmdexpand) LEND"
    663    LET optval = substitute(optval, ' ', '\\ ', 'g')
    664    exe "set findfunc=" .. optval
    665    LET g:FindFunc1Args = []
    666    find abc8
    667    call assert_equal(['abc8', v:false], g:FindFunc1Args)
    668 
    669    #" Test for using a lambda function using LET
    670    LET &findfunc = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND
    671    LET g:FindFunc1Args = []
    672    find abc9
    673    call assert_equal(['abc9', v:false], g:FindFunc1Args)
    674 
    675    #" Set 'findfunc' to a string(lambda expression)
    676    LET &findfunc = 'LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND'
    677    LET g:FindFunc1Args = []
    678    find abc10
    679    call assert_equal(['abc10', v:false], g:FindFunc1Args)
    680 
    681    #" Set 'findfunc' to a variable with a lambda expression
    682    VAR Lambda = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND
    683    LET &findfunc = Lambda
    684    LET g:FindFunc1Args = []
    685    find abc11
    686    call assert_equal(['abc11', v:false], g:FindFunc1Args)
    687 
    688    #" Set 'findfunc' to a string(variable with a lambda expression)
    689    LET Lambda = LSTART pat, _ LMIDDLE FindFunc1(pat, v:false) LEND
    690    LET &findfunc = string(Lambda)
    691    LET g:FindFunc1Args = []
    692    find abc12
    693    call assert_equal(['abc12', v:false], g:FindFunc1Args)
    694 
    695    #" Try to use 'findfunc' after the function is deleted
    696    func g:TmpFindFunc(pat, cmdexpand)
    697      let g:TmpFindFunc1Args = [a:pat, a:cmdexpand]
    698    endfunc
    699    LET &findfunc = function('g:TmpFindFunc')
    700    delfunc g:TmpFindFunc
    701    call test_garbagecollect_now()
    702    LET g:TmpFindFunc1Args = []
    703    call assert_fails('find abc13', 'E117:')
    704    call assert_equal([], g:TmpFindFunc1Args)
    705 
    706    #" Try to use a function with three arguments for 'findfunc'
    707    func g:TmpFindFunc2(x, y, z)
    708      let g:TmpFindFunc2Args = [a:x, a:y, a:z]
    709    endfunc
    710    set findfunc=TmpFindFunc2
    711    LET g:TmpFindFunc2Args = []
    712    call assert_fails('find abc14', 'E119:')
    713    call assert_equal([], g:TmpFindFunc2Args)
    714    delfunc TmpFindFunc2
    715 
    716    #" Try to use a function with zero arguments for 'findfunc'
    717    func g:TmpFindFunc3()
    718      let g:TmpFindFunc3Called = v:true
    719    endfunc
    720    set findfunc=TmpFindFunc3
    721    LET g:TmpFindFunc3Called = v:false
    722    call assert_fails('find abc15', 'E118:')
    723    call assert_equal(v:false, g:TmpFindFunc3Called)
    724    delfunc TmpFindFunc3
    725 
    726    #" Try to use a lambda function with three arguments for 'findfunc'
    727    LET &findfunc = LSTART a, b, c LMIDDLE FindFunc1(a, v:false) LEND
    728    LET g:FindFunc1Args = []
    729    call assert_fails('find abc16', 'E119:')
    730    call assert_equal([], g:FindFunc1Args)
    731 
    732    #" Test for clearing the 'findfunc' option
    733    set findfunc=''
    734    set findfunc&
    735    call assert_fails("set findfunc=function('abc')", "E700:")
    736    call assert_fails("set findfunc=funcref('abc')", "E700:")
    737 
    738    #" set 'findfunc' to a non-existing function
    739    LET &findfunc = function('g:FindFunc1')
    740    call assert_fails("set findfunc=function('NonExistingFunc')", 'E700:')
    741    call assert_fails("LET &findfunc = function('NonExistingFunc')", 'E700:')
    742    LET g:FindFunc1Args = []
    743    find abc17
    744    call assert_equal(['abc17', v:false], g:FindFunc1Args)
    745  END
    746  call CheckTransLegacySuccess(lines)
    747 
    748  " Test for using a script-local function name
    749  func s:FindFunc2(pat, cmdexpand)
    750    let g:FindFunc2Args = [a:pat, a:cmdexpand]
    751    return ['findfunc2']
    752  endfunc
    753  set findfunc=s:FindFunc2
    754  let g:FindFunc2Args = []
    755  find abc18
    756  call assert_equal(['abc18', v:false], g:FindFunc2Args)
    757 
    758  let &findfunc = 's:FindFunc2'
    759  let g:FindFunc2Args = []
    760  find abc19
    761  call assert_equal(['abc19', v:false], g:FindFunc2Args)
    762  delfunc s:FindFunc2
    763 
    764  " Using Vim9 lambda expression in legacy context should fail
    765  set findfunc=(pat,\ cmdexpand)\ =>\ FindFunc1(pat,\ v:false)
    766  let g:FindFunc1Args = []
    767  call assert_fails('find abc20', 'E117:')
    768  call assert_equal([], g:FindFunc1Args)
    769 
    770  " set 'findfunc' to a partial with dict.
    771  func SetFindFunc()
    772    let operator = {'execute': function('FindFuncExecute')}
    773    let &findfunc = operator.execute
    774  endfunc
    775  func FindFuncExecute(pat, cmdexpand) dict
    776    return ['findfuncexecute']
    777  endfunc
    778  call SetFindFunc()
    779  call test_garbagecollect_now()
    780  set findfunc=
    781  delfunc SetFindFunc
    782  delfunc FindFuncExecute
    783 
    784  func FindFunc2(pat, cmdexpand)
    785    let g:FindFunc2Args = [a:pat, a:cmdexpand]
    786    return ['findfunc2']
    787  endfunc
    788 
    789  " Vim9 tests
    790  let lines =<< trim END
    791    vim9script
    792 
    793    def g:Vim9findFunc(pat: string, cmdexpand: bool): list<string>
    794      g:FindFunc1Args = [pat, cmdexpand]
    795      return ['vim9findfunc']
    796    enddef
    797 
    798    # Test for using a def function with findfunc
    799    set findfunc=function('g:Vim9findFunc')
    800    g:FindFunc1Args = []
    801    find abc21
    802    assert_equal(['abc21', false], g:FindFunc1Args)
    803 
    804    # Test for using a global function name
    805    &findfunc = g:FindFunc2
    806    g:FindFunc2Args = []
    807    find abc22
    808    assert_equal(['abc22', false], g:FindFunc2Args)
    809    bw!
    810 
    811    # Test for using a script-local function name
    812    def LocalFindFunc(pat: string, cmdexpand: bool): list<string>
    813      g:LocalFindFuncArgs = [pat, cmdexpand]
    814      return ['localfindfunc']
    815    enddef
    816    &findfunc = LocalFindFunc
    817    g:LocalFindFuncArgs = []
    818    find abc23
    819    assert_equal(['abc23', false], g:LocalFindFuncArgs)
    820    bw!
    821  END
    822  call CheckScriptSuccess(lines)
    823 
    824  " setting 'findfunc' to a script local function outside of a script context
    825  " should fail
    826  let cleanup =<< trim END
    827    call writefile([execute('messages')], 'Xtest.out')
    828    qall
    829  END
    830  call writefile(cleanup, 'Xverify.vim', 'D')
    831  call RunVim([], [], "-c \"set findfunc=s:abc\" -S Xverify.vim")
    832  call assert_match('E81: Using <SID> not in a', readfile('Xtest.out')[0])
    833  call delete('Xtest.out')
    834 
    835  " cleanup
    836  set findfunc&
    837  delfunc FindFunc1
    838  delfunc FindFunc2
    839  unlet g:FindFunc1Args g:FindFunc2Args
    840  %bw!
    841 endfunc
    842 
    843 " Test using environment variables with spaces
    844 func Test_path_env_variable_with_whitespaces()
    845    let save_path = &path
    846    defer execute('let &path = save_path')
    847 
    848    let $testdir = 'Xpath with some whites'
    849    call mkdir($testdir, 'R')
    850 
    851    " Check direct usage yields the same result that autocomplete
    852    call feedkeys(':set path=$testdir' .. "\<C-A>\<CR>", 'xt')
    853    let auto_testpath = &path
    854    " include autocomplete suffix
    855    exe "set path=$testdir" .. "/"
    856    call assert_equal(auto_testpath, &path)
    857 
    858    " Check a file can be found using environment variables
    859    let expanded_test_path = expand('$testdir/test.txt')
    860    call writefile(['testing...'], expanded_test_path)
    861 
    862    " hinting an environment variable path
    863    call assert_equal(expanded_test_path, findfile('test.txt', $test_dir))
    864 
    865    " using 'path' option with an environment variable
    866    set path=$testdir
    867    call assert_equal(expanded_test_path, findfile('test.txt'))
    868 
    869    " using :find instead of findfile()
    870    find test.txt
    871    call assert_equal(expanded_test_path, expand('%:.'))
    872    enew
    873 endfunc
    874 
    875 " vim: shiftwidth=2 sts=2 expandtab