test_findfile.vim 26 KB

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