blob: 5c67dbf4f2ac100610609a62ec0f0514f81db329 [file] [log] [blame]
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001" Test for insert completion
2
Bram Moolenaar09dd2bb2019-12-14 18:42:15 +01003source screendump.vim
Bram Moolenaar50f91d22019-08-02 19:52:15 +02004source check.vim
Bram Moolenaar62aec932022-01-29 21:45:34 +00005import './vim9.vim' as v9
Bram Moolenaar15993ce2017-10-26 20:21:44 +02006
7" Test for insert expansion
8func Test_ins_complete()
Bram Moolenaarcf1ba352017-10-27 00:55:04 +02009 edit test_ins_complete.vim
Bram Moolenaarfb094e12017-11-05 20:59:28 +010010 " The files in the current directory interferes with the files
11 " used by this test. So use a separate directory for the test.
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +010012 call mkdir('Xcpldir')
13 cd Xcpldir
Bram Moolenaarfb094e12017-11-05 20:59:28 +010014
Bram Moolenaar15993ce2017-10-26 20:21:44 +020015 set ff=unix
16 call writefile(["test11\t36Gepeto\t/Tag/",
17 \ "asd\ttest11file\t36G",
Bram Moolenaar7dd5a782022-09-29 21:01:57 +010018 \ "Makefile\tto\trun"], 'Xtestfile', 'D')
Bram Moolenaar15993ce2017-10-26 20:21:44 +020019 call writefile(['', 'start of testfile',
20 \ 'ru',
21 \ 'run1',
22 \ 'run2',
23 \ 'STARTTEST',
24 \ 'ENDTEST',
Bram Moolenaar7dd5a782022-09-29 21:01:57 +010025 \ 'end of testfile'], 'Xtestdata', 'D')
Bram Moolenaar15993ce2017-10-26 20:21:44 +020026 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
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +000050 set cpt=.,\ ,w,i
Bram Moolenaar15993ce2017-10-26 20:21:44 +020051 " 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('.'))
Dominique Pelle923dce22021-11-21 11:36:04 +000054 " add-expands lines (it would end in an empty line if it didn't ignore
Bram Moolenaar15993ce2017-10-26 20:21:44 +020055 " 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
Yegappan Lakshmanan37079142022-01-08 10:38:48 +000074 " 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
Bram Moolenaar15993ce2017-10-26 20:21:44 +020079 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!
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200102 call delete('Xtest11.one')
103 call delete('Xtest11.two')
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200104 set cpt& cot& def& tags& tagbsearch& hidden&
Bram Moolenaarfb094e12017-11-05 20:59:28 +0100105 cd ..
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +0100106 call delete('Xcpldir', 'rf')
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200107endfunc
Bram Moolenaarffd99f72017-11-02 15:44:14 +0100108
Bram Moolenaar4b28ba32021-12-27 19:28:37 +0000109func Test_ins_complete_invalid_byte()
110 if has('unix') && executable('base64')
111 " this weird command was causing an illegal memory access
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100112 call writefile(['bm9ybTlvMDCAMM4Dbw4OGA4ODg=='], 'Xinvalid64', 'D')
Bram Moolenaar4b28ba32021-12-27 19:28:37 +0000113 call system('base64 -d Xinvalid64 > Xinvalid')
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100114 call writefile(['qa!'], 'Xexit', 'D')
Bram Moolenaar4b28ba32021-12-27 19:28:37 +0000115 call RunVim([], [], " -i NONE -n -X -Z -e -m -s -S Xinvalid -S Xexit")
Bram Moolenaar4b28ba32021-12-27 19:28:37 +0000116 call delete('Xinvalid')
Bram Moolenaar4b28ba32021-12-27 19:28:37 +0000117 endif
118endfunc
119
Bram Moolenaarffd99f72017-11-02 15:44:14 +0100120func Test_omni_dash()
121 func Omni(findstart, base)
122 if a:findstart
123 return 5
124 else
125 echom a:base
126 return ['-help', '-v']
127 endif
128 endfunc
129 set omnifunc=Omni
130 new
131 exe "normal Gofind -\<C-x>\<C-o>"
Bram Moolenaarcc233582020-12-12 13:32:07 +0100132 call assert_equal("find -help", getline('$'))
Girish Palyacbe53192025-04-14 22:13:15 +0200133 %d
134 set complete=o
135 exe "normal Gofind -\<C-n>"
136 " 'complete' inserts at 'iskeyword' boundary (so you get --help)
137 call assert_equal("find --help", getline('$'))
Bram Moolenaarffd99f72017-11-02 15:44:14 +0100138
139 bwipe!
140 delfunc Omni
Girish Palyacbe53192025-04-14 22:13:15 +0200141 set omnifunc= complete&
Bram Moolenaarffd99f72017-11-02 15:44:14 +0100142endfunc
Bram Moolenaar02ae9b42018-02-09 15:06:02 +0100143
LemonBoy9bcb9ca2022-05-26 15:23:26 +0100144func Test_omni_throw()
145 let g:CallCount = 0
146 func Omni(findstart, base)
147 let g:CallCount += 1
148 if a:findstart
149 throw "he he he"
150 endif
151 endfunc
152 set omnifunc=Omni
153 new
154 try
155 exe "normal ifoo\<C-x>\<C-o>"
156 call assert_false(v:true, 'command should have failed')
157 catch
158 call assert_exception('he he he')
159 call assert_equal(1, g:CallCount)
160 endtry
Girish Palyacbe53192025-04-14 22:13:15 +0200161 %d
162 set complete=o
163 let g:CallCount = 0
164 try
165 exe "normal ifoo\<C-n>"
166 call assert_false(v:true, 'command should have failed')
167 catch
168 call assert_exception('he he he')
169 call assert_equal(1, g:CallCount)
170 endtry
LemonBoy9bcb9ca2022-05-26 15:23:26 +0100171
172 bwipe!
173 delfunc Omni
174 unlet g:CallCount
Girish Palyacbe53192025-04-14 22:13:15 +0200175 set omnifunc= complete&
LemonBoy9bcb9ca2022-05-26 15:23:26 +0100176endfunc
177
Bram Moolenaarff34bee2021-07-25 20:27:06 +0200178func Test_omni_autoload()
179 let save_rtp = &rtp
180 set rtp=Xruntime/some
181 let dir = 'Xruntime/some/autoload'
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100182 call mkdir(dir, 'pR')
Bram Moolenaarff34bee2021-07-25 20:27:06 +0200183
184 let lines =<< trim END
185 vim9script
Bram Moolenaar6a058072022-01-30 18:56:35 +0000186 export def Func(findstart: bool, base: string): any
Bram Moolenaarff34bee2021-07-25 20:27:06 +0200187 if findstart
188 return 1
189 else
190 return ['match']
191 endif
192 enddef
193 {
194 eval 1 + 2
195 }
196 END
197 call writefile(lines, dir .. '/omni.vim')
198
199 new
Bram Moolenaar6a058072022-01-30 18:56:35 +0000200 setlocal omnifunc=omni#Func
Bram Moolenaarff34bee2021-07-25 20:27:06 +0200201 call feedkeys("i\<C-X>\<C-O>\<Esc>", 'xt')
202
203 bwipe!
Bram Moolenaarff34bee2021-07-25 20:27:06 +0200204 set omnifunc=
205 let &rtp = save_rtp
206endfunc
207
Bram Moolenaarffa96842018-06-12 22:05:14 +0200208func Test_completefunc_args()
209 let s:args = []
210 func! CompleteFunc(findstart, base)
211 let s:args += [[a:findstart, empty(a:base)]]
212 endfunc
213 new
214
215 set completefunc=CompleteFunc
216 call feedkeys("i\<C-X>\<C-U>\<Esc>", 'x')
Bram Moolenaar52d3aae2018-06-13 21:27:24 +0200217 call assert_equal([1, 1], s:args[0])
218 call assert_equal(0, s:args[1][0])
Bram Moolenaarffa96842018-06-12 22:05:14 +0200219 set completefunc=
220
221 let s:args = []
222 set omnifunc=CompleteFunc
223 call feedkeys("i\<C-X>\<C-O>\<Esc>", 'x')
Bram Moolenaar52d3aae2018-06-13 21:27:24 +0200224 call assert_equal([1, 1], s:args[0])
225 call assert_equal(0, s:args[1][0])
Bram Moolenaarffa96842018-06-12 22:05:14 +0200226 set omnifunc=
227
Girish Palyacbe53192025-04-14 22:13:15 +0200228 set complete=fCompleteFunc
229 call feedkeys("i\<C-N>\<Esc>", 'x')
230 call assert_equal([1, 1], s:args[0])
231 call assert_equal(0, s:args[1][0])
232 set complete=o
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&
237
Bram Moolenaarffa96842018-06-12 22:05:14 +0200238 bwipe!
239 unlet s:args
240 delfunc CompleteFunc
241endfunc
242
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100243func s:CompleteDone_CompleteFuncNone( findstart, base )
244 if a:findstart
245 return 0
246 endif
247
248 return v:none
249endfunc
250
Bram Moolenaar1e115362019-01-09 23:01:02 +0100251func s:CompleteDone_CompleteFuncDict( findstart, base )
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100252 if a:findstart
253 return 0
254 endif
255
256 return {
Bram Moolenaar08928322020-01-04 14:32:48 +0100257 \ 'words': [
258 \ {
259 \ 'word': 'aword',
260 \ 'abbr': 'wrd',
261 \ 'menu': 'extra text',
262 \ 'info': 'words are cool',
263 \ 'kind': 'W',
zeertzjq4cd45f12022-12-15 13:48:30 +0000264 \ 'user_data': ['one', 'two']
Bram Moolenaar08928322020-01-04 14:32:48 +0100265 \ }
266 \ ]
267 \ }
Bram Moolenaar1e115362019-01-09 23:01:02 +0100268endfunc
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100269
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100270func s:CompleteDone_CheckCompletedItemNone()
271 let s:called_completedone = 1
272endfunc
273
Bram Moolenaar3f169ce2020-01-26 22:43:31 +0100274func s:CompleteDone_CheckCompletedItemDict(pre)
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100275 call assert_equal( 'aword', v:completed_item[ 'word' ] )
276 call assert_equal( 'wrd', v:completed_item[ 'abbr' ] )
277 call assert_equal( 'extra text', v:completed_item[ 'menu' ] )
278 call assert_equal( 'words are cool', v:completed_item[ 'info' ] )
279 call assert_equal( 'W', v:completed_item[ 'kind' ] )
zeertzjq4cd45f12022-12-15 13:48:30 +0000280 call assert_equal( ['one', 'two'], v:completed_item[ 'user_data' ] )
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100281
Bram Moolenaar3f169ce2020-01-26 22:43:31 +0100282 if a:pre
Girish Palyacbe53192025-04-14 22:13:15 +0200283 call assert_equal(a:pre == 1 ? 'function' : 'keyword', complete_info().mode)
Bram Moolenaar3f169ce2020-01-26 22:43:31 +0100284 endif
Bram Moolenaar17e04782020-01-17 18:58:59 +0100285
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100286 let s:called_completedone = 1
Bram Moolenaar1e115362019-01-09 23:01:02 +0100287endfunc
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100288
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100289func Test_CompleteDoneNone()
290 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemNone()
Bram Moolenaar9845f362019-04-08 18:59:54 +0200291 let oldline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '')
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100292
293 set completefunc=<SID>CompleteDone_CompleteFuncNone
294 execute "normal a\<C-X>\<C-U>\<C-Y>"
295 set completefunc&
Bram Moolenaar9845f362019-04-08 18:59:54 +0200296 let newline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '')
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100297
298 call assert_true(s:called_completedone)
Bram Moolenaar9845f362019-04-08 18:59:54 +0200299 call assert_equal(oldline, newline)
Girish Palyacbe53192025-04-14 22:13:15 +0200300 let s:called_completedone = 0
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100301
Girish Palyacbe53192025-04-14 22:13:15 +0200302 set complete=f<SID>CompleteDone_CompleteFuncNone
303 execute "normal a\<C-N>\<C-Y>"
304 set complete&
305 let newline = join(map(range(&columns), 'nr2char(screenchar(&lines-1, v:val+1))'), '')
306
307 call assert_true(s:called_completedone)
308 call assert_equal(oldline, newline)
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100309 let s:called_completedone = 0
310 au! CompleteDone
311endfunc
312
glepnir1c5a1202024-12-04 20:27:34 +0100313func Test_CompleteDone_vevent_keys()
314 func OnDone()
315 let g:complete_word = get(v:event, 'complete_word', v:null)
316 let g:complete_type = get(v:event, 'complete_type', v:null)
317 endfunction
318
319 autocmd CompleteDone * :call OnDone()
320
321 func CompleteFunc(findstart, base)
322 if a:findstart
323 return col(".")
324 endif
325 return [#{word: "foo"}, #{word: "bar"}]
326 endfunc
327 set omnifunc=CompleteFunc
328 set completefunc=CompleteFunc
Girish Palyacbe53192025-04-14 22:13:15 +0200329 set complete=.,fCompleteFunc
glepnir1c5a1202024-12-04 20:27:34 +0100330 set completeopt+=menuone
331
332 new
333 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'tx')
334 call assert_equal('', g:complete_word)
335 call assert_equal('omni', g:complete_type)
336
337 call feedkeys("S\<C-X>\<C-O>\<C-Y>\<Esc>", 'tx')
338 call assert_equal('foo', g:complete_word)
339 call assert_equal('omni', g:complete_type)
340
341 call feedkeys("S\<C-X>\<C-O>\<C-N>\<C-Y>\<Esc>0", 'tx')
342 call assert_equal('bar', g:complete_word)
343 call assert_equal('omni', g:complete_type)
344
345 call feedkeys("Shello vim visual v\<C-X>\<C-N>\<ESC>", 'tx')
346 call assert_equal('', g:complete_word)
347 call assert_equal('keyword', g:complete_type)
348
349 call feedkeys("Shello vim visual v\<C-X>\<C-N>\<C-Y>", 'tx')
350 call assert_equal('vim', g:complete_word)
351 call assert_equal('keyword', g:complete_type)
352
Girish Palyacbe53192025-04-14 22:13:15 +0200353 call feedkeys("Shello vim visual v\<C-N>\<ESC>", 'tx')
354 call assert_equal('', g:complete_word)
355 call assert_equal('keyword', g:complete_type)
356
357 call feedkeys("Shello vim visual v\<C-N>\<C-Y>", 'tx')
glepnir1c5a1202024-12-04 20:27:34 +0100358 call assert_equal('vim', g:complete_word)
359 call assert_equal('keyword', g:complete_type)
360
361 call feedkeys("Shello vim\<CR>completion test\<CR>\<C-X>\<C-l>\<C-Y>", 'tx')
362 call assert_equal('completion test', g:complete_word)
363 call assert_equal('whole_line', g:complete_type)
364
365 call feedkeys("S\<C-X>\<C-U>\<C-Y>", 'tx')
366 call assert_equal('foo', g:complete_word)
367 call assert_equal('function', g:complete_type)
368
369 inoremap <buffer> <f3> <cmd>call complete(1, ["red", "blue"])<cr>
370 call feedkeys("S\<f3>\<C-Y>", 'tx')
371 call assert_equal('red', g:complete_word)
372 call assert_equal('eval', g:complete_type)
373
374 call feedkeys("S\<C-X>\<C-V>\<C-Y>", 'tx')
375 call assert_equal('!', g:complete_word)
376 call assert_equal('cmdline', g:complete_type)
377
378 call writefile([''], 'foo_test', 'D')
379 call feedkeys("Sfoo\<C-X>\<C-F>\<C-Y>\<Esc>", 'tx')
380 call assert_equal('foo_test', g:complete_word)
381 call assert_equal('files', g:complete_type)
382
383 call writefile(['hello help'], 'test_case.txt', 'D')
384 set dictionary=test_case.txt
385 call feedkeys("ggdGSh\<C-X>\<C-K>\<C-Y>\<Esc>", 'tx')
386 call assert_equal('hello', g:complete_word)
387 call assert_equal('dictionary', g:complete_type)
388
389 set spell spelllang=en_us
390 call feedkeys("STheatre\<C-X>s\<C-Y>\<Esc>", 'tx')
391 call assert_equal('Theater', g:complete_word)
392 call assert_equal('spell', g:complete_type)
393
394 bwipe!
395 set completeopt& omnifunc& completefunc& spell& spelllang& dictionary&
396 autocmd! CompleteDone
397 delfunc OnDone
398 delfunc CompleteFunc
399 unlet g:complete_word
400 unlet g:complete_type
401endfunc
402
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100403func Test_CompleteDoneDict()
Bram Moolenaar3f169ce2020-01-26 22:43:31 +0100404 au CompleteDonePre * :call <SID>CompleteDone_CheckCompletedItemDict(1)
405 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDict(0)
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100406
407 set completefunc=<SID>CompleteDone_CompleteFuncDict
408 execute "normal a\<C-X>\<C-U>\<C-Y>"
409 set completefunc&
410
zeertzjq4cd45f12022-12-15 13:48:30 +0000411 call assert_equal(['one', 'two'], v:completed_item[ 'user_data' ])
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100412 call assert_true(s:called_completedone)
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100413
414 let s:called_completedone = 0
Girish Palyacbe53192025-04-14 22:13:15 +0200415 au! CompleteDonePre
416 au! CompleteDone
417
418 au CompleteDonePre * :call <SID>CompleteDone_CheckCompletedItemDict(2)
419 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDict(0)
420
421 set complete=.,f<SID>CompleteDone_CompleteFuncDict
422 execute "normal a\<C-N>\<C-Y>"
423 set complete&
424
425 call assert_equal(['one', 'two'], v:completed_item[ 'user_data' ])
426 call assert_true(s:called_completedone)
427
428 let s:called_completedone = 0
429 au! CompleteDonePre
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100430 au! CompleteDone
431endfunc
432
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100433func s:CompleteDone_CompleteFuncDictNoUserData(findstart, base)
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100434 if a:findstart
435 return 0
436 endif
437
438 return {
Bram Moolenaar08928322020-01-04 14:32:48 +0100439 \ 'words': [
440 \ {
441 \ 'word': 'aword',
442 \ 'abbr': 'wrd',
443 \ 'menu': 'extra text',
444 \ 'info': 'words are cool',
445 \ 'kind': 'W',
Bram Moolenaar08928322020-01-04 14:32:48 +0100446 \ }
447 \ ]
448 \ }
Bram Moolenaar1e115362019-01-09 23:01:02 +0100449endfunc
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100450
Bram Moolenaar1e115362019-01-09 23:01:02 +0100451func s:CompleteDone_CheckCompletedItemDictNoUserData()
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100452 call assert_equal( 'aword', v:completed_item[ 'word' ] )
453 call assert_equal( 'wrd', v:completed_item[ 'abbr' ] )
454 call assert_equal( 'extra text', v:completed_item[ 'menu' ] )
455 call assert_equal( 'words are cool', v:completed_item[ 'info' ] )
456 call assert_equal( 'W', v:completed_item[ 'kind' ] )
zeertzjq4cd45f12022-12-15 13:48:30 +0000457 call assert_equal( '', v:completed_item[ 'user_data' ] )
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100458
459 let s:called_completedone = 1
Bram Moolenaar1e115362019-01-09 23:01:02 +0100460endfunc
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100461
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100462func Test_CompleteDoneDictNoUserData()
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100463 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemDictNoUserData()
464
465 set completefunc=<SID>CompleteDone_CompleteFuncDictNoUserData
466 execute "normal a\<C-X>\<C-U>\<C-Y>"
467 set completefunc&
468
zeertzjq4cd45f12022-12-15 13:48:30 +0000469 call assert_equal('', v:completed_item[ 'user_data' ])
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100470 call assert_true(s:called_completedone)
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100471
472 let s:called_completedone = 0
Girish Palyacbe53192025-04-14 22:13:15 +0200473
474 set complete=.,f<SID>CompleteDone_CompleteFuncDictNoUserData
475 execute "normal a\<C-N>\<C-Y>"
476 set complete&
477
478 call assert_equal('', v:completed_item[ 'user_data' ])
479 call assert_true(s:called_completedone)
480
481 let s:called_completedone = 0
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100482 au! CompleteDone
483endfunc
484
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100485func s:CompleteDone_CompleteFuncList(findstart, base)
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100486 if a:findstart
487 return 0
488 endif
489
490 return [ 'aword' ]
Bram Moolenaar1e115362019-01-09 23:01:02 +0100491endfunc
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100492
Bram Moolenaar1e115362019-01-09 23:01:02 +0100493func s:CompleteDone_CheckCompletedItemList()
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100494 call assert_equal( 'aword', v:completed_item[ 'word' ] )
495 call assert_equal( '', v:completed_item[ 'abbr' ] )
496 call assert_equal( '', v:completed_item[ 'menu' ] )
497 call assert_equal( '', v:completed_item[ 'info' ] )
498 call assert_equal( '', v:completed_item[ 'kind' ] )
499 call assert_equal( '', v:completed_item[ 'user_data' ] )
500
501 let s:called_completedone = 1
Bram Moolenaar1e115362019-01-09 23:01:02 +0100502endfunc
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100503
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100504func Test_CompleteDoneList()
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100505 au CompleteDone * :call <SID>CompleteDone_CheckCompletedItemList()
506
507 set completefunc=<SID>CompleteDone_CompleteFuncList
508 execute "normal a\<C-X>\<C-U>\<C-Y>"
509 set completefunc&
510
Bram Moolenaarcee9bc22019-01-11 13:02:23 +0100511 call assert_equal('', v:completed_item[ 'user_data' ])
512 call assert_true(s:called_completedone)
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100513
514 let s:called_completedone = 0
Girish Palyacbe53192025-04-14 22:13:15 +0200515
516 set complete=.,f<SID>CompleteDone_CompleteFuncList
517 execute "normal a\<C-N>\<C-Y>"
518 set complete&
519
520 call assert_equal('', v:completed_item[ 'user_data' ])
521 call assert_true(s:called_completedone)
522
523 let s:called_completedone = 0
524
525 set complete=.,f
526 execute "normal a\<C-N>\<C-Y>"
527 set complete&
528
529 call assert_equal('', v:completed_item[ 'user_data' ])
530 call assert_true(s:called_completedone)
531
532 let s:called_completedone = 0
Bram Moolenaar9b56a572018-02-10 16:19:32 +0100533 au! CompleteDone
534endfunc
535
Bram Moolenaaraf559d22018-08-08 22:55:41 +0200536func Test_CompleteDone_undo()
537 au CompleteDone * call append(0, "prepend1")
538 new
539 call setline(1, ["line1", "line2"])
540 call feedkeys("Go\<C-X>\<C-N>\<CR>\<ESC>", "tx")
541 call assert_equal(["prepend1", "line1", "line2", "line1", ""],
542 \ getline(1, '$'))
543 undo
544 call assert_equal(["line1", "line2"], getline(1, '$'))
545 bwipe!
546 au! CompleteDone
547endfunc
548
Shougo Matsushita61021aa2022-07-27 14:40:00 +0100549func Test_CompleteDone_modify()
550 let value = {
551 \ 'word': '',
552 \ 'abbr': '',
553 \ 'menu': '',
554 \ 'info': '',
555 \ 'kind': '',
556 \ 'user_data': '',
557 \ }
558 let v:completed_item = value
zeertzjq75020942022-07-31 11:37:20 +0100559 call assert_equal(value, v:completed_item)
Shougo Matsushita61021aa2022-07-27 14:40:00 +0100560endfunc
561
Bram Moolenaarb806aa52020-09-12 22:52:57 +0200562func CompleteTest(findstart, query)
563 if a:findstart
564 return col('.')
565 endif
566 return ['matched']
567endfunc
568
569func Test_completefunc_info()
570 new
571 set completeopt=menuone
572 set completefunc=CompleteTest
573 call feedkeys("i\<C-X>\<C-U>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
Bram Moolenaarf9d51352020-10-26 19:22:42 +0100574 call assert_equal("matched{'pum_visible': 1, 'mode': 'function', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
Girish Palyacbe53192025-04-14 22:13:15 +0200575 %d
576 set complete=.,fCompleteTest
577 call feedkeys("i\<C-N>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
578 call assert_equal("matched{'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
579 %d
580 set complete=.,f
581 call feedkeys("i\<C-N>\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
582 call assert_equal("matched{'pum_visible': 1, 'mode': 'keyword', 'selected': 0, 'items': [{'word': 'matched', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}]}", getline(1))
Bram Moolenaarb806aa52020-09-12 22:52:57 +0200583 set completeopt&
Girish Palyacbe53192025-04-14 22:13:15 +0200584 set complete&
Bram Moolenaarb806aa52020-09-12 22:52:57 +0200585 set completefunc&
586endfunc
587
Girish Palyacbe53192025-04-14 22:13:15 +0200588func Test_cpt_func_cursorcol()
589 func CptColTest(findstart, query)
590 if a:findstart
591 call assert_equal("foo bar", getline(1))
592 call assert_equal(8, col('.'))
593 return col('.')
594 endif
595 call assert_equal("foo bar", getline(1))
596 call assert_equal(8, col('.'))
597 return v:none
598 endfunc
599
600 set complete=fCptColTest
601 new
602 call feedkeys("ifoo bar\<C-N>", "tx")
603 bwipe!
604 new
605 set completeopt=longest
606 call feedkeys("ifoo bar\<C-N>", "tx")
607 bwipe!
608 new
609 set completeopt=menuone
610 call feedkeys("ifoo bar\<C-N>", "tx")
611 bwipe!
612 new
613 set completeopt=menuone,preinsert
614 call feedkeys("ifoo bar\<C-N>", "tx")
615 bwipe!
616 set complete& completeopt&
617 delfunc CptColTest
618endfunc
619
Girish Palya12b1eb52025-02-24 21:39:42 +0100620func ScrollInfoWindowUserDefinedFn(findstart, query)
621 " User defined function (i_CTRL-X_CTRL-U)
622 if a:findstart
623 return col('.')
624 endif
625 let infostr = range(20)->mapnew({_, v -> string(v)})->join("\n")
626 return [{'word': 'foo', 'info': infostr}, {'word': 'bar'}]
627endfunc
628
629func ScrollInfoWindowPageDown()
630 call win_execute(popup_findinfo(), "normal! \<PageDown>")
631 return ''
632endfunc
633
634func ScrollInfoWindowPageUp()
635 call win_execute(popup_findinfo(), "normal! \<PageUp>")
636 return ''
637endfunc
638
639func ScrollInfoWindowTest(mvmt, count, fline)
640 new
641 set completeopt=menuone,popup,noinsert,noselect
642 set completepopup=height:5
643 set completefunc=ScrollInfoWindowUserDefinedFn
644 let keyseq = "i\<C-X>\<C-U>\<C-N>"
645 for _ in range(a:count)
646 let keyseq .= (a:mvmt == "pageup" ? "\<C-R>\<C-R>=ScrollInfoWindowPageUp()\<CR>" :
647 \ "\<C-R>\<C-R>=ScrollInfoWindowPageDown()\<CR>")
648 endfor
649 let keyseq .= "\<C-R>\<C-R>=string(popup_getpos(popup_findinfo()))\<CR>\<ESC>"
650 call feedkeys(keyseq, "tx")
651 call assert_match('''firstline'': ' . a:fline, getline(1))
652 bwipe!
653 set completeopt&
654 set completepopup&
655 set completefunc&
656endfunc
657
658func Test_scroll_info_window()
659 call ScrollInfoWindowTest("", 0, 1)
660 call ScrollInfoWindowTest("pagedown", 1, 4)
661 call ScrollInfoWindowTest("pagedown", 2, 7)
662 call ScrollInfoWindowTest("pagedown", 3, 11)
663 call ScrollInfoWindowTest("pageup", 3, 1)
664endfunc
665
Girish Palya8950bf72024-03-20 20:07:29 +0100666func CompleteInfoUserDefinedFn(findstart, query)
667 " User defined function (i_CTRL-X_CTRL-U)
668 if a:findstart
669 return col('.')
670 endif
671 return [{'word': 'foo'}, {'word': 'bar'}, {'word': 'baz'}, {'word': 'qux'}]
672endfunc
673
674func CompleteInfoTestUserDefinedFn(mvmt, idx, noselect)
Girish Palya8950bf72024-03-20 20:07:29 +0100675 if a:noselect
676 set completeopt=menuone,popup,noinsert,noselect
677 else
678 set completeopt=menu,preview
679 endif
Girish Palyacbe53192025-04-14 22:13:15 +0200680 let items = "[" .
Girish Palya8950bf72024-03-20 20:07:29 +0100681 \ "{'word': 'foo', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " .
682 \ "{'word': 'bar', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " .
683 \ "{'word': 'baz', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, " .
684 \ "{'word': 'qux', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}" .
Girish Palyacbe53192025-04-14 22:13:15 +0200685 \ "]"
686 new
687 set completefunc=CompleteInfoUserDefinedFn
688 call feedkeys("i\<C-X>\<C-U>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
689 let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : ''
690 call assert_equal(completed. "{'pum_visible': 1, 'mode': 'function', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
691 %d
692 set complete=.,fCompleteInfoUserDefinedFn
693 call feedkeys("i\<C-N>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
694 let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : ''
695 call assert_equal(completed. "{'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
696 %d
697 set complete=.,f
698 call feedkeys("i\<C-N>" . a:mvmt . "\<C-R>\<C-R>=string(complete_info())\<CR>\<ESC>", "tx")
699 let completed = a:idx != -1 ? ['foo', 'bar', 'baz', 'qux']->get(a:idx) : ''
700 call assert_equal(completed. "{'pum_visible': 1, 'mode': 'keyword', 'selected': " . a:idx . ", 'items': " . items . "}", getline(1))
Girish Palya8950bf72024-03-20 20:07:29 +0100701 bwipe!
Girish Palyacbe53192025-04-14 22:13:15 +0200702 set completeopt& completefunc& complete&
Girish Palya8950bf72024-03-20 20:07:29 +0100703endfunc
704
705func Test_complete_info_user_defined_fn()
706 " forward
707 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 1, v:true)
708 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 2, v:true)
709 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>", 2, v:false)
710 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>", 3, v:false)
711 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>", -1, v:false)
712 " backward
713 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 2, v:true)
714 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 1, v:true)
715 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>", -1, v:true)
716 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>", 3, v:false)
717 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>", 2, v:false)
718 " forward backward
719 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 1, v:true)
720 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 0, v:true)
721 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-P>", 2, v:false)
722 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 3, v:false)
723 call CompleteInfoTestUserDefinedFn("\<C-N>\<C-N>\<C-P>", 1, v:false)
724 " backward forward
725 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 0, v:true)
726 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 2, v:true)
727 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-N>", 1, v:false)
728 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-P>\<C-P>\<C-N>", 3, v:false)
729 call CompleteInfoTestUserDefinedFn("\<C-P>\<C-N>\<C-N>", 1, v:false)
730endfunc
731
zeertzjq440d4cb2023-03-02 17:51:32 +0000732" Test that mouse scrolling/movement should not interrupt completion.
733func Test_mouse_scroll_move_during_completion()
734 new
735 com! -buffer TestCommand1 echo 'TestCommand1'
736 com! -buffer TestCommand2 echo 'TestCommand2'
737 call setline(1, ['', '', '', '', ''])
738 call cursor(5, 1)
739
740 " Without completion menu scrolling can move text.
741 set completeopt-=menu wrap
742 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelDown>\<C-V>", 'tx')
743 call assert_equal('TestCommand2', getline('.'))
744 call assert_notequal(1, winsaveview().topline)
745 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelUp>\<C-V>", 'tx')
746 call assert_equal('TestCommand2', getline('.'))
747 call assert_equal(1, winsaveview().topline)
748 set nowrap
749 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelRight>\<C-V>", 'tx')
750 call assert_equal('TestCommand2', getline('.'))
751 call assert_notequal(0, winsaveview().leftcol)
752 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelLeft>\<C-V>", 'tx')
753 call assert_equal('TestCommand2', getline('.'))
754 call assert_equal(0, winsaveview().leftcol)
755 call feedkeys("ccT\<C-X>\<C-V>\<MouseMove>\<C-V>", 'tx')
756 call assert_equal('TestCommand2', getline('.'))
757
758 " With completion menu scrolling cannot move text.
759 set completeopt+=menu wrap
760 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelDown>\<C-V>", 'tx')
761 call assert_equal('TestCommand2', getline('.'))
762 call assert_equal(1, winsaveview().topline)
763 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelUp>\<C-V>", 'tx')
764 call assert_equal('TestCommand2', getline('.'))
765 call assert_equal(1, winsaveview().topline)
766 set nowrap
767 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelRight>\<C-V>", 'tx')
768 call assert_equal('TestCommand2', getline('.'))
769 call assert_equal(0, winsaveview().leftcol)
770 call feedkeys("ccT\<C-X>\<C-V>\<ScrollWheelLeft>\<C-V>", 'tx')
771 call assert_equal('TestCommand2', getline('.'))
772 call assert_equal(0, winsaveview().leftcol)
773 call feedkeys("ccT\<C-X>\<C-V>\<MouseMove>\<C-V>", 'tx')
774 call assert_equal('TestCommand2', getline('.'))
775
776 bwipe!
777 set completeopt& wrap&
778endfunc
779
Bram Moolenaar02ae9b42018-02-09 15:06:02 +0100780" Check that when using feedkeys() typeahead does not interrupt searching for
781" completions.
782func Test_compl_feedkeys()
783 new
784 set completeopt=menuone,noselect
785 call feedkeys("ajump ju\<C-X>\<C-N>\<C-P>\<ESC>", "tx")
786 call assert_equal("jump jump", getline(1))
787 bwipe!
788 set completeopt&
789endfunc
Bram Moolenaarf03e3282019-07-22 21:55:18 +0200790
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200791" Test for insert path completion with completeslash option
792func Test_ins_completeslash()
Bram Moolenaar50f91d22019-08-02 19:52:15 +0200793 CheckMSWindows
Bram Moolenaar8f187fc2020-09-26 18:47:11 +0200794
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100795 call mkdir('Xcpldir', 'R')
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200796 let orig_shellslash = &shellslash
797 set cpt&
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200798 new
Bram Moolenaar8f187fc2020-09-26 18:47:11 +0200799
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200800 set noshellslash
801
802 set completeslash=
Bram Moolenaar816736b2022-08-29 23:01:45 +0100803 exe "normal oXcp\<C-X>\<C-F>"
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +0100804 call assert_equal('Xcpldir\', getline('.'))
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200805
806 set completeslash=backslash
Bram Moolenaar816736b2022-08-29 23:01:45 +0100807 exe "normal oXcp\<C-X>\<C-F>"
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +0100808 call assert_equal('Xcpldir\', getline('.'))
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200809
810 set completeslash=slash
Bram Moolenaar816736b2022-08-29 23:01:45 +0100811 exe "normal oXcp\<C-X>\<C-F>"
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +0100812 call assert_equal('Xcpldir/', getline('.'))
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200813
814 set shellslash
815
816 set completeslash=
Bram Moolenaar816736b2022-08-29 23:01:45 +0100817 exe "normal oXcp\<C-X>\<C-F>"
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +0100818 call assert_equal('Xcpldir/', getline('.'))
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200819
820 set completeslash=backslash
Bram Moolenaar816736b2022-08-29 23:01:45 +0100821 exe "normal oXcp\<C-X>\<C-F>"
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +0100822 call assert_equal('Xcpldir\', getline('.'))
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200823
824 set completeslash=slash
Bram Moolenaar816736b2022-08-29 23:01:45 +0100825 exe "normal oXcp\<C-X>\<C-F>"
Bram Moolenaar3b0d70f2022-08-29 22:31:20 +0100826 call assert_equal('Xcpldir/', getline('.'))
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200827 %bw!
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200828
Bram Moolenaar50f91d22019-08-02 19:52:15 +0200829 set noshellslash
830 set completeslash=slash
831 call assert_true(stridx(globpath(&rtp, 'syntax/*.vim', 1, 1)[0], '\') != -1)
832
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200833 let &shellslash = orig_shellslash
Bram Moolenaar50f91d22019-08-02 19:52:15 +0200834 set completeslash=
Bram Moolenaarac3150d2019-07-28 16:36:39 +0200835endfunc
836
Bram Moolenaard0e1b712020-09-27 20:13:03 +0200837func Test_pum_stopped_by_timer()
838 CheckScreendump
839
840 let lines =<< trim END
841 call setline(1, ['hello', 'hullo', 'heeee', ''])
842 func StartCompl()
843 call timer_start(100, { -> execute('stopinsert') })
844 call feedkeys("Gah\<C-N>")
845 endfunc
846 END
847
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100848 call writefile(lines, 'Xpumscript', 'D')
Bram Moolenaard0e1b712020-09-27 20:13:03 +0200849 let buf = RunVimInTerminal('-S Xpumscript', #{rows: 12})
850 call term_sendkeys(buf, ":call StartCompl()\<CR>")
851 call TermWait(buf, 200)
852 call term_sendkeys(buf, "k")
853 call VerifyScreenDump(buf, 'Test_pum_stopped_by_timer', {})
854
855 call StopVimInTerminal(buf)
Bram Moolenaard0e1b712020-09-27 20:13:03 +0200856endfunc
857
zeertzjqcd5dbad2022-05-04 17:51:50 +0100858func Test_complete_stopinsert_startinsert()
859 nnoremap <F2> <Cmd>startinsert<CR>
860 inoremap <F2> <Cmd>stopinsert<CR>
861 " This just checks if this causes an error
862 call feedkeys("i\<C-X>\<C-N>\<F2>\<F2>", 'x')
863 nunmap <F2>
864 iunmap <F2>
865endfunc
866
Bram Moolenaar09dd2bb2019-12-14 18:42:15 +0100867func Test_pum_with_folds_two_tabs()
868 CheckScreendump
869
870 let lines =<< trim END
871 set fdm=marker
872 call setline(1, ['" x {{{1', '" a some text'])
873 call setline(3, range(&lines)->map({_, val -> '" a' .. val}))
874 norm! zm
875 tab sp
876 call feedkeys('2Gzv', 'xt')
877 call feedkeys("0fa", 'xt')
878 END
879
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100880 call writefile(lines, 'Xpumscript', 'D')
Bram Moolenaar09dd2bb2019-12-14 18:42:15 +0100881 let buf = RunVimInTerminal('-S Xpumscript', #{rows: 10})
Bram Moolenaar6a2c5a72020-04-08 21:50:25 +0200882 call TermWait(buf, 50)
Bram Moolenaar09dd2bb2019-12-14 18:42:15 +0100883 call term_sendkeys(buf, "a\<C-N>")
884 call VerifyScreenDump(buf, 'Test_pum_with_folds_two_tabs', {})
885
886 call term_sendkeys(buf, "\<Esc>")
887 call StopVimInTerminal(buf)
Bram Moolenaar09dd2bb2019-12-14 18:42:15 +0100888endfunc
Bram Moolenaar5e5a98d2019-12-15 14:55:33 +0100889
890func Test_pum_with_preview_win()
891 CheckScreendump
892
893 let lines =<< trim END
glepnir53387c52024-05-27 15:11:01 +0200894 func Omni_test(findstart, base)
895 if a:findstart
896 return col(".") - 1
897 endif
898 return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}]
899 endfunc
900 set omnifunc=Omni_test
901 set completeopt+=longest
Bram Moolenaar5e5a98d2019-12-15 14:55:33 +0100902 END
903
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100904 call writefile(lines, 'Xpreviewscript', 'D')
Bram Moolenaar5e5a98d2019-12-15 14:55:33 +0100905 let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12})
Bram Moolenaar5e5a98d2019-12-15 14:55:33 +0100906 call term_sendkeys(buf, "Gi\<C-X>\<C-O>")
Bram Moolenaar0ff01832022-09-24 19:20:30 +0100907 call TermWait(buf, 200)
Bram Moolenaar5e5a98d2019-12-15 14:55:33 +0100908 call term_sendkeys(buf, "\<C-N>")
909 call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {})
910
911 call term_sendkeys(buf, "\<Esc>")
912 call StopVimInTerminal(buf)
Bram Moolenaar5e5a98d2019-12-15 14:55:33 +0100913endfunc
Bram Moolenaar830c1af2020-01-05 20:35:44 +0100914
Bram Moolenaar35d8c202022-03-03 11:46:00 +0000915func Test_scrollbar_on_wide_char()
916 CheckScreendump
917
918 let lines =<< trim END
919 call setline(1, ['a', ' 啊啊啊',
920 \ ' 哦哦哦',
921 \ ' 呃呃呃'])
922 call setline(5, range(10)->map({i, v -> 'aa' .. v .. 'bb'}))
923 END
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100924 call writefile(lines, 'Xwidescript', 'D')
Bram Moolenaar35d8c202022-03-03 11:46:00 +0000925 let buf = RunVimInTerminal('-S Xwidescript', #{rows: 10})
926 call term_sendkeys(buf, "A\<C-N>")
927 call VerifyScreenDump(buf, 'Test_scrollbar_on_wide_char', {})
928
929 call StopVimInTerminal(buf)
Bram Moolenaar35d8c202022-03-03 11:46:00 +0000930endfunc
931
Bram Moolenaar830c1af2020-01-05 20:35:44 +0100932" Test for inserting the tag search pattern in insert mode
933func Test_ins_compl_tag_sft()
934 call writefile([
935 \ "!_TAG_FILE_ENCODING\tutf-8\t//",
936 \ "first\tXfoo\t/^int first() {}$/",
937 \ "second\tXfoo\t/^int second() {}$/",
938 \ "third\tXfoo\t/^int third() {}$/"],
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100939 \ 'Xtags', 'D')
Bram Moolenaar830c1af2020-01-05 20:35:44 +0100940 set tags=Xtags
941 let code =<< trim [CODE]
942 int first() {}
943 int second() {}
944 int third() {}
945 [CODE]
Bram Moolenaar7dd5a782022-09-29 21:01:57 +0100946 call writefile(code, 'Xfoo', 'D')
Bram Moolenaar830c1af2020-01-05 20:35:44 +0100947
948 enew
949 set showfulltag
950 exe "normal isec\<C-X>\<C-]>\<C-N>\<CR>"
951 call assert_equal('int second() {}', getline(1))
952 set noshowfulltag
953
Bram Moolenaar830c1af2020-01-05 20:35:44 +0100954 set tags&
955 %bwipe!
956endfunc
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200957
958" Test for 'completefunc' deleting text
959func Test_completefunc_error()
960 new
Bram Moolenaarad48e6c2020-04-21 22:19:45 +0200961 " delete text when called for the first time
Bram Moolenaaree4e0c12020-04-06 21:35:05 +0200962 func CompleteFunc(findstart, base)
963 if a:findstart == 1
964 normal dd
965 return col('.') - 1
966 endif
967 return ['a', 'b']
968 endfunc
969 set completefunc=CompleteFunc
970 call setline(1, ['', 'abcd', ''])
zeertzjqcfe45652022-05-27 17:26:55 +0100971 call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:')
Girish Palyacbe53192025-04-14 22:13:15 +0200972 set complete=fCompleteFunc
973 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:')
974 set complete=f
975 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:')
Bram Moolenaarad48e6c2020-04-21 22:19:45 +0200976
977 " delete text when called for the second time
978 func CompleteFunc2(findstart, base)
979 if a:findstart == 1
980 return col('.') - 1
981 endif
982 normal dd
983 return ['a', 'b']
984 endfunc
985 set completefunc=CompleteFunc2
986 call setline(1, ['', 'abcd', ''])
zeertzjqcfe45652022-05-27 17:26:55 +0100987 call assert_fails('exe "normal 2G$a\<C-X>\<C-U>"', 'E565:')
Girish Palyacbe53192025-04-14 22:13:15 +0200988 set complete=fCompleteFunc2
989 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:')
990 set complete=f
991 call assert_fails('exe "normal 2G$a\<C-N>"', 'E565:')
Bram Moolenaarad48e6c2020-04-21 22:19:45 +0200992
Bram Moolenaar97202d92021-01-28 18:34:35 +0100993 " Jump to a different window from the complete function
Bram Moolenaar28976e22021-01-29 21:07:07 +0100994 func CompleteFunc3(findstart, base)
Bram Moolenaar97202d92021-01-28 18:34:35 +0100995 if a:findstart == 1
996 return col('.') - 1
997 endif
998 wincmd p
999 return ['a', 'b']
1000 endfunc
Bram Moolenaar28976e22021-01-29 21:07:07 +01001001 set completefunc=CompleteFunc3
Bram Moolenaar97202d92021-01-28 18:34:35 +01001002 new
Bram Moolenaar28976e22021-01-29 21:07:07 +01001003 call assert_fails('exe "normal a\<C-X>\<C-U>"', 'E565:')
Girish Palyacbe53192025-04-14 22:13:15 +02001004 %d
1005 set complete=fCompleteFunc3
1006 call assert_fails('exe "normal a\<C-N>"', 'E565:')
1007 %d
1008 set complete=f
1009 call assert_fails('exe "normal a\<C-N>"', 'E565:')
Bram Moolenaar97202d92021-01-28 18:34:35 +01001010 close!
1011
Girish Palyacbe53192025-04-14 22:13:15 +02001012 set completefunc& complete&
Bram Moolenaar97202d92021-01-28 18:34:35 +01001013 delfunc CompleteFunc
Bram Moolenaar28976e22021-01-29 21:07:07 +01001014 delfunc CompleteFunc2
1015 delfunc CompleteFunc3
1016 close!
Bram Moolenaar97202d92021-01-28 18:34:35 +01001017endfunc
1018
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001019" Test for returning non-string values from 'completefunc'
1020func Test_completefunc_invalid_data()
1021 new
1022 func! CompleteFunc(findstart, base)
1023 if a:findstart == 1
1024 return col('.') - 1
1025 endif
1026 return [{}, '', 'moon']
1027 endfunc
1028 set completefunc=CompleteFunc
1029 exe "normal i\<C-X>\<C-U>"
1030 call assert_equal('moon', getline(1))
Girish Palyacbe53192025-04-14 22:13:15 +02001031 %d
1032 set complete=fCompleteFunc
1033 exe "normal i\<C-N>"
1034 call assert_equal('moon', getline(1))
1035 %d
1036 set complete=f
1037 exe "normal i\<C-N>"
1038 call assert_equal('moon', getline(1))
1039 set completefunc& complete&
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001040 close!
1041endfunc
1042
Bram Moolenaarad48e6c2020-04-21 22:19:45 +02001043" Test for errors in using complete() function
1044func Test_complete_func_error()
1045 call assert_fails('call complete(1, ["a"])', 'E785:')
1046 func ListColors()
1047 call complete(col('.'), "blue")
1048 endfunc
Bram Moolenaard83392a2022-09-01 12:22:46 +01001049 call assert_fails('exe "normal i\<C-R>=ListColors()\<CR>"', 'E1211:')
Bram Moolenaarad48e6c2020-04-21 22:19:45 +02001050 func ListMonths()
1051 call complete(col('.'), test_null_list())
1052 endfunc
Bram Moolenaard83392a2022-09-01 12:22:46 +01001053 call assert_fails('exe "normal i\<C-R>=ListMonths()\<CR>"', 'E1298:')
Bram Moolenaarad48e6c2020-04-21 22:19:45 +02001054 delfunc ListColors
1055 delfunc ListMonths
Bram Moolenaard83392a2022-09-01 12:22:46 +01001056 call assert_fails('call complete_info({})', 'E1211:')
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001057 call assert_equal([], complete_info(['items']).items)
Bram Moolenaarad48e6c2020-04-21 22:19:45 +02001058endfunc
1059
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001060" Test for recursively starting completion mode using complete()
1061func Test_recursive_complete_func()
1062 func ListColors()
1063 call complete(5, ["red", "blue"])
1064 return ''
1065 endfunc
1066 new
1067 call setline(1, ['a1', 'a2'])
1068 set complete=.
1069 exe "normal Goa\<C-X>\<C-L>\<C-R>=ListColors()\<CR>\<C-N>"
1070 call assert_equal('a2blue', getline(3))
1071 delfunc ListColors
1072 bw!
1073endfunc
1074
bfredl87af60c2022-09-24 11:17:51 +01001075" Test for using complete() with completeopt+=longest
1076func Test_complete_with_longest()
bfredl87af60c2022-09-24 11:17:51 +01001077 new
zeertzjq75f4baf2022-09-24 14:08:23 +01001078 inoremap <buffer> <f3> <cmd>call complete(1, ["iaax", "iaay", "iaaz"])<cr>
bfredl87af60c2022-09-24 11:17:51 +01001079
1080 " default: insert first match
1081 set completeopt&
1082 call setline(1, ['i'])
1083 exe "normal Aa\<f3>\<esc>"
1084 call assert_equal('iaax', getline(1))
1085
1086 " with longest: insert longest prefix
1087 set completeopt+=longest
1088 call setline(1, ['i'])
1089 exe "normal Aa\<f3>\<esc>"
1090 call assert_equal('iaa', getline(1))
1091 set completeopt&
zeertzjq75f4baf2022-09-24 14:08:23 +01001092 bwipe!
bfredl87af60c2022-09-24 11:17:51 +01001093endfunc
1094
zeertzjq529b9ad2024-06-05 20:27:06 +02001095" Test for buffer-local value of 'completeopt'
1096func Test_completeopt_buffer_local()
1097 set completeopt=menu
1098 new
1099 call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
1100 call assert_equal('', &l:completeopt)
1101 call assert_equal('menu', &completeopt)
1102 call assert_equal('menu', &g:completeopt)
1103
1104 setlocal bufhidden=hide
1105 enew
1106 call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
1107 call assert_equal('', &l:completeopt)
1108 call assert_equal('menu', &completeopt)
1109 call assert_equal('menu', &g:completeopt)
1110
1111 setlocal completeopt+=fuzzy,noinsert
1112 call assert_equal('menu,fuzzy,noinsert', &l:completeopt)
1113 call assert_equal('menu,fuzzy,noinsert', &completeopt)
1114 call assert_equal('menu', &g:completeopt)
1115 call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix')
1116 call assert_equal('foobaz', getline('.'))
1117
1118 setlocal completeopt=
1119 call assert_equal('', &l:completeopt)
1120 call assert_equal('menu', &completeopt)
1121 call assert_equal('menu', &g:completeopt)
1122 call feedkeys("Gccf\<C-X>\<C-N>\<C-Y>", 'tnix')
1123 call assert_equal('foofoo', getline('.'))
1124
1125 setlocal completeopt+=longest
1126 call assert_equal('menu,longest', &l:completeopt)
1127 call assert_equal('menu,longest', &completeopt)
1128 call assert_equal('menu', &g:completeopt)
1129 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix')
1130 call assert_equal('foo', getline('.'))
1131
1132 setlocal bufhidden=hide
1133 buffer #
1134 call assert_equal('', &l:completeopt)
1135 call assert_equal('menu', &completeopt)
1136 call assert_equal('menu', &g:completeopt)
1137 call feedkeys("Gccf\<C-X>\<C-N>\<C-Y>", 'tnix')
1138 call assert_equal('foofoo', getline('.'))
1139
1140 setlocal completeopt+=fuzzy,noinsert
1141 call assert_equal('menu,fuzzy,noinsert', &l:completeopt)
1142 call assert_equal('menu,fuzzy,noinsert', &completeopt)
1143 call assert_equal('menu', &g:completeopt)
1144 call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix')
1145 call assert_equal('foobaz', getline('.'))
1146
1147 buffer #
1148 call assert_equal('menu,longest', &l:completeopt)
1149 call assert_equal('menu,longest', &completeopt)
1150 call assert_equal('menu', &g:completeopt)
1151 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix')
1152 call assert_equal('foo', getline('.'))
1153
1154 setlocal bufhidden=wipe
1155 buffer! #
1156 bwipe!
1157 call assert_equal('', &l:completeopt)
1158 call assert_equal('menu', &completeopt)
1159 call assert_equal('menu', &g:completeopt)
1160
zeertzjq46dcd842024-11-03 09:10:50 +01001161 new | only
1162 call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
1163 set completeopt&
1164 setlocal completeopt=menu,fuzzy,noinsert
1165 setglobal completeopt=menu,longest
1166 call assert_equal('menu,fuzzy,noinsert', &completeopt)
1167 call assert_equal('menu,fuzzy,noinsert', &l:completeopt)
1168 call assert_equal('menu,longest', &g:completeopt)
1169 call feedkeys("Gccf\<C-X>\<C-N>bz\<C-Y>", 'tnix')
1170 call assert_equal('foobaz', getline('.'))
1171 setlocal bufhidden=wipe
1172 new | only!
1173 call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
1174 call assert_equal('menu,longest', &completeopt)
1175 call assert_equal('menu,longest', &g:completeopt)
1176 call assert_equal('', &l:completeopt)
1177 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix')
1178 call assert_equal('foo', getline('.'))
1179 bwipe!
1180
1181 new | only
1182 call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
1183 set completeopt&
1184 setlocal completeopt=menu,fuzzy,noinsert
1185 set completeopt=menu,longest
1186 call assert_equal('menu,longest', &completeopt)
1187 call assert_equal('menu,longest', &g:completeopt)
1188 call assert_equal('', &l:completeopt)
1189 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix')
1190 call assert_equal('foo', getline('.'))
1191 setlocal bufhidden=wipe
1192 new | only!
1193 call setline(1, ['foofoo', 'foobar', 'foobaz', ''])
1194 call assert_equal('menu,longest', &completeopt)
1195 call assert_equal('menu,longest', &g:completeopt)
1196 call assert_equal('', &l:completeopt)
1197 call feedkeys("Gccf\<C-X>\<C-N>\<C-X>\<C-Z>", 'tnix')
1198 call assert_equal('foo', getline('.'))
1199 bwipe!
1200
zeertzjq529b9ad2024-06-05 20:27:06 +02001201 set completeopt&
1202endfunc
bfredl87af60c2022-09-24 11:17:51 +01001203
Bram Moolenaar224a5f12020-04-28 20:29:07 +02001204" Test for completing words following a completed word in a line
1205func Test_complete_wrapscan()
1206 " complete words from another buffer
1207 new
1208 call setline(1, ['one two', 'three four'])
1209 new
1210 setlocal complete=w
1211 call feedkeys("itw\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>", 'xt')
1212 call assert_equal('two three four', getline(1))
1213 close!
1214 " complete words from the current buffer
1215 setlocal complete=.
1216 %d
1217 call setline(1, ['one two', ''])
1218 call cursor(2, 1)
1219 call feedkeys("ion\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>", 'xt')
1220 call assert_equal('one two one two', getline(2))
1221 close!
1222endfunc
1223
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001224" Test for completing special characters
1225func Test_complete_special_chars()
1226 new
1227 call setline(1, 'int .*[-\^$ func float')
1228 call feedkeys("oin\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>", 'xt')
1229 call assert_equal('int .*[-\^$ func float', getline(2))
1230 close!
1231endfunc
1232
1233" Test for completion when text is wrapped across lines.
1234func Test_complete_across_line()
1235 new
1236 call setline(1, ['red green blue', 'one two three'])
1237 setlocal textwidth=20
1238 exe "normal 2G$a re\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>"
1239 call assert_equal(['one two three red', 'green blue one'], getline(2, '$'))
1240 close!
1241endfunc
1242
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00001243" Test for completing words with a '.' at the end of a word.
1244func Test_complete_joinspaces()
1245 new
1246 call setline(1, ['one two.', 'three. four'])
1247 set joinspaces
1248 exe "normal Goon\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>"
1249 call assert_equal("one two. three. four", getline(3))
1250 set joinspaces&
1251 bw!
1252endfunc
1253
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001254" Test for using CTRL-L to add one character when completing matching
1255func Test_complete_add_onechar()
1256 new
1257 call setline(1, ['wool', 'woodwork'])
1258 call feedkeys("Gowoo\<C-P>\<C-P>\<C-P>\<C-L>f", 'xt')
1259 call assert_equal('woof', getline(3))
1260
1261 " use 'ignorecase' and backspace to erase characters from the prefix string
1262 " and then add letters using CTRL-L
1263 %d
1264 set ignorecase backspace=2
1265 setlocal complete=.
1266 call setline(1, ['workhorse', 'workload'])
1267 normal Go
nwounkn2e3cd522023-10-17 11:05:38 +02001268 exe "normal aWOR\<C-P>\<bs>\<bs>\<bs>\<bs>\<bs>\<bs>\<C-L>\<C-L>\<C-L>"
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001269 call assert_equal('workh', getline(3))
1270 set ignorecase& backspace&
1271 close!
1272endfunc
1273
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00001274" Test for using CTRL-X CTRL-L to complete whole lines lines
1275func Test_complete_wholeline()
1276 new
1277 " complete one-line
1278 call setline(1, ['a1', 'a2'])
1279 exe "normal ggoa\<C-X>\<C-L>"
1280 call assert_equal(['a1', 'a1', 'a2'], getline(1, '$'))
1281 " go to the next match (wrapping around the buffer)
1282 exe "normal 2GCa\<C-X>\<C-L>\<C-N>"
1283 call assert_equal(['a1', 'a', 'a2'], getline(1, '$'))
1284 " go to the next match
1285 exe "normal 2GCa\<C-X>\<C-L>\<C-N>\<C-N>"
1286 call assert_equal(['a1', 'a2', 'a2'], getline(1, '$'))
1287 exe "normal 2GCa\<C-X>\<C-L>\<C-N>\<C-N>\<C-N>"
1288 call assert_equal(['a1', 'a1', 'a2'], getline(1, '$'))
1289 " repeat the test using CTRL-L
1290 " go to the next match (wrapping around the buffer)
1291 exe "normal 2GCa\<C-X>\<C-L>\<C-L>"
1292 call assert_equal(['a1', 'a2', 'a2'], getline(1, '$'))
1293 " go to the next match
1294 exe "normal 2GCa\<C-X>\<C-L>\<C-L>\<C-L>"
1295 call assert_equal(['a1', 'a', 'a2'], getline(1, '$'))
1296 exe "normal 2GCa\<C-X>\<C-L>\<C-L>\<C-L>\<C-L>"
1297 call assert_equal(['a1', 'a1', 'a2'], getline(1, '$'))
1298 %d
1299 " use CTRL-X CTRL-L to add one more line
1300 call setline(1, ['a1', 'b1'])
1301 setlocal complete=.
1302 exe "normal ggOa\<C-X>\<C-L>\<C-X>\<C-L>\<C-X>\<C-L>"
1303 call assert_equal(['a1', 'b1', '', 'a1', 'b1'], getline(1, '$'))
1304 bw!
1305endfunc
1306
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001307" Test insert completion with 'cindent' (adjust the indent)
1308func Test_complete_with_cindent()
1309 new
1310 setlocal cindent
1311 call setline(1, ['if (i == 1)', " j = 2;"])
1312 exe "normal Go{\<CR>i\<C-X>\<C-L>\<C-X>\<C-L>\<CR>}"
1313 call assert_equal(['{', "\tif (i == 1)", "\t\tj = 2;", '}'], getline(3, '$'))
1314
1315 %d
1316 call setline(1, ['when while', '{', ''])
1317 setlocal cinkeys+==while
1318 exe "normal Giwh\<C-P> "
1319 call assert_equal("\twhile ", getline('$'))
1320 close!
1321endfunc
1322
1323" Test for <CTRL-X> <CTRL-V> completion. Complete commands and functions
1324func Test_complete_cmdline()
1325 new
1326 exe "normal icaddb\<C-X>\<C-V>"
1327 call assert_equal('caddbuffer', getline(1))
1328 exe "normal ocall getqf\<C-X>\<C-V>"
1329 call assert_equal('call getqflist(', getline(2))
1330 exe "normal oabcxyz(\<C-X>\<C-V>"
1331 call assert_equal('abcxyz(', getline(3))
zeertzjqdca29d92021-08-31 19:12:51 +02001332 com! -buffer TestCommand1 echo 'TestCommand1'
1333 com! -buffer TestCommand2 echo 'TestCommand2'
Jim Zhouf7087cb2025-03-05 20:25:11 +01001334 write! TestCommand1Test
1335 write! TestCommand2Test
zeertzjqdca29d92021-08-31 19:12:51 +02001336 " Test repeating <CTRL-X> <CTRL-V> and switching to another CTRL-X mode
1337 exe "normal oT\<C-X>\<C-V>\<C-X>\<C-V>\<C-X>\<C-F>\<Esc>"
1338 call assert_equal('TestCommand2Test', getline(4))
1339 call delete('TestCommand1Test')
1340 call delete('TestCommand2Test')
1341 delcom TestCommand1
1342 delcom TestCommand2
1343 close!
1344endfunc
1345
1346" Test for <CTRL-X> <CTRL-Z> stopping completion without changing the match
1347func Test_complete_stop()
1348 new
1349 func Save_mode1()
1350 let g:mode1 = mode(1)
1351 return ''
1352 endfunc
1353 func Save_mode2()
1354 let g:mode2 = mode(1)
1355 return ''
1356 endfunc
1357 inoremap <F1> <C-R>=Save_mode1()<CR>
1358 inoremap <F2> <C-R>=Save_mode2()<CR>
1359 call setline(1, ['aaa bbb ccc '])
1360 exe "normal A\<C-N>\<C-P>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
1361 call assert_equal('ic', g:mode1)
1362 call assert_equal('i', g:mode2)
1363 call assert_equal('aaa bbb ccc ', getline(1))
1364 exe "normal A\<C-N>\<Down>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
1365 call assert_equal('ic', g:mode1)
1366 call assert_equal('i', g:mode2)
1367 call assert_equal('aaa bbb ccc aaa', getline(1))
1368 set completeopt+=noselect
1369 exe "normal A \<C-N>\<Down>\<Down>\<C-L>\<C-L>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
1370 call assert_equal('ic', g:mode1)
1371 call assert_equal('i', g:mode2)
1372 call assert_equal('aaa bbb ccc aaa bb', getline(1))
1373 set completeopt&
1374 exe "normal A d\<C-N>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
1375 call assert_equal('ic', g:mode1)
1376 call assert_equal('i', g:mode2)
1377 call assert_equal('aaa bbb ccc aaa bb d', getline(1))
1378 com! -buffer TestCommand1 echo 'TestCommand1'
1379 com! -buffer TestCommand2 echo 'TestCommand2'
1380 exe "normal oT\<C-X>\<C-V>\<C-X>\<C-V>\<F1>\<C-X>\<C-Z>\<F2>\<Esc>"
1381 call assert_equal('ic', g:mode1)
1382 call assert_equal('i', g:mode2)
1383 call assert_equal('TestCommand2', getline(2))
1384 delcom TestCommand1
1385 delcom TestCommand2
1386 unlet g:mode1
1387 unlet g:mode2
1388 iunmap <F1>
1389 iunmap <F2>
1390 delfunc Save_mode1
1391 delfunc Save_mode2
Bram Moolenaarf9ab52e2020-05-05 19:57:18 +02001392 close!
1393endfunc
1394
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00001395" Test for typing CTRL-R in insert completion mode to insert a register
1396" content.
1397func Test_complete_reginsert()
1398 new
1399 call setline(1, ['a1', 'a12', 'a123', 'a1234'])
1400
1401 " if a valid CTRL-X mode key is returned from <C-R>=, then it should be
1402 " processed. Otherwise, CTRL-X mode should be stopped and the key should be
1403 " inserted.
1404 exe "normal Goa\<C-P>\<C-R>=\"\\<C-P>\"\<CR>"
1405 call assert_equal('a123', getline(5))
1406 let @r = "\<C-P>\<C-P>"
1407 exe "normal GCa\<C-P>\<C-R>r"
1408 call assert_equal('a12', getline(5))
1409 exe "normal GCa\<C-P>\<C-R>=\"x\"\<CR>"
1410 call assert_equal('a1234x', getline(5))
1411 bw!
1412endfunc
1413
Bram Moolenaar8f187fc2020-09-26 18:47:11 +02001414func Test_issue_7021()
1415 CheckMSWindows
1416
1417 let orig_shellslash = &shellslash
1418 set noshellslash
1419
1420 set completeslash=slash
1421 call assert_false(expand('~') =~ '/')
1422
1423 let &shellslash = orig_shellslash
1424 set completeslash=
1425endfunc
1426
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001427" Test for 'longest' setting in 'completeopt' with latin1 and utf-8 encodings
1428func Test_complete_longest_match()
1429 for e in ['latin1', 'utf-8']
1430 exe 'set encoding=' .. e
1431 new
1432 set complete=.
1433 set completeopt=menu,longest
1434 call setline(1, ['pfx_a1', 'pfx_a12', 'pfx_a123', 'pfx_b1'])
1435 exe "normal Gopfx\<C-P>"
1436 call assert_equal('pfx_', getline(5))
1437 bw!
1438 endfor
1439
1440 " Test for completing additional words with longest match set
1441 new
1442 call setline(1, ['abc1', 'abd2'])
1443 exe "normal Goab\<C-P>\<C-X>\<C-P>"
1444 call assert_equal('ab', getline(3))
1445 bw!
1446 set complete& completeopt&
1447endfunc
1448
1449" Test for removing the first displayed completion match and selecting the
1450" match just before that.
1451func Test_complete_erase_firstmatch()
1452 new
1453 call setline(1, ['a12', 'a34', 'a56'])
1454 set complete=.
1455 exe "normal Goa\<C-P>\<BS>\<BS>3\<CR>"
1456 call assert_equal('a34', getline('$'))
1457 set complete&
1458 bw!
1459endfunc
1460
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001461" Test for completing words from unloaded buffers
1462func Test_complete_from_unloadedbuf()
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001463 call writefile(['abc'], "Xfile1", 'D')
1464 call writefile(['def'], "Xfile2", 'D')
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001465 edit Xfile1
1466 edit Xfile2
1467 new | close
1468 enew
1469 bunload Xfile1 Xfile2
1470 set complete=u
1471 " complete from an unloaded buffer
1472 exe "normal! ia\<C-P>"
1473 call assert_equal('abc', getline(1))
1474 exe "normal! od\<C-P>"
1475 call assert_equal('def', getline(2))
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001476
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001477 set complete&
1478 %bw!
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001479endfunc
1480
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001481" Test for completing whole lines from unloaded buffers
1482func Test_complete_wholeline_unloadedbuf()
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001483 call writefile(['a line1', 'a line2', 'a line3'], "Xfile1", 'D')
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001484 edit Xfile1
1485 enew
1486 set complete=u
1487 exe "normal! ia\<C-X>\<C-L>\<C-P>"
1488 call assert_equal('a line2', getline(1))
1489 %d
1490 " completing from an unlisted buffer should fail
1491 bdel Xfile1
1492 exe "normal! ia\<C-X>\<C-L>\<C-P>"
1493 call assert_equal('a', getline(1))
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001494
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001495 set complete&
1496 %bw!
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001497endfunc
1498
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001499" Test for completing words from unlisted buffers
1500func Test_complete_from_unlistedbuf()
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001501 call writefile(['abc'], "Xfile1", 'D')
1502 call writefile(['def'], "Xfile2", 'D')
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001503 edit Xfile1
1504 edit Xfile2
1505 new | close
1506 bdel Xfile1 Xfile2
1507 set complete=U
1508 " complete from an unlisted buffer
1509 exe "normal! ia\<C-P>"
1510 call assert_equal('abc', getline(1))
1511 exe "normal! od\<C-P>"
1512 call assert_equal('def', getline(2))
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001513
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001514 set complete&
1515 %bw!
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001516endfunc
1517
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001518" Test for completing whole lines from unlisted buffers
1519func Test_complete_wholeline_unlistedbuf()
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001520 call writefile(['a line1', 'a line2', 'a line3'], "Xfile1", 'D')
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001521 edit Xfile1
1522 enew
1523 set complete=U
zeertzjqc029c132024-03-28 11:37:26 +01001524 " completing from an unloaded buffer should fail
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001525 exe "normal! ia\<C-X>\<C-L>\<C-P>"
1526 call assert_equal('a', getline(1))
1527 %d
1528 bdel Xfile1
1529 exe "normal! ia\<C-X>\<C-L>\<C-P>"
1530 call assert_equal('a line2', getline(1))
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01001531
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001532 set complete&
1533 %bw!
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001534endfunc
1535
1536" Test for adding a multibyte character using CTRL-L in completion mode
1537func Test_complete_mbyte_char_add()
1538 new
1539 set complete=.
1540 call setline(1, 'abė')
1541 exe "normal! oa\<C-P>\<BS>\<BS>\<C-L>\<C-L>"
1542 call assert_equal('abė', getline(2))
1543 " Test for a leader with multibyte character
1544 %d
1545 call setline(1, 'abėĕ')
1546 exe "normal! oabė\<C-P>"
1547 call assert_equal('abėĕ', getline(2))
1548 bw!
1549endfunc
1550
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001551" Test for using <C-X><C-P> for local expansion even if 'complete' is set to
1552" not to complete matches from the local buffer. Also test using multiple
1553" <C-X> to cancel the current completion mode.
1554func Test_complete_local_expansion()
1555 new
1556 set complete=t
1557 call setline(1, ['abc', 'def'])
1558 exe "normal! Go\<C-X>\<C-P>"
1559 call assert_equal("def", getline(3))
1560 exe "normal! Go\<C-P>"
1561 call assert_equal("", getline(4))
1562 exe "normal! Go\<C-X>\<C-N>"
1563 call assert_equal("abc", getline(5))
1564 exe "normal! Go\<C-N>"
1565 call assert_equal("", getline(6))
1566
1567 " use multiple <C-X> to cancel the previous completion mode
1568 exe "normal! Go\<C-P>\<C-X>\<C-P>"
1569 call assert_equal("", getline(7))
1570 exe "normal! Go\<C-P>\<C-X>\<C-X>\<C-P>"
1571 call assert_equal("", getline(8))
1572 exe "normal! Go\<C-P>\<C-X>\<C-X>\<C-X>\<C-P>"
1573 call assert_equal("abc", getline(9))
1574
1575 " interrupt the current completion mode
1576 set completeopt=menu,noinsert
1577 exe "normal! Go\<C-X>\<C-F>\<C-X>\<C-X>\<C-P>\<C-Y>"
1578 call assert_equal("abc", getline(10))
1579
1580 " when only one <C-X> is used to interrupt, do normal expansion
1581 exe "normal! Go\<C-X>\<C-F>\<C-X>\<C-P>"
1582 call assert_equal("", getline(11))
1583 set completeopt&
1584
1585 " using two <C-X> in non-completion mode and restarting the same mode
1586 exe "normal! God\<C-X>\<C-X>\<C-P>\<C-X>\<C-X>\<C-P>\<C-Y>"
1587 call assert_equal("def", getline(12))
1588
1589 " test for adding a match from the original empty text
1590 %d
1591 call setline(1, 'abc def g')
1592 exe "normal! o\<C-X>\<C-P>\<C-N>\<C-X>\<C-P>"
1593 call assert_equal('def', getline(2))
1594 exe "normal! 0C\<C-X>\<C-N>\<C-P>\<C-X>\<C-N>"
1595 call assert_equal('abc', getline(2))
1596
1597 bw!
1598endfunc
1599
1600" Test for undoing changes after a insert-mode completion
1601func Test_complete_undo()
1602 new
1603 set complete=.
1604 " undo with 'ignorecase'
1605 call setline(1, ['ABOVE', 'BELOW'])
1606 set ignorecase
1607 exe "normal! Goab\<C-G>u\<C-P>"
1608 call assert_equal("ABOVE", getline(3))
1609 undo
1610 call assert_equal("ab", getline(3))
1611 set ignorecase&
1612 %d
1613 " undo with longest match
1614 set completeopt=menu,longest
1615 call setline(1, ['above', 'about'])
1616 exe "normal! Goa\<C-G>u\<C-P>"
1617 call assert_equal("abo", getline(3))
1618 undo
1619 call assert_equal("a", getline(3))
1620 set completeopt&
1621 %d
1622 " undo for line completion
1623 call setline(1, ['above that change', 'below that change'])
1624 exe "normal! Goabove\<C-G>u\<C-X>\<C-L>"
1625 call assert_equal("above that change", getline(3))
1626 undo
1627 call assert_equal("above", getline(3))
1628
1629 bw!
1630endfunc
1631
1632" Test for completing a very long word
1633func Test_complete_long_word()
1634 set complete&
1635 new
1636 call setline(1, repeat('x', 950) .. ' one two three')
1637 exe "normal! Gox\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>"
1638 call assert_equal(repeat('x', 950) .. ' one two three', getline(2))
1639 %d
1640 " should fail when more than 950 characters are in a word
1641 call setline(1, repeat('x', 951) .. ' one two three')
1642 exe "normal! Gox\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>\<C-X>\<C-P>"
1643 call assert_equal(repeat('x', 951), getline(2))
1644
1645 " Test for adding a very long word to an existing completion
1646 %d
1647 call setline(1, ['abc', repeat('x', 1016) .. '012345'])
1648 exe "normal! Goab\<C-P>\<C-X>\<C-P>"
1649 call assert_equal('abc ' .. repeat('x', 1016) .. '0123', getline(3))
1650 bw!
1651endfunc
1652
1653" Test for some fields in the complete items used by complete()
1654func Test_complete_items()
1655 func CompleteItems(idx)
1656 let items = [[#{word: "one", dup: 1, user_data: 'u1'}, #{word: "one", dup: 1, user_data: 'u2'}],
1657 \ [#{word: "one", dup: 0, user_data: 'u3'}, #{word: "one", dup: 0, user_data: 'u4'}],
1658 \ [#{word: "one", icase: 1, user_data: 'u7'}, #{word: "oNE", icase: 1, user_data: 'u8'}],
1659 \ [#{user_data: 'u9'}],
1660 \ [#{word: "", user_data: 'u10'}],
1661 \ [#{word: "", empty: 1, user_data: 'u11'}]]
1662 call complete(col('.'), items[a:idx])
1663 return ''
1664 endfunc
1665 new
1666 exe "normal! i\<C-R>=CompleteItems(0)\<CR>\<C-N>\<C-Y>"
1667 call assert_equal('u2', v:completed_item.user_data)
1668 call assert_equal('one', getline(1))
1669 exe "normal! o\<C-R>=CompleteItems(1)\<CR>\<C-Y>"
1670 call assert_equal('u3', v:completed_item.user_data)
1671 call assert_equal('one', getline(2))
1672 exe "normal! o\<C-R>=CompleteItems(1)\<CR>\<C-N>"
1673 call assert_equal('', getline(3))
1674 set completeopt=menu,noinsert
1675 exe "normal! o\<C-R>=CompleteItems(2)\<CR>one\<C-N>\<C-Y>"
1676 call assert_equal('oNE', getline(4))
1677 call assert_equal('u8', v:completed_item.user_data)
1678 set completeopt&
1679 exe "normal! o\<C-R>=CompleteItems(3)\<CR>"
1680 call assert_equal('', getline(5))
1681 exe "normal! o\<C-R>=CompleteItems(4)\<CR>"
1682 call assert_equal('', getline(6))
1683 exe "normal! o\<C-R>=CompleteItems(5)\<CR>"
1684 call assert_equal('', getline(7))
1685 call assert_equal('u11', v:completed_item.user_data)
1686 " pass invalid argument to complete()
1687 let cmd = "normal! o\<C-R>=complete(1, [[]])\<CR>"
1688 call assert_fails('exe cmd', 'E730:')
1689 bw!
1690 delfunc CompleteItems
1691endfunc
1692
1693" Test for the "refresh" item in the dict returned by an insert completion
1694" function
1695func Test_complete_item_refresh_always()
1696 let g:CallCount = 0
1697 func! Tcomplete(findstart, base)
1698 if a:findstart
1699 " locate the start of the word
1700 let line = getline('.')
1701 let start = col('.') - 1
1702 while start > 0 && line[start - 1] =~ '\a'
1703 let start -= 1
1704 endwhile
1705 return start
1706 else
1707 let g:CallCount += 1
1708 let res = ["update1", "update12", "update123"]
1709 return #{words: res, refresh: 'always'}
1710 endif
1711 endfunc
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001712 set completeopt=menu,longest
1713 set completefunc=Tcomplete
Girish Palyacbe53192025-04-14 22:13:15 +02001714 new
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001715 exe "normal! iup\<C-X>\<C-U>\<BS>\<BS>\<BS>\<BS>\<BS>"
1716 call assert_equal('up', getline(1))
Luca Saccarola959ef612024-12-01 16:25:53 +01001717 call assert_equal(6, g:CallCount)
Girish Palyacbe53192025-04-14 22:13:15 +02001718 %d
1719 let g:CallCount = 0
1720 set complete=fTcomplete
1721 exe "normal! iup\<C-N>\<BS>\<BS>\<BS>\<BS>\<BS>"
1722 call assert_equal('up', getline(1))
1723 call assert_equal(6, g:CallCount)
1724 %d
1725 let g:CallCount = 0
1726 set complete=f
1727 exe "normal! iup\<C-N>\<BS>\<BS>\<BS>\<BS>\<BS>"
1728 call assert_equal('up', getline(1))
1729 call assert_equal(6, g:CallCount)
1730 %d
1731 let g:CallCount = 0
1732 set omnifunc=Tcomplete
1733 set complete=o
1734 exe "normal! iup\<C-N>\<BS>\<BS>\<BS>\<BS>\<BS>"
1735 call assert_equal('up', getline(1))
1736 call assert_equal(6, g:CallCount)
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001737 bw!
Girish Palyacbe53192025-04-14 22:13:15 +02001738 set completeopt&
1739 set complete&
1740 set completefunc&
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00001741 delfunc Tcomplete
1742endfunc
1743
Girish Palyacbe53192025-04-14 22:13:15 +02001744" Test for 'cpt' user func that fails (return -2/-3) when refresh:always
1745func Test_cpt_func_refresh_always_fail()
1746 func! CompleteFail(retval, findstart, base)
1747 if a:findstart
1748 return a:retval
1749 endif
1750 call assert_equal(-999, a:findstart) " Should not reach here
1751 endfunc
1752 new
1753 set complete=ffunction('CompleteFail'\\,\ [-2])
1754 exe "normal! ia\<C-N>"
1755 %d
1756 set complete=ffunction('CompleteFail'\\,\ [-3])
1757 exe "normal! ia\<C-N>"
1758 bw!
1759
1760 func! CompleteFailIntermittent(retval, findstart, base)
1761 if a:findstart
1762 if g:CallCount == 2
1763 let g:CallCount += 1
1764 return a:retval
1765 endif
1766 return col('.') - 1
1767 endif
1768 let g:CallCount += 1
1769 let res = [[], ['foo', 'fbar'], ['foo1', 'foo2'], ['foofail'], ['fooo3']]
1770 return #{words: res[g:CallCount], refresh: 'always'}
1771 endfunc
1772 new
1773 set completeopt=menuone,noselect
1774 set complete=ffunction('CompleteFailIntermittent'\\,\ [-2])
1775 let g:CallCount = 0
1776 exe "normal! if\<C-N>\<c-r>=complete_info([\"items\"])\<cr>"
1777 call assert_match('''word'': ''foo''.*''word'': ''fbar''', getline(1))
1778 call assert_equal(1, g:CallCount)
1779 %d
1780 let g:CallCount = 0
1781 exe "normal! if\<C-N>o\<c-r>=complete_info([\"items\", \"selected\"])\<cr>"
1782 call assert_match('''selected'': -1.*''word'': ''foo1''.*''word'': ''foo2''', getline(1))
1783 call assert_equal(2, g:CallCount)
1784 %d
1785 set complete=ffunction('CompleteFailIntermittent'\\,\ [-3])
1786 let g:CallCount = 0
1787 exe "normal! if\<C-N>o\<c-r>=complete_info([\"items\", \"selected\"])\<cr>"
1788 call assert_match('''selected'': -1.*''word'': ''foo1''.*''word'': ''foo2''', getline(1))
1789 call assert_equal(2, g:CallCount)
1790 %d
1791 set complete=ffunction('CompleteFailIntermittent'\\,\ [-2])
1792 " completion mode is dismissed when there are no matches in list
1793 let g:CallCount = 0
1794 exe "normal! if\<C-N>oo\<c-r>=complete_info([\"items\"])\<cr>"
1795 call assert_equal('foo{''items'': []}', getline(1))
1796 call assert_equal(3, g:CallCount)
1797 %d
1798 let g:CallCount = 0
1799 exe "normal! if\<C-N>oo\<bs>\<c-r>=complete_info([\"items\"])\<cr>"
1800 call assert_equal('fo{''items'': []}', getline(1))
1801 call assert_equal(3, g:CallCount)
1802 %d
1803 " completion mode continues when matches from other sources present
1804 set complete=.,ffunction('CompleteFailIntermittent'\\,\ [-2])
1805 call setline(1, 'fooo1')
1806 let g:CallCount = 0
1807 exe "normal! Gof\<C-N>oo\<c-r>=complete_info([\"items\", \"selected\"])\<cr>"
1808 call assert_equal('foo{''selected'': -1, ''items'': [{''word'': ''fooo1'', ''menu'': '''', '
1809 \ . '''user_data'': '''', ''info'': '''', ''kind'': '''', ''abbr'': ''''}]}',
1810 \ getline(2))
1811 call assert_equal(3, g:CallCount)
1812 %d
1813 call setline(1, 'fooo1')
1814 let g:CallCount = 0
1815 exe "normal! Gof\<C-N>oo\<bs>\<c-r>=complete_info([\"items\"])\<cr>"
1816 call assert_match('''word'': ''fooo1''.*''word'': ''fooo3''', getline(2))
1817 call assert_equal(4, g:CallCount)
1818 %d
1819 " refresh will stop when -3 is returned
1820 set complete=.,,\ ffunction('CompleteFailIntermittent'\\,\ [-3])
1821 call setline(1, 'fooo1')
1822 let g:CallCount = 0
1823 exe "normal! Gof\<C-N>o\<bs>\<c-r>=complete_info([\"items\", \"selected\"])\<cr>"
1824 call assert_equal('f{''selected'': -1, ''items'': [{''word'': ''fooo1'', ''menu'': '''', '
1825 \ . '''user_data'': '''', ''info'': '''', ''kind'': '''', ''abbr'': ''''}]}',
1826 \ getline(2))
1827 call assert_equal(3, g:CallCount)
1828 %d
1829 call setline(1, 'fooo1')
1830 let g:CallCount = 0
1831 exe "normal! Gof\<C-N>oo\<bs>\<c-r>=complete_info([\"items\", \"selected\"])\<cr>"
1832 call assert_equal('fo{''selected'': -1, ''items'': [{''word'': ''fooo1'', ''menu'': '''', '
1833 \ . '''user_data'': '''', ''info'': '''', ''kind'': '''', ''abbr'': ''''}]}',
1834 \ getline(2))
1835 call assert_equal(3, g:CallCount)
1836 bw!
1837
1838 set complete& completeopt&
1839 delfunc CompleteFail
1840 delfunc CompleteFailIntermittent
1841endfunc
1842
1843" Select items before they are removed by refresh:always
1844func Test_cpt_select_item_refresh_always()
1845
1846 func CompleteMenuWords()
1847 let info = complete_info(["items", "selected"])
1848 call map(info.items, {_, v -> v.word})
1849 return info
1850 endfunc
1851
1852 func! CompleteItemsSelect(compl, findstart, base)
1853 if a:findstart
1854 return col('.') - 1
1855 endif
1856 let g:CallCount += 1
1857 if g:CallCount == 2
1858 return #{words: a:compl, refresh: 'always'}
1859 endif
1860 let res = [[], ['fo', 'foobar'], [], ['foo1', 'foo2']]
1861 return #{words: res[g:CallCount], refresh: 'always'}
1862 endfunc
1863
1864 new
1865 set complete=.,ffunction('CompleteItemsSelect'\\,\ [[]])
1866 call setline(1, "foobarbar")
1867 let g:CallCount = 0
1868 exe "normal! Gof\<c-n>\<c-n>\<c-r>=CompleteMenuWords()\<cr>"
1869 call assert_equal('fo{''selected'': 1, ''items'': [''foobarbar'', ''fo'', ''foobar'']}', getline(2))
1870 call assert_equal(1, g:CallCount)
1871 %d
1872 call setline(1, "foobarbar")
1873 let g:CallCount = 0
1874 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<c-r>=CompleteMenuWords()\<cr>"
1875 call assert_equal('fo{''selected'': 0, ''items'': [''fo'', ''foobar'', ''foobarbar'']}', getline(2))
1876 call assert_equal(1, g:CallCount)
1877 %d
1878 call setline(1, "foobarbar")
1879 let g:CallCount = 0
1880 exe "normal! Gof\<c-n>\<c-n>o\<c-r>=CompleteMenuWords()\<cr>"
1881 call assert_equal('foo{''selected'': -1, ''items'': []}' , getline(2))
1882 call assert_equal(1, g:CallCount)
1883 %d
1884 call setline(1, "foobarbar")
1885 let g:CallCount = 0
1886 exe "normal! Gof\<c-n>\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1887 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'']}', getline(2))
1888 call assert_equal(2, g:CallCount)
1889 %d
1890 call setline(1, "foobarbar")
1891 let g:CallCount = 0
1892 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1893 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'']}', getline(2))
1894 call assert_equal(2, g:CallCount)
1895
1896 %d
1897 set complete=.,ffunction('CompleteItemsSelect'\\,\ [['foonext']])
1898 call setline(1, "foobarbar")
1899 let g:CallCount = 0
1900 exe "normal! Gof\<c-n>\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1901 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'', ''foonext'']}', getline(2))
1902 call assert_equal(2, g:CallCount)
1903 %d
1904 call setline(1, "foobarbar")
1905 let g:CallCount = 0
1906 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1907 call assert_equal('f{''selected'': -1, ''items'': [''foonext'', ''foobarbar'']}', getline(2))
1908 call assert_equal(2, g:CallCount)
1909
1910 %d
1911 call setline(1, "foob")
1912 let g:CallCount = 0
1913 exe "normal! Gof\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1914 call assert_equal('foo{''selected'': 0, ''items'': [''foob'', ''foonext'']}', getline(2))
1915 call assert_equal(2, g:CallCount)
1916 %d
1917 call setline(1, "foob")
1918 let g:CallCount = 0
1919 exe "normal! Gof\<c-n>\<bs>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1920 call assert_equal('fo{''selected'': 0, ''items'': [''foob'', ''foo1'', ''foo2'']}', getline(2))
1921 call assert_equal(3, g:CallCount)
1922
1923 %d
1924 call setline(1, "foob")
1925 let g:CallCount = 0
1926 exe "normal! Gof\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1927 call assert_equal('foo{''selected'': 1, ''items'': [''foonext'', ''foob'']}', getline(2))
1928 call assert_equal(2, g:CallCount)
1929 %d
1930 call setline(1, "foob")
1931 let g:CallCount = 0
1932 exe "normal! Gof\<c-p>\<bs>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1933 call assert_equal('fo{''selected'': 2, ''items'': [''foo1'', ''foo2'', ''foob'']}', getline(2))
1934 call assert_equal(3, g:CallCount)
1935
1936 %d
1937 set complete=.,ffunction('CompleteItemsSelect'\\,\ [['fo'\\,\ 'foonext']])
1938 call setline(1, "foobarbar")
1939 let g:CallCount = 0
1940 exe "normal! Gof\<c-n>\<c-n>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1941 call assert_equal('f{''selected'': -1, ''items'': [''foobarbar'', ''fo'', ''foonext'']}', getline(2))
1942 call assert_equal(2, g:CallCount)
1943 %d
1944 call setline(1, "foobarbar")
1945 let g:CallCount = 0
1946 exe "normal! Gof\<c-p>\<c-p>\<c-p>\<bs>\<c-r>=CompleteMenuWords()\<cr>"
1947 call assert_equal('f{''selected'': -1, ''items'': [''fo'', ''foonext'', ''foobarbar'']}', getline(2))
1948 call assert_equal(2, g:CallCount)
1949 bw!
1950
1951 set complete&
1952 delfunc CompleteMenuWords
1953 delfunc CompleteItemsSelect
1954endfunc
1955
1956" Test two functions together, each returning refresh:always
1957func Test_cpt_multi_func_refresh_always()
1958
1959 func CompleteMenuMatches()
1960 let info = complete_info(["matches", "selected"])
1961 call map(info.matches, {_, v -> v.word})
1962 return info
1963 endfunc
1964
1965 func! CompleteItems1(findstart, base)
1966 if a:findstart
1967 return col('.') - 1
1968 endif
1969 let g:CallCount1 += 1
1970 let res = [[], [], ['foo1', 'foobar1'], [], ['foo11', 'foo12'], [], ['foo13', 'foo14']]
1971 return #{words: res[g:CallCount1], refresh: 'always'}
1972 endfunc
1973
1974 func! CompleteItems2(findstart, base)
1975 if a:findstart
1976 return col('.') - 1
1977 endif
1978 let g:CallCount2 += 1
1979 let res = [[], [], [], ['foo2', 'foobar2'], ['foo21', 'foo22'], ['foo23'], []]
1980 return #{words: res[g:CallCount2], refresh: 'always'}
1981 endfunc
1982
1983 set complete=
1984 exe "normal! if\<C-N>\<c-r>=CompleteMenuMatches()\<cr>"
1985 " \x0e is <c-n>
1986 call assert_equal("f\x0e" . '{''matches'': [], ''selected'': -1}', getline(1))
1987
1988 set completeopt=menuone,noselect
1989 set complete=fCompleteItems1,fCompleteItems2
1990
1991 new
1992 let g:CallCount1 = 0
1993 let g:CallCount2 = 0
1994 exe "normal! if\<c-n>o\<c-n>o\<c-r>=CompleteMenuMatches()\<cr>"
1995 call assert_equal('foo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1))
1996 call assert_equal(3, g:CallCount1)
1997 call assert_equal(3, g:CallCount2)
1998 %d
1999 let g:CallCount1 = 0
2000 let g:CallCount2 = 0
2001 exe "normal! if\<c-p>o\<c-p>o\<c-r>=CompleteMenuMatches()\<cr>"
2002 call assert_equal('foo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1))
2003 call assert_equal(3, g:CallCount1)
2004 call assert_equal(3, g:CallCount2)
2005 %d
2006 let g:CallCount1 = 0
2007 let g:CallCount2 = 0
2008 exe "normal! if\<c-p>\<c-r>=CompleteMenuMatches()\<cr>"
2009 call assert_equal('f{''matches'': [], ''selected'': -1}', getline(1))
2010 call assert_equal(1, g:CallCount1)
2011 call assert_equal(1, g:CallCount2)
2012 %d
2013 let g:CallCount1 = 1
2014 let g:CallCount2 = 1
2015 exe "normal! if\<c-n>\<c-r>=CompleteMenuMatches()\<cr>"
2016 call assert_equal('f{''matches'': [''foo1'', ''foobar1''], ''selected'': -1}', getline(1))
2017 call assert_equal(2, g:CallCount2)
2018 call assert_equal(2, g:CallCount2)
2019 %d
2020 let g:CallCount1 = 1
2021 let g:CallCount2 = 1
2022 exe "normal! if\<c-n>o\<c-r>=CompleteMenuMatches()\<cr>"
2023 call assert_equal('fo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1))
2024 call assert_equal(3, g:CallCount2)
2025 call assert_equal(3, g:CallCount2)
2026 %d
2027 let g:CallCount1 = 1
2028 let g:CallCount2 = 1
2029 exe "normal! if\<c-p>o\<c-r>=CompleteMenuMatches()\<cr>"
2030 call assert_equal('fo{''matches'': [''foo2'', ''foobar2''], ''selected'': -1}', getline(1))
2031 call assert_equal(3, g:CallCount2)
2032 call assert_equal(3, g:CallCount2)
2033 %d
2034 let g:CallCount1 = 1
2035 let g:CallCount2 = 1
2036 exe "normal! if\<c-n>oo\<c-r>=CompleteMenuMatches()\<cr>"
2037 call assert_equal('foo{''matches'': [''foo11'', ''foo12'', ''foo21'', ''foo22''], ''selected'': -1}', getline(1))
2038 call assert_equal(4, g:CallCount2)
2039 call assert_equal(4, g:CallCount2)
2040 %d
2041 let g:CallCount1 = 1
2042 let g:CallCount2 = 1
2043 exe "normal! if\<c-n>oo\<bs>\<c-r>=CompleteMenuMatches()\<cr>"
2044 call assert_equal('fo{''matches'': [''foo23''], ''selected'': -1}', getline(1))
2045 call assert_equal(5, g:CallCount2)
2046 call assert_equal(5, g:CallCount2)
2047 %d
2048 let g:CallCount1 = 1
2049 let g:CallCount2 = 1
2050 exe "normal! if\<c-p>oo\<bs>\<c-r>=CompleteMenuMatches()\<cr>"
2051 call assert_equal('fo{''matches'': [''foo23''], ''selected'': -1}', getline(1))
2052 call assert_equal(5, g:CallCount2)
2053 call assert_equal(5, g:CallCount2)
2054 %d
2055 let g:CallCount1 = 1
2056 let g:CallCount2 = 1
2057 exe "normal! if\<c-n>oo\<bs>o\<c-r>=CompleteMenuMatches()\<cr>"
2058 call assert_equal('foo{''matches'': [''foo13'', ''foo14''], ''selected'': -1}', getline(1))
2059 call assert_equal(6, g:CallCount2)
2060 call assert_equal(6, g:CallCount2)
2061 bw!
2062
2063 set complete& completeopt&
2064 delfunc CompleteMenuMatches
2065 delfunc CompleteItems1
2066 delfunc CompleteItems2
2067endfunc
2068
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00002069" Test for completing from a thesaurus file without read permission
2070func Test_complete_unreadable_thesaurus_file()
2071 CheckUnix
2072 CheckNotRoot
2073
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01002074 call writefile(['about', 'above'], 'Xunrfile', 'D')
Bram Moolenaarb18b4962022-09-02 21:55:50 +01002075 call setfperm('Xunrfile', '---r--r--')
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00002076 new
2077 set complete=sXfile
2078 exe "normal! ia\<C-P>"
2079 call assert_equal('a', getline(1))
Bram Moolenaar7dd5a782022-09-29 21:01:57 +01002080
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00002081 bw!
Yegappan Lakshmanan37079142022-01-08 10:38:48 +00002082 set complete&
2083endfunc
2084
Bram Moolenaarcc233582020-12-12 13:32:07 +01002085" Test to ensure 'Scanning...' messages are not recorded in messages history
2086func Test_z1_complete_no_history()
2087 new
2088 messages clear
2089 let currmess = execute('messages')
2090 setlocal dictionary=README.txt
2091 exe "normal owh\<C-X>\<C-K>"
2092 exe "normal owh\<C-N>"
2093 call assert_equal(currmess, execute('messages'))
Bram Moolenaard979d642022-03-04 14:51:06 +00002094 bwipe!
2095endfunc
2096
2097" A mapping is not used for the key after CTRL-X.
2098func Test_no_mapping_for_ctrl_x_key()
2099 new
zeertzjq75f4baf2022-09-24 14:08:23 +01002100 inoremap <buffer> <C-K> <Cmd>let was_mapped = 'yes'<CR>
Bram Moolenaard979d642022-03-04 14:51:06 +00002101 setlocal dictionary=README.txt
2102 call feedkeys("aexam\<C-X>\<C-K> ", 'xt')
2103 call assert_equal('example ', getline(1))
2104 call assert_false(exists('was_mapped'))
2105 bwipe!
Bram Moolenaarcc233582020-12-12 13:32:07 +01002106endfunc
2107
Girish Palyacbe53192025-04-14 22:13:15 +02002108" Test for different ways of setting a function in 'complete' option
2109func Test_cpt_func_callback()
2110 func CompleteFunc1(callnr, findstart, base)
2111 call add(g:CompleteFunc1Args, [a:callnr, a:findstart, a:base])
2112 return a:findstart ? 0 : []
2113 endfunc
2114 func CompleteFunc2(findstart, base)
2115 call add(g:CompleteFunc2Args, [a:findstart, a:base])
2116 return a:findstart ? 0 : []
2117 endfunc
2118
2119 let lines =<< trim END
2120 #" Test for using a global function name
2121 set complete=fg:CompleteFunc2
2122 new
2123 call setline(1, 'global')
2124 LET g:CompleteFunc2Args = []
2125 call feedkeys("A\<C-N>\<Esc>", 'x')
2126 call assert_equal([[1, ''], [0, 'global']], g:CompleteFunc2Args)
2127 set complete&
2128 bw!
2129
2130 #" Test for using a function()
2131 set complete=ffunction('g:CompleteFunc1'\\,\ [10])
2132 new
2133 call setline(1, 'one')
2134 LET g:CompleteFunc1Args = []
2135 call feedkeys("A\<C-N>\<Esc>", 'x')
2136 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:CompleteFunc1Args)
2137 set complete&
2138 bw!
2139
2140 #" Using a funcref variable
2141 set complete=ffuncref('g:CompleteFunc1'\\,\ [11])
2142 new
2143 call setline(1, 'two')
2144 LET g:CompleteFunc1Args = []
2145 call feedkeys("A\<C-N>\<Esc>", 'x')
2146 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:CompleteFunc1Args)
2147 set complete&
2148 bw!
2149
2150 END
2151 call v9.CheckLegacyAndVim9Success(lines)
2152
2153 " Test for using a script-local function name
2154 func s:CompleteFunc3(findstart, base)
2155 call add(g:CompleteFunc3Args, [a:findstart, a:base])
2156 return a:findstart ? 0 : []
2157 endfunc
2158 set complete=fs:CompleteFunc3
2159 new
2160 call setline(1, 'script1')
2161 let g:CompleteFunc3Args = []
2162 call feedkeys("A\<C-N>\<Esc>", 'x')
2163 call assert_equal([[1, ''], [0, 'script1']], g:CompleteFunc3Args)
2164 set complete&
2165 bw!
2166
2167 let &complete = 'fs:CompleteFunc3'
2168 new
2169 call setline(1, 'script2')
2170 let g:CompleteFunc3Args = []
2171 call feedkeys("A\<C-N>\<Esc>", 'x')
2172 call assert_equal([[1, ''], [0, 'script2']], g:CompleteFunc3Args)
2173 bw!
2174 delfunc s:CompleteFunc3
2175 set complete&
2176
2177 " In Vim9 script s: can be omitted
2178 let lines =<< trim END
2179 vim9script
2180 var CompleteFunc4Args = []
2181 def CompleteFunc4(findstart: bool, base: string): any
2182 add(CompleteFunc4Args, [findstart, base])
2183 return findstart ? 0 : []
2184 enddef
2185 set complete=fCompleteFunc4
2186 new
2187 setline(1, 'script1')
2188 feedkeys("A\<C-N>\<Esc>", 'x')
2189 assert_equal([[1, ''], [0, 'script1']], CompleteFunc4Args)
2190 set complete&
2191 bw!
2192 END
2193 call v9.CheckScriptSuccess(lines)
2194
2195 " Vim9 tests
2196 let lines =<< trim END
2197 vim9script
2198
2199 def Vim9CompleteFunc(callnr: number, findstart: number, base: string): any
2200 add(g:Vim9completeFuncArgs, [callnr, findstart, base])
2201 return findstart ? 0 : []
2202 enddef
2203
2204 # Test for using a def function with completefunc
2205 set complete=ffunction('Vim9CompleteFunc'\\,\ [60])
2206 new | only
2207 setline(1, 'one')
2208 g:Vim9completeFuncArgs = []
2209 feedkeys("A\<C-N>\<Esc>", 'x')
2210 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9completeFuncArgs)
2211 bw!
2212
2213 # Test for using a global function name
2214 &complete = 'fg:CompleteFunc2'
2215 new | only
2216 setline(1, 'two')
2217 g:CompleteFunc2Args = []
2218 feedkeys("A\<C-N>\<Esc>", 'x')
2219 assert_equal([[1, ''], [0, 'two']], g:CompleteFunc2Args)
2220 bw!
2221
2222 # Test for using a script-local function name
2223 def LocalCompleteFunc(findstart: number, base: string): any
2224 add(g:LocalCompleteFuncArgs, [findstart, base])
2225 return findstart ? 0 : []
2226 enddef
2227 &complete = 'fLocalCompleteFunc'
2228 new | only
2229 setline(1, 'three')
2230 g:LocalCompleteFuncArgs = []
2231 feedkeys("A\<C-N>\<Esc>", 'x')
2232 assert_equal([[1, ''], [0, 'three']], g:LocalCompleteFuncArgs)
2233 bw!
2234 END
2235 call v9.CheckScriptSuccess(lines)
2236
2237 " cleanup
2238 set completefunc& complete&
2239 delfunc CompleteFunc1
2240 delfunc CompleteFunc2
2241 unlet g:CompleteFunc1Args g:CompleteFunc2Args
2242 %bw!
2243endfunc
2244
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002245" Test for different ways of setting the 'completefunc' option
2246func Test_completefunc_callback()
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002247 func CompleteFunc1(callnr, findstart, base)
2248 call add(g:CompleteFunc1Args, [a:callnr, a:findstart, a:base])
2249 return a:findstart ? 0 : []
2250 endfunc
2251 func CompleteFunc2(findstart, base)
2252 call add(g:CompleteFunc2Args, [a:findstart, a:base])
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002253 return a:findstart ? 0 : []
2254 endfunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002255
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002256 let lines =<< trim END
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002257 #" Test for using a global function name
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002258 LET &completefunc = 'g:CompleteFunc2'
2259 new
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002260 call setline(1, 'global')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002261 LET g:CompleteFunc2Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002262 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002263 call assert_equal([[1, ''], [0, 'global']], g:CompleteFunc2Args)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002264 bw!
2265
2266 #" Test for using a function()
2267 set completefunc=function('g:CompleteFunc1',\ [10])
2268 new
2269 call setline(1, 'one')
2270 LET g:CompleteFunc1Args = []
2271 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2272 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002273 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002274
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002275 #" Using a funcref variable to set 'completefunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002276 VAR Fn = function('g:CompleteFunc1', [11])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002277 LET &completefunc = Fn
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002278 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002279 call setline(1, 'two')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002280 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002281 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002282 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002283 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002284
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002285 #" Using string(funcref_variable) to set 'completefunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002286 LET Fn = function('g:CompleteFunc1', [12])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002287 LET &completefunc = string(Fn)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002288 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002289 call setline(1, 'two')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002290 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002291 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002292 call assert_equal([[12, 1, ''], [12, 0, 'two']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002293 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002294
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002295 #" Test for using a funcref()
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002296 set completefunc=funcref('g:CompleteFunc1',\ [13])
2297 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002298 call setline(1, 'three')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002299 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002300 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002301 call assert_equal([[13, 1, ''], [13, 0, 'three']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002302 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002303
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002304 #" Using a funcref variable to set 'completefunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002305 LET Fn = funcref('g:CompleteFunc1', [14])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002306 LET &completefunc = Fn
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002307 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002308 call setline(1, 'four')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002309 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002310 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002311 call assert_equal([[14, 1, ''], [14, 0, 'four']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002312 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002313
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002314 #" Using a string(funcref_variable) to set 'completefunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002315 LET Fn = funcref('g:CompleteFunc1', [15])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002316 LET &completefunc = string(Fn)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002317 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002318 call setline(1, 'four')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002319 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002320 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002321 call assert_equal([[15, 1, ''], [15, 0, 'four']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002322 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002323
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002324 #" Test for using a lambda function with set
Bram Moolenaar62aec932022-01-29 21:45:34 +00002325 VAR optval = "LSTART a, b LMIDDLE g:CompleteFunc1(16, a, b) LEND"
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002326 LET optval = substitute(optval, ' ', '\\ ', 'g')
2327 exe "set completefunc=" .. optval
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002328 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002329 call setline(1, 'five')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002330 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002331 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002332 call assert_equal([[16, 1, ''], [16, 0, 'five']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002333 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002334
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002335 #" Set 'completefunc' to a lambda expression
Bram Moolenaar62aec932022-01-29 21:45:34 +00002336 LET &completefunc = LSTART a, b LMIDDLE g:CompleteFunc1(17, a, b) LEND
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002337 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002338 call setline(1, 'six')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002339 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002340 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002341 call assert_equal([[17, 1, ''], [17, 0, 'six']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002342 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002343
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002344 #" Set 'completefunc' to string(lambda_expression)
Bram Moolenaar62aec932022-01-29 21:45:34 +00002345 LET &completefunc = 'LSTART a, b LMIDDLE g:CompleteFunc1(18, a, b) LEND'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002346 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002347 call setline(1, 'six')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002348 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002349 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002350 call assert_equal([[18, 1, ''], [18, 0, 'six']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002351 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002352
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002353 #" Set 'completefunc' to a variable with a lambda expression
Bram Moolenaar62aec932022-01-29 21:45:34 +00002354 VAR Lambda = LSTART a, b LMIDDLE g:CompleteFunc1(19, a, b) LEND
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002355 LET &completefunc = Lambda
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002356 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002357 call setline(1, 'seven')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002358 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002359 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002360 call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002361 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002362
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002363 #" Set 'completefunc' to a string(variable with a lambda expression)
Bram Moolenaar62aec932022-01-29 21:45:34 +00002364 LET Lambda = LSTART a, b LMIDDLE g:CompleteFunc1(20, a, b) LEND
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002365 LET &completefunc = string(Lambda)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002366 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002367 call setline(1, 'seven')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002368 LET g:CompleteFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002369 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002370 call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:CompleteFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002371 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002372
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002373 #" Test for using a lambda function with incorrect return value
2374 LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
2375 LET &completefunc = Lambda
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002376 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002377 call setline(1, 'eight')
2378 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2379 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002380
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002381 #" Test for clearing the 'completefunc' option
2382 set completefunc=''
2383 set completefunc&
2384 call assert_fails("set completefunc=function('abc')", "E700:")
2385 call assert_fails("set completefunc=funcref('abc')", "E700:")
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002386
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002387 #" set 'completefunc' to a non-existing function
Bram Moolenaar848fadd2022-01-30 15:28:30 +00002388 set completefunc=g:CompleteFunc2
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002389 call setline(1, 'five')
2390 call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
2391 call assert_fails("LET &completefunc = function('NonExistingFunc')", 'E700:')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002392 LET g:CompleteFunc2Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002393 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002394 call assert_equal([[1, ''], [0, 'five']], g:CompleteFunc2Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002395 bw!
2396 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00002397 call v9.CheckLegacyAndVim9Success(lines)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002398
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002399 " Test for using a script-local function name
2400 func s:CompleteFunc3(findstart, base)
2401 call add(g:CompleteFunc3Args, [a:findstart, a:base])
2402 return a:findstart ? 0 : []
2403 endfunc
2404 set completefunc=s:CompleteFunc3
2405 new
2406 call setline(1, 'script1')
2407 let g:CompleteFunc3Args = []
2408 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2409 call assert_equal([[1, ''], [0, 'script1']], g:CompleteFunc3Args)
2410 bw!
2411
2412 let &completefunc = 's:CompleteFunc3'
2413 new
2414 call setline(1, 'script2')
2415 let g:CompleteFunc3Args = []
2416 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2417 call assert_equal([[1, ''], [0, 'script2']], g:CompleteFunc3Args)
2418 bw!
2419 delfunc s:CompleteFunc3
2420
Bram Moolenaar1fca5f32022-02-18 17:50:47 +00002421 " In Vim9 script s: can be omitted
2422 let lines =<< trim END
2423 vim9script
2424 var CompleteFunc4Args = []
2425 def CompleteFunc4(findstart: bool, base: string): any
2426 add(CompleteFunc4Args, [findstart, base])
2427 return findstart ? 0 : []
2428 enddef
2429 set completefunc=CompleteFunc4
2430 new
2431 setline(1, 'script1')
2432 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2433 assert_equal([[1, ''], [0, 'script1']], CompleteFunc4Args)
2434 bw!
2435 END
2436 call v9.CheckScriptSuccess(lines)
2437
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002438 " invalid return value
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002439 let &completefunc = {a -> 'abc'}
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002440 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2441
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002442 " Using Vim9 lambda expression in legacy context should fail
Bram Moolenaar62aec932022-01-29 21:45:34 +00002443 set completefunc=(a,\ b)\ =>\ g:CompleteFunc1(21,\ a,\ b)
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002444 new | only
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002445 let g:CompleteFunc1Args = []
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002446 call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002447 call assert_equal([], g:CompleteFunc1Args)
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002448
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002449 " set 'completefunc' to a partial with dict. This used to cause a crash.
2450 func SetCompleteFunc()
2451 let params = {'complete': function('g:DictCompleteFunc')}
2452 let &completefunc = params.complete
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002453 endfunc
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002454 func g:DictCompleteFunc(_) dict
2455 endfunc
2456 call SetCompleteFunc()
2457 new
2458 call SetCompleteFunc()
2459 bw
2460 call test_garbagecollect_now()
2461 new
2462 set completefunc=
2463 wincmd w
2464 set completefunc=
2465 %bw!
2466 delfunc g:DictCompleteFunc
2467 delfunc SetCompleteFunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002468
2469 " Vim9 tests
2470 let lines =<< trim END
2471 vim9script
2472
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002473 def Vim9CompleteFunc(callnr: number, findstart: number, base: string): any
2474 add(g:Vim9completeFuncArgs, [callnr, findstart, base])
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002475 return findstart ? 0 : []
2476 enddef
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002477
2478 # Test for using a def function with completefunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002479 set completefunc=function('Vim9CompleteFunc',\ [60])
2480 new | only
2481 setline(1, 'one')
2482 g:Vim9completeFuncArgs = []
2483 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2484 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9completeFuncArgs)
2485 bw!
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002486
2487 # Test for using a global function name
2488 &completefunc = g:CompleteFunc2
2489 new | only
2490 setline(1, 'two')
2491 g:CompleteFunc2Args = []
2492 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2493 assert_equal([[1, ''], [0, 'two']], g:CompleteFunc2Args)
2494 bw!
2495
2496 # Test for using a script-local function name
Bram Moolenaar62b191c2022-02-12 20:34:50 +00002497 def LocalCompleteFunc(findstart: number, base: string): any
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002498 add(g:LocalCompleteFuncArgs, [findstart, base])
2499 return findstart ? 0 : []
2500 enddef
Bram Moolenaar62b191c2022-02-12 20:34:50 +00002501 &completefunc = LocalCompleteFunc
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002502 new | only
2503 setline(1, 'three')
2504 g:LocalCompleteFuncArgs = []
2505 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
2506 assert_equal([[1, ''], [0, 'three']], g:LocalCompleteFuncArgs)
2507 bw!
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002508 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00002509 call v9.CheckScriptSuccess(lines)
Yegappan Lakshmanan4dc24eb2021-12-07 12:23:57 +00002510
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002511 " cleanup
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002512 set completefunc&
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002513 delfunc CompleteFunc1
2514 delfunc CompleteFunc2
2515 unlet g:CompleteFunc1Args g:CompleteFunc2Args
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002516 %bw!
2517endfunc
2518
2519" Test for different ways of setting the 'omnifunc' option
2520func Test_omnifunc_callback()
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002521 func OmniFunc1(callnr, findstart, base)
2522 call add(g:OmniFunc1Args, [a:callnr, a:findstart, a:base])
2523 return a:findstart ? 0 : []
2524 endfunc
2525 func OmniFunc2(findstart, base)
2526 call add(g:OmniFunc2Args, [a:findstart, a:base])
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002527 return a:findstart ? 0 : []
2528 endfunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002529
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002530 let lines =<< trim END
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002531 #" Test for using a function name
2532 LET &omnifunc = 'g:OmniFunc2'
2533 new
2534 call setline(1, 'zero')
2535 LET g:OmniFunc2Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002536 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002537 call assert_equal([[1, ''], [0, 'zero']], g:OmniFunc2Args)
2538 bw!
2539
2540 #" Test for using a function()
2541 set omnifunc=function('g:OmniFunc1',\ [10])
2542 new
2543 call setline(1, 'one')
2544 LET g:OmniFunc1Args = []
2545 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2546 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002547 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002548
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002549 #" Using a funcref variable to set 'omnifunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002550 VAR Fn = function('g:OmniFunc1', [11])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002551 LET &omnifunc = Fn
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002552 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002553 call setline(1, 'two')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002554 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002555 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002556 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002557 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002558
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002559 #" Using a string(funcref_variable) to set 'omnifunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002560 LET Fn = function('g:OmniFunc1', [12])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002561 LET &omnifunc = string(Fn)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002562 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002563 call setline(1, 'two')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002564 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002565 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002566 call assert_equal([[12, 1, ''], [12, 0, 'two']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002567 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002568
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002569 #" Test for using a funcref()
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002570 set omnifunc=funcref('g:OmniFunc1',\ [13])
2571 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002572 call setline(1, 'three')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002573 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002574 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002575 call assert_equal([[13, 1, ''], [13, 0, 'three']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002576 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002577
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002578 #" Use let to set 'omnifunc' to a funcref
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002579 LET Fn = funcref('g:OmniFunc1', [14])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002580 LET &omnifunc = Fn
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002581 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002582 call setline(1, 'four')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002583 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002584 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002585 call assert_equal([[14, 1, ''], [14, 0, 'four']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002586 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002587
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002588 #" Using a string(funcref) to set 'omnifunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002589 LET Fn = funcref("g:OmniFunc1", [15])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002590 LET &omnifunc = string(Fn)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002591 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002592 call setline(1, 'four')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002593 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002594 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002595 call assert_equal([[15, 1, ''], [15, 0, 'four']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002596 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002597
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002598 #" Test for using a lambda function with set
Bram Moolenaar62aec932022-01-29 21:45:34 +00002599 VAR optval = "LSTART a, b LMIDDLE g:OmniFunc1(16, a, b) LEND"
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002600 LET optval = substitute(optval, ' ', '\\ ', 'g')
2601 exe "set omnifunc=" .. optval
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002602 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002603 call setline(1, 'five')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002604 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002605 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002606 call assert_equal([[16, 1, ''], [16, 0, 'five']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002607 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002608
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002609 #" Set 'omnifunc' to a lambda expression
Bram Moolenaar62aec932022-01-29 21:45:34 +00002610 LET &omnifunc = LSTART a, b LMIDDLE g:OmniFunc1(17, a, b) LEND
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002611 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002612 call setline(1, 'six')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002613 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002614 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002615 call assert_equal([[17, 1, ''], [17, 0, 'six']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002616 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002617
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002618 #" Set 'omnifunc' to a string(lambda_expression)
Bram Moolenaar62aec932022-01-29 21:45:34 +00002619 LET &omnifunc = 'LSTART a, b LMIDDLE g:OmniFunc1(18, a, b) LEND'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002620 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002621 call setline(1, 'six')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002622 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002623 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002624 call assert_equal([[18, 1, ''], [18, 0, 'six']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002625 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002626
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002627 #" Set 'omnifunc' to a variable with a lambda expression
Bram Moolenaar62aec932022-01-29 21:45:34 +00002628 VAR Lambda = LSTART a, b LMIDDLE g:OmniFunc1(19, a, b) LEND
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002629 LET &omnifunc = Lambda
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002630 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002631 call setline(1, 'seven')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002632 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002633 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002634 call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002635 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002636
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002637 #" Set 'omnifunc' to a string(variable with a lambda expression)
Bram Moolenaar62aec932022-01-29 21:45:34 +00002638 LET Lambda = LSTART a, b LMIDDLE g:OmniFunc1(20, a, b) LEND
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002639 LET &omnifunc = string(Lambda)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002640 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002641 call setline(1, 'seven')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002642 LET g:OmniFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002643 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002644 call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:OmniFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002645 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002646
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002647 #" Test for using a lambda function with incorrect return value
2648 LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
2649 LET &omnifunc = Lambda
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002650 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002651 call setline(1, 'eight')
2652 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2653 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002654
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002655 #" Test for clearing the 'omnifunc' option
2656 set omnifunc=''
2657 set omnifunc&
2658 call assert_fails("set omnifunc=function('abc')", "E700:")
2659 call assert_fails("set omnifunc=funcref('abc')", "E700:")
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002660
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002661 #" set 'omnifunc' to a non-existing function
Bram Moolenaar848fadd2022-01-30 15:28:30 +00002662 set omnifunc=g:OmniFunc2
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002663 call setline(1, 'nine')
2664 call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
2665 call assert_fails("LET &omnifunc = function('NonExistingFunc')", 'E700:')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002666 LET g:OmniFunc2Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002667 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002668 call assert_equal([[1, ''], [0, 'nine']], g:OmniFunc2Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002669 bw!
2670 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00002671 call v9.CheckLegacyAndVim9Success(lines)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002672
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002673 " Test for using a script-local function name
2674 func s:OmniFunc3(findstart, base)
2675 call add(g:OmniFunc3Args, [a:findstart, a:base])
2676 return a:findstart ? 0 : []
2677 endfunc
2678 set omnifunc=s:OmniFunc3
2679 new
2680 call setline(1, 'script1')
2681 let g:OmniFunc3Args = []
2682 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2683 call assert_equal([[1, ''], [0, 'script1']], g:OmniFunc3Args)
2684 bw!
2685
2686 let &omnifunc = 's:OmniFunc3'
2687 new
2688 call setline(1, 'script2')
2689 let g:OmniFunc3Args = []
2690 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2691 call assert_equal([[1, ''], [0, 'script2']], g:OmniFunc3Args)
2692 bw!
2693 delfunc s:OmniFunc3
2694
2695 " invalid return value
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002696 let &omnifunc = {a -> 'abc'}
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002697 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2698
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002699 " Using Vim9 lambda expression in legacy context should fail
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002700 set omnifunc=(a,\ b)\ =>\ OmniFunc1(21,\ a,\ b)
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002701 new | only
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002702 let g:OmniFunc1Args = []
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002703 call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002704 call assert_equal([], g:OmniFunc1Args)
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002705
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002706 " set 'omnifunc' to a partial with dict. This used to cause a crash.
2707 func SetOmniFunc()
2708 let params = {'omni': function('g:DictOmniFunc')}
2709 let &omnifunc = params.omni
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002710 endfunc
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002711 func g:DictOmniFunc(_) dict
2712 endfunc
2713 call SetOmniFunc()
2714 new
2715 call SetOmniFunc()
2716 bw
2717 call test_garbagecollect_now()
2718 new
2719 set omnifunc=
2720 wincmd w
2721 set omnifunc=
2722 %bw!
2723 delfunc g:DictOmniFunc
2724 delfunc SetOmniFunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002725
2726 " Vim9 tests
2727 let lines =<< trim END
2728 vim9script
2729
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002730 def Vim9omniFunc(callnr: number, findstart: number, base: string): any
2731 add(g:Vim9omniFunc_Args, [callnr, findstart, base])
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002732 return findstart ? 0 : []
2733 enddef
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002734
2735 # Test for using a def function with omnifunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002736 set omnifunc=function('Vim9omniFunc',\ [60])
2737 new | only
2738 setline(1, 'one')
2739 g:Vim9omniFunc_Args = []
2740 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2741 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9omniFunc_Args)
2742 bw!
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002743
2744 # Test for using a global function name
2745 &omnifunc = g:OmniFunc2
2746 new | only
2747 setline(1, 'two')
2748 g:OmniFunc2Args = []
2749 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2750 assert_equal([[1, ''], [0, 'two']], g:OmniFunc2Args)
2751 bw!
2752
2753 # Test for using a script-local function name
Bram Moolenaar62b191c2022-02-12 20:34:50 +00002754 def LocalOmniFunc(findstart: number, base: string): any
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002755 add(g:LocalOmniFuncArgs, [findstart, base])
2756 return findstart ? 0 : []
2757 enddef
Bram Moolenaar62b191c2022-02-12 20:34:50 +00002758 &omnifunc = LocalOmniFunc
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002759 new | only
2760 setline(1, 'three')
2761 g:LocalOmniFuncArgs = []
2762 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
2763 assert_equal([[1, ''], [0, 'three']], g:LocalOmniFuncArgs)
2764 bw!
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002765 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00002766 call v9.CheckScriptSuccess(lines)
Yegappan Lakshmanan4dc24eb2021-12-07 12:23:57 +00002767
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002768 " cleanup
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002769 set omnifunc&
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002770 delfunc OmniFunc1
2771 delfunc OmniFunc2
2772 unlet g:OmniFunc1Args g:OmniFunc2Args
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002773 %bw!
2774endfunc
2775
2776" Test for different ways of setting the 'thesaurusfunc' option
2777func Test_thesaurusfunc_callback()
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002778 func TsrFunc1(callnr, findstart, base)
2779 call add(g:TsrFunc1Args, [a:callnr, a:findstart, a:base])
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002780 return a:findstart ? 0 : []
2781 endfunc
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002782 func TsrFunc2(findstart, base)
2783 call add(g:TsrFunc2Args, [a:findstart, a:base])
2784 return a:findstart ? 0 : ['sunday']
2785 endfunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00002786
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002787 let lines =<< trim END
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002788 #" Test for using a function name
2789 LET &thesaurusfunc = 'g:TsrFunc2'
2790 new
2791 call setline(1, 'zero')
2792 LET g:TsrFunc2Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002793 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002794 call assert_equal([[1, ''], [0, 'zero']], g:TsrFunc2Args)
2795 bw!
2796
2797 #" Test for using a function()
2798 set thesaurusfunc=function('g:TsrFunc1',\ [10])
2799 new
2800 call setline(1, 'one')
2801 LET g:TsrFunc1Args = []
2802 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
2803 call assert_equal([[10, 1, ''], [10, 0, 'one']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002804 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002805
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002806 #" Using a funcref variable to set 'thesaurusfunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002807 VAR Fn = function('g:TsrFunc1', [11])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002808 LET &thesaurusfunc = Fn
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002809 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002810 call setline(1, 'two')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002811 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002812 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002813 call assert_equal([[11, 1, ''], [11, 0, 'two']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002814 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002815
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002816 #" Using a string(funcref_variable) to set 'thesaurusfunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002817 LET Fn = function('g:TsrFunc1', [12])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002818 LET &thesaurusfunc = string(Fn)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002819 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002820 call setline(1, 'two')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002821 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002822 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002823 call assert_equal([[12, 1, ''], [12, 0, 'two']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002824 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002825
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002826 #" Test for using a funcref()
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002827 set thesaurusfunc=funcref('g:TsrFunc1',\ [13])
2828 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002829 call setline(1, 'three')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002830 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002831 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002832 call assert_equal([[13, 1, ''], [13, 0, 'three']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002833 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002834
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002835 #" Using a funcref variable to set 'thesaurusfunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002836 LET Fn = funcref('g:TsrFunc1', [14])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002837 LET &thesaurusfunc = Fn
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002838 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002839 call setline(1, 'four')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002840 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002841 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002842 call assert_equal([[14, 1, ''], [14, 0, 'four']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002843 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002844
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002845 #" Using a string(funcref_variable) to set 'thesaurusfunc'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002846 LET Fn = funcref('g:TsrFunc1', [15])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002847 LET &thesaurusfunc = string(Fn)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002848 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002849 call setline(1, 'four')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002850 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002851 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002852 call assert_equal([[15, 1, ''], [15, 0, 'four']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002853 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002854
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002855 #" Test for using a lambda function
Bram Moolenaar62aec932022-01-29 21:45:34 +00002856 VAR optval = "LSTART a, b LMIDDLE g:TsrFunc1(16, a, b) LEND"
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002857 LET optval = substitute(optval, ' ', '\\ ', 'g')
2858 exe "set thesaurusfunc=" .. optval
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002859 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002860 call setline(1, 'five')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002861 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002862 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002863 call assert_equal([[16, 1, ''], [16, 0, 'five']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002864 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002865
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002866 #" Test for using a lambda function with set
Bram Moolenaar62aec932022-01-29 21:45:34 +00002867 LET &thesaurusfunc = LSTART a, b LMIDDLE g:TsrFunc1(17, a, b) LEND
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002868 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002869 call setline(1, 'six')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002870 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002871 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002872 call assert_equal([[17, 1, ''], [17, 0, 'six']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002873 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002874
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002875 #" Set 'thesaurusfunc' to a string(lambda expression)
Bram Moolenaar62aec932022-01-29 21:45:34 +00002876 LET &thesaurusfunc = 'LSTART a, b LMIDDLE g:TsrFunc1(18, a, b) LEND'
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002877 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002878 call setline(1, 'six')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002879 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002880 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002881 call assert_equal([[18, 1, ''], [18, 0, 'six']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002882 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002883
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002884 #" Set 'thesaurusfunc' to a variable with a lambda expression
Bram Moolenaar62aec932022-01-29 21:45:34 +00002885 VAR Lambda = LSTART a, b LMIDDLE g:TsrFunc1(19, a, b) LEND
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002886 LET &thesaurusfunc = Lambda
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002887 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002888 call setline(1, 'seven')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002889 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002890 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002891 call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002892 bw!
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00002893
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002894 #" Set 'thesaurusfunc' to a string(variable with a lambda expression)
Bram Moolenaar62aec932022-01-29 21:45:34 +00002895 LET Lambda = LSTART a, b LMIDDLE g:TsrFunc1(20, a, b) LEND
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002896 LET &thesaurusfunc = string(Lambda)
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002897 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002898 call setline(1, 'seven')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002899 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002900 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002901 call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002902 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002903
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002904 #" Test for using a lambda function with incorrect return value
2905 LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
2906 LET &thesaurusfunc = Lambda
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002907 new
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002908 call setline(1, 'eight')
2909 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
2910 bw!
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002911
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002912 #" Test for clearing the 'thesaurusfunc' option
2913 set thesaurusfunc=''
2914 set thesaurusfunc&
2915 call assert_fails("set thesaurusfunc=function('abc')", "E700:")
2916 call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002917
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002918 #" set 'thesaurusfunc' to a non-existing function
Bram Moolenaar848fadd2022-01-30 15:28:30 +00002919 set thesaurusfunc=g:TsrFunc2
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002920 call setline(1, 'ten')
2921 call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:')
2922 call assert_fails("LET &thesaurusfunc = function('NonExistingFunc')", 'E700:')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002923 LET g:TsrFunc2Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002924 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002925 call assert_equal([[1, ''], [0, 'ten']], g:TsrFunc2Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002926 bw!
2927
2928 #" Use a buffer-local value and a global value
2929 set thesaurusfunc&
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002930 setlocal thesaurusfunc=function('g:TsrFunc1',\ [22])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002931 call setline(1, 'sun')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002932 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002933 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
2934 call assert_equal('sun', getline(1))
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002935 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002936 new
2937 call setline(1, 'sun')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002938 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002939 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
2940 call assert_equal('sun', getline(1))
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002941 call assert_equal([], g:TsrFunc1Args)
2942 set thesaurusfunc=function('g:TsrFunc1',\ [23])
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002943 wincmd w
2944 call setline(1, 'sun')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002945 LET g:TsrFunc1Args = []
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002946 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
2947 call assert_equal('sun', getline(1))
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00002948 call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:TsrFunc1Args)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002949 :%bw!
2950 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00002951 call v9.CheckLegacyAndVim9Success(lines)
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002952
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002953 " Test for using a script-local function name
2954 func s:TsrFunc3(findstart, base)
2955 call add(g:TsrFunc3Args, [a:findstart, a:base])
2956 return a:findstart ? 0 : []
2957 endfunc
zeertzjq6eda2692024-11-03 09:23:33 +01002958
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00002959 set tsrfu=s:TsrFunc3
2960 new
2961 call setline(1, 'script1')
2962 let g:TsrFunc3Args = []
2963 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
2964 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args)
2965 bw!
2966
2967 let &tsrfu = 's:TsrFunc3'
2968 new
2969 call setline(1, 'script2')
2970 let g:TsrFunc3Args = []
2971 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
2972 call assert_equal([[1, ''], [0, 'script2']], g:TsrFunc3Args)
2973 bw!
zeertzjq6eda2692024-11-03 09:23:33 +01002974
2975 new | only
2976 set thesaurusfunc=
2977 setlocal thesaurusfunc=NoSuchFunc
2978 setglobal thesaurusfunc=s:TsrFunc3
2979 call assert_equal('NoSuchFunc', &thesaurusfunc)
2980 call assert_equal('NoSuchFunc', &l:thesaurusfunc)
2981 call assert_equal('s:TsrFunc3', &g:thesaurusfunc)
2982 new | only
2983 call assert_equal('s:TsrFunc3', &thesaurusfunc)
2984 call assert_equal('s:TsrFunc3', &g:thesaurusfunc)
2985 call assert_equal('', &l:thesaurusfunc)
2986 call setline(1, 'script1')
2987 let g:TsrFunc3Args = []
2988 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
2989 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args)
2990 bw!
2991
2992 new | only
2993 set thesaurusfunc=
2994 setlocal thesaurusfunc=NoSuchFunc
2995 set thesaurusfunc=s:TsrFunc3
2996 call assert_equal('s:TsrFunc3', &thesaurusfunc)
2997 call assert_equal('s:TsrFunc3', &g:thesaurusfunc)
2998 call assert_equal('', &l:thesaurusfunc)
2999 call setline(1, 'script1')
3000 let g:TsrFunc3Args = []
3001 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
3002 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args)
3003 setlocal bufhidden=wipe
3004 new | only!
3005 call assert_equal('s:TsrFunc3', &thesaurusfunc)
3006 call assert_equal('s:TsrFunc3', &g:thesaurusfunc)
3007 call assert_equal('', &l:thesaurusfunc)
3008 call setline(1, 'script1')
3009 let g:TsrFunc3Args = []
3010 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
3011 call assert_equal([[1, ''], [0, 'script1']], g:TsrFunc3Args)
3012 bw!
3013
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00003014 delfunc s:TsrFunc3
3015
3016 " invalid return value
Yegappan Lakshmanan64095532021-12-06 11:03:55 +00003017 let &thesaurusfunc = {a -> 'abc'}
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00003018 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
3019
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00003020 " Using Vim9 lambda expression in legacy context should fail
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00003021 set thesaurusfunc=(a,\ b)\ =>\ TsrFunc1(21,\ a,\ b)
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00003022 new | only
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00003023 let g:TsrFunc1Args = []
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00003024 call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:')
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00003025 call assert_equal([], g:TsrFunc1Args)
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00003026 bw!
3027
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00003028 " set 'thesaurusfunc' to a partial with dict. This used to cause a crash.
3029 func SetTsrFunc()
3030 let params = {'thesaurus': function('g:DictTsrFunc')}
3031 let &thesaurusfunc = params.thesaurus
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00003032 endfunc
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00003033 func g:DictTsrFunc(_) dict
3034 endfunc
3035 call SetTsrFunc()
3036 new
3037 call SetTsrFunc()
3038 bw
3039 call test_garbagecollect_now()
3040 new
3041 set thesaurusfunc=
3042 wincmd w
3043 %bw!
3044 delfunc SetTsrFunc
3045
3046 " set buffer-local 'thesaurusfunc' to a partial with dict. This used to
3047 " cause a crash.
3048 func SetLocalTsrFunc()
3049 let params = {'thesaurus': function('g:DictTsrFunc')}
3050 let &l:thesaurusfunc = params.thesaurus
3051 endfunc
3052 call SetLocalTsrFunc()
3053 call test_garbagecollect_now()
3054 call SetLocalTsrFunc()
3055 set thesaurusfunc=
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00003056 bw!
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00003057 delfunc g:DictTsrFunc
3058 delfunc SetLocalTsrFunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00003059
3060 " Vim9 tests
3061 let lines =<< trim END
3062 vim9script
3063
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00003064 def Vim9tsrFunc(callnr: number, findstart: number, base: string): any
3065 add(g:Vim9tsrFunc_Args, [callnr, findstart, base])
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00003066 return findstart ? 0 : []
3067 enddef
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00003068
3069 # Test for using a def function with thesaurusfunc
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00003070 set thesaurusfunc=function('Vim9tsrFunc',\ [60])
3071 new | only
3072 setline(1, 'one')
3073 g:Vim9tsrFunc_Args = []
3074 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
3075 assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9tsrFunc_Args)
3076 bw!
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00003077
3078 # Test for using a global function name
3079 &thesaurusfunc = g:TsrFunc2
3080 new | only
3081 setline(1, 'two')
3082 g:TsrFunc2Args = []
3083 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
3084 assert_equal([[1, ''], [0, 'two']], g:TsrFunc2Args)
3085 bw!
3086
3087 # Test for using a script-local function name
Bram Moolenaar62b191c2022-02-12 20:34:50 +00003088 def LocalTsrFunc(findstart: number, base: string): any
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00003089 add(g:LocalTsrFuncArgs, [findstart, base])
3090 return findstart ? 0 : []
3091 enddef
Bram Moolenaar62b191c2022-02-12 20:34:50 +00003092 &thesaurusfunc = LocalTsrFunc
Yegappan Lakshmanandb1a4102021-12-17 16:21:20 +00003093 new | only
3094 setline(1, 'three')
3095 g:LocalTsrFuncArgs = []
3096 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
3097 assert_equal([[1, ''], [0, 'three']], g:LocalTsrFuncArgs)
3098 bw!
Yegappan Lakshmanan2172bff2021-12-08 10:46:21 +00003099 END
Bram Moolenaar62aec932022-01-29 21:45:34 +00003100 call v9.CheckScriptSuccess(lines)
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00003101
3102 " cleanup
3103 set thesaurusfunc&
Yegappan Lakshmanan04ef1fb2021-12-12 20:08:05 +00003104 delfunc TsrFunc1
3105 delfunc TsrFunc2
3106 unlet g:TsrFunc1Args g:TsrFunc2Args
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00003107 %bw!
3108endfunc
3109
Christian Brabandtac72c212022-04-07 21:00:53 +01003110func FooBarComplete(findstart, base)
3111 if a:findstart
3112 return col('.') - 1
3113 else
3114 return ["Foo", "Bar", "}"]
3115 endif
3116endfunc
3117
3118func Test_complete_smartindent()
3119 new
3120 setlocal smartindent completefunc=FooBarComplete
Christian Brabandtac72c212022-04-07 21:00:53 +01003121 exe "norm! o{\<cr>\<c-x>\<c-u>\<c-p>}\<cr>\<esc>"
3122 let result = getline(1,'$')
3123 call assert_equal(['', '{','}',''], result)
Girish Palyacbe53192025-04-14 22:13:15 +02003124 %d
3125 setlocal complete=fFooBarComplete
3126 exe "norm! o{\<cr>\<c-n>\<c-p>}\<cr>\<esc>"
3127 let result = getline(1,'$')
3128 call assert_equal(['', '{','}',''], result)
3129 %d
3130 setlocal complete=f
3131 exe "norm! o{\<cr>\<c-n>\<c-p>}\<cr>\<esc>"
3132 let result = getline(1,'$')
3133 call assert_equal(['', '{','}',''], result)
Christian Brabandtac72c212022-04-07 21:00:53 +01003134 bw!
3135 delfunction! FooBarComplete
3136endfunc
3137
Bram Moolenaarf12129f2022-07-01 19:58:30 +01003138func Test_complete_overrun()
3139 " this was going past the end of the copied text
3140 new
3141 sil norm si”0s0 
3142 bwipe!
3143endfunc
3144
Bram Moolenaarcaea6642022-07-07 19:42:04 +01003145func Test_infercase_very_long_line()
3146 " this was truncating the line when inferring case
3147 new
3148 let longLine = "blah "->repeat(300)
3149 let verylongLine = "blah "->repeat(400)
3150 call setline(1, verylongLine)
3151 call setline(2, longLine)
3152 set ic infercase
3153 exe "normal 2Go\<C-X>\<C-L>\<Esc>"
3154 call assert_equal(longLine, getline(3))
3155
Bram Moolenaarb9e71732022-07-23 06:53:08 +01003156 " check that the too long text is NUL terminated
3157 %del
3158 norm o
3159 norm 1987ax
3160 exec "norm ox\<C-X>\<C-L>"
3161 call assert_equal(repeat('x', 1987), getline(3))
3162
Bram Moolenaarcaea6642022-07-07 19:42:04 +01003163 bwipe!
3164 set noic noinfercase
3165endfunc
3166
Bram Moolenaarbaefde12022-07-07 19:59:49 +01003167func Test_ins_complete_add()
3168 " this was reading past the end of allocated memory
3169 new
3170 norm o
3171 norm 7o€€
3172 sil! norm o
3173
3174 bwipe!
3175endfunc
3176
Bram Moolenaara6f9e302022-07-28 21:51:37 +01003177func Test_ins_complete_end_of_line()
3178 " this was reading past the end of the line
Bram Moolenaar94722c52023-01-28 19:19:03 +00003179 new
Bram Moolenaara6f9e302022-07-28 21:51:37 +01003180 norm 8o€ý 
3181 sil! norm o
3182
3183 bwipe!
3184endfunc
Bram Moolenaarcaea6642022-07-07 19:42:04 +01003185
Bram Moolenaar0ff01832022-09-24 19:20:30 +01003186func s:Tagfunc(t,f,o)
3187 bwipe!
3188 return []
3189endfunc
3190
3191" This was using freed memory, since 'complete' was in a wiped out buffer.
3192" Also using a window that was closed.
3193func Test_tagfunc_wipes_out_buffer()
3194 new
3195 set complete=.,t,w,b,u,i
3196 se tagfunc=s:Tagfunc
3197 sil norm i
3198
3199 bwipe!
3200endfunc
3201
Bram Moolenaar6ac2e432023-03-31 19:32:29 +01003202func Test_ins_complete_popup_position()
3203 CheckScreendump
3204
3205 let lines =<< trim END
3206 vim9script
3207 set nowrap
3208 setline(1, ['one', 'two', 'this is line ', 'four'])
3209 prop_type_add('test', {highlight: 'Error'})
3210 prop_add(3, 0, {
3211 text_align: 'above',
3212 text: 'The quick brown fox jumps over the lazy dog',
3213 type: 'test'
3214 })
3215 END
3216 call writefile(lines, 'XinsPopup', 'D')
3217 let buf = RunVimInTerminal('-S XinsPopup', #{rows: 10})
3218
3219 call term_sendkeys(buf, "3GA\<C-N>")
3220 call VerifyScreenDump(buf, 'Test_ins_complete_popup_position_1', {})
3221
3222 call StopVimInTerminal(buf)
3223endfunc
3224
LemonBoy69fb5af2023-10-11 21:55:56 +02003225func GetCompleteInfo()
3226 let g:compl_info = complete_info()
3227 return ''
3228endfunc
3229
nwounkn2e3cd522023-10-17 11:05:38 +02003230func Test_completion_restart()
3231 new
3232 set complete=. completeopt=menuone backspace=2
3233 call setline(1, 'workhorse workhorse')
3234 exe "normal $a\<C-N>\<BS>\<BS>\<C-R>=GetCompleteInfo()\<CR>"
3235 call assert_equal(1, len(g:compl_info['items']))
3236 call assert_equal('workhorse', g:compl_info['items'][0]['word'])
3237 set complete& completeopt& backspace&
3238 bwipe!
3239endfunc
3240
LemonBoy69fb5af2023-10-11 21:55:56 +02003241func Test_complete_info_index()
3242 new
3243 call setline(1, ["aaa", "bbb", "ccc", "ddd", "eee", "fff"])
3244 inoremap <buffer><F5> <C-R>=GetCompleteInfo()<CR>
3245
3246 " Ensure 'index' in complete_info() is coherent with the 'items' array.
3247
3248 set completeopt=menu,preview
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003249 " Search forward
LemonBoy69fb5af2023-10-11 21:55:56 +02003250 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx')
3251 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003252 call assert_equal(6 , len(g:compl_info['items']))
LemonBoy69fb5af2023-10-11 21:55:56 +02003253 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
3254 call assert_equal("bbb", g:compl_info['items'][g:compl_info['selected']]['word'])
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003255 call assert_equal(6 , len(g:compl_info['items']))
3256 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
3257 call assert_equal("ccc", g:compl_info['items'][g:compl_info['selected']]['word'])
3258 call assert_equal(6 , len(g:compl_info['items']))
3259 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
3260 call assert_equal("ddd", g:compl_info['items'][g:compl_info['selected']]['word'])
3261 call assert_equal(6 , len(g:compl_info['items']))
3262 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
3263 call assert_equal("eee", g:compl_info['items'][g:compl_info['selected']]['word'])
3264 call assert_equal(6 , len(g:compl_info['items']))
3265 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
3266 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
3267 call assert_equal(6 , len(g:compl_info['items']))
3268 " Search forward: unselected item
3269 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
3270 call assert_equal(6 , len(g:compl_info['items']))
3271 call assert_equal(-1 , g:compl_info['selected'])
LemonBoy69fb5af2023-10-11 21:55:56 +02003272
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003273 " Search backward
LemonBoy69fb5af2023-10-11 21:55:56 +02003274 call feedkeys("Go\<C-X>\<C-P>\<F5>\<Esc>_dd", 'tx')
3275 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003276 call assert_equal(6 , len(g:compl_info['items']))
LemonBoy69fb5af2023-10-11 21:55:56 +02003277 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3278 call assert_equal("eee", g:compl_info['items'][g:compl_info['selected']]['word'])
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003279 call assert_equal(6 , len(g:compl_info['items']))
3280 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3281 call assert_equal("ddd", g:compl_info['items'][g:compl_info['selected']]['word'])
3282 call assert_equal(6 , len(g:compl_info['items']))
3283 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3284 call assert_equal("ccc", g:compl_info['items'][g:compl_info['selected']]['word'])
3285 call assert_equal(6 , len(g:compl_info['items']))
3286 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3287 call assert_equal("bbb", g:compl_info['items'][g:compl_info['selected']]['word'])
3288 call assert_equal(6 , len(g:compl_info['items']))
3289 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3290 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
3291 call assert_equal(6 , len(g:compl_info['items']))
3292 " search backwards: unselected item
3293 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3294 call assert_equal(6 , len(g:compl_info['items']))
3295 call assert_equal(-1 , g:compl_info['selected'])
3296
3297 " switch direction: forwards, then backwards
3298 call feedkeys("Go\<C-X>\<C-N>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3299 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
3300 call assert_equal(6 , len(g:compl_info['items']))
3301 " switch direction: forwards, then backwards, then forwards again
3302 call feedkeys("Go\<C-X>\<C-N>\<C-P>\<C-P>\<F5>\<Esc>_dd", 'tx')
3303 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-P>\<C-P>\<C-N>\<F5>\<Esc>_dd", 'tx')
3304 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
3305 call assert_equal(6 , len(g:compl_info['items']))
3306
3307 " switch direction: backwards, then forwards
3308 call feedkeys("Go\<C-X>\<C-P>\<C-N>\<C-N>\<F5>\<Esc>_dd", 'tx')
3309 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
3310 call assert_equal(6 , len(g:compl_info['items']))
3311 " switch direction: backwards, then forwards, then backwards again
3312 call feedkeys("Go\<C-X>\<C-P>\<C-P>\<C-N>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx')
3313 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
3314 call assert_equal(6 , len(g:compl_info['items']))
LemonBoy69fb5af2023-10-11 21:55:56 +02003315
3316 " Add 'noselect', check that 'selected' is -1 when nothing is selected.
3317 set completeopt+=noselect
3318 " Search forward.
3319 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx')
3320 call assert_equal(-1, g:compl_info['selected'])
3321
3322 " Search backward.
3323 call feedkeys("Go\<C-X>\<C-P>\<F5>\<Esc>_dd", 'tx')
3324 call assert_equal(-1, g:compl_info['selected'])
3325
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003326 call feedkeys("Go\<C-X>\<C-N>\<C-P>\<F5>\<Esc>_dd", 'tx')
Girish Palya8950bf72024-03-20 20:07:29 +01003327 call assert_equal(5, g:compl_info['selected'])
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003328 call assert_equal(6 , len(g:compl_info['items']))
3329 call assert_equal("fff", g:compl_info['items'][g:compl_info['selected']]['word'])
3330 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')
Christian Brabandt87ca5e82023-10-27 19:47:29 +02003331 call assert_equal("aaa", g:compl_info['items'][g:compl_info['selected']]['word'])
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003332 call assert_equal(6 , len(g:compl_info['items']))
Christian Brabandt57f9ce12023-11-04 09:58:14 +01003333 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>_dd", 'tx')
3334 call assert_equal(-1, g:compl_info['selected'])
3335 call assert_equal(6 , len(g:compl_info['items']))
Christian Brabandtdaef8c72023-10-27 19:16:26 +02003336
LemonBoy69fb5af2023-10-11 21:55:56 +02003337 set completeopt&
3338 bwipe!
3339endfunc
Bram Moolenaar0ff01832022-09-24 19:20:30 +01003340
Christian Brabandtfef66302024-01-29 21:46:58 +01003341func Test_complete_changed_complete_info()
3342 CheckRunVimInTerminal
3343 " this used to crash vim, see #13929
3344 let lines =<< trim END
3345 set completeopt=menuone
3346 autocmd CompleteChanged * call complete_info(['items'])
3347 call feedkeys("iii\<cr>\<c-p>")
3348 END
3349 call writefile(lines, 'Xsegfault', 'D')
3350 let buf = RunVimInTerminal('-S Xsegfault', #{rows: 5})
3351 call WaitForAssert({-> assert_match('^ii', term_getline(buf, 1))}, 1000)
3352 call StopVimInTerminal(buf)
3353endfunc
3354
zeertzjq0a419e02024-04-02 19:01:14 +02003355func Test_completefunc_first_call_complete_add()
3356 new
3357
3358 func Complete(findstart, base) abort
3359 if a:findstart
3360 let col = col('.')
3361 call complete_add('#')
3362 return col - 1
3363 else
3364 return []
3365 endif
3366 endfunc
3367
3368 set completeopt=longest completefunc=Complete
3369 " This used to cause heap-buffer-overflow
3370 call assert_fails('call feedkeys("ifoo#\<C-X>\<C-U>", "xt")', 'E840:')
3371
3372 delfunc Complete
3373 set completeopt& completefunc&
3374 bwipe!
3375endfunc
3376
glepnirf31cfa22025-03-06 21:59:13 +01003377func Test_complete_opt_fuzzy()
glepnira218cc62024-06-03 19:32:39 +02003378 func OnPumChange()
3379 let g:item = get(v:event, 'completed_item', {})
3380 let g:word = get(g:item, 'word', v:null)
glepnirc0b7ca42025-02-13 20:27:44 +01003381 let g:abbr = get(g:item, 'abbr', v:null)
3382 let g:selected = get(complete_info(['selected']), 'selected')
glepnira218cc62024-06-03 19:32:39 +02003383 endfunction
3384
3385 augroup AAAAA_Group
3386 au!
3387 autocmd CompleteChanged * :call OnPumChange()
3388 augroup END
3389
3390 func Omni_test(findstart, base)
3391 if a:findstart
3392 return col(".")
3393 endif
glepnirf400a0c2025-01-23 19:55:14 +01003394 return [#{word: "foo"}, #{word: "foobar"}, #{word: "fooBaz"}, #{word: "foobala"}, #{word: "你好吗"}, #{word: "我好"}]
glepnira218cc62024-06-03 19:32:39 +02003395 endfunc
zeertzjq551d8c32024-06-05 19:53:32 +02003396
glepnira218cc62024-06-03 19:32:39 +02003397 new
3398 set omnifunc=Omni_test
3399 set completeopt+=noinsert,fuzzy
3400 call feedkeys("Gi\<C-x>\<C-o>", 'tx')
3401 call assert_equal('foo', g:word)
3402 call feedkeys("S\<C-x>\<C-o>fb", 'tx')
3403 call assert_equal('fooBaz', g:word)
3404 call feedkeys("S\<C-x>\<C-o>fa", 'tx')
3405 call assert_equal('foobar', g:word)
3406 " select next
3407 call feedkeys("S\<C-x>\<C-o>fb\<C-n>", 'tx')
3408 call assert_equal('foobar', g:word)
zeertzjq551d8c32024-06-05 19:53:32 +02003409 " can cyclically select next
glepnira218cc62024-06-03 19:32:39 +02003410 call feedkeys("S\<C-x>\<C-o>fb\<C-n>\<C-n>\<C-n>", 'tx')
3411 call assert_equal(v:null, g:word)
3412 " select prev
3413 call feedkeys("S\<C-x>\<C-o>fb\<C-p>", 'tx')
3414 call assert_equal(v:null, g:word)
zeertzjq551d8c32024-06-05 19:53:32 +02003415 " can cyclically select prev
glepnira218cc62024-06-03 19:32:39 +02003416 call feedkeys("S\<C-x>\<C-o>fb\<C-p>\<C-p>\<C-p>\<C-p>", 'tx')
3417 call assert_equal('fooBaz', g:word)
3418
glepnirf94c9c42024-06-14 21:11:56 +02003419 func Comp()
3420 call complete(col('.'), ["fooBaz", "foobar", "foobala"])
3421 return ''
3422 endfunc
3423 call feedkeys("i\<C-R>=Comp()\<CR>", 'tx')
3424 call assert_equal('fooBaz', g:word)
3425
glepnira218cc62024-06-03 19:32:39 +02003426 " respect noselect
3427 set completeopt+=noselect
3428 call feedkeys("S\<C-x>\<C-o>fb", 'tx')
3429 call assert_equal(v:null, g:word)
3430 call feedkeys("S\<C-x>\<C-o>fb\<C-n>", 'tx')
3431 call assert_equal('fooBaz', g:word)
3432
glepnirf31cfa22025-03-06 21:59:13 +01003433 " test case for nosort option
3434 set cot=menuone,menu,noinsert,fuzzy,nosort
3435 " "fooBaz" should have a higher score when the leader is "fb".
3436 " With "nosort", "foobar" should still be shown first in the popup menu.
3437 call feedkeys("S\<C-x>\<C-o>fb", 'tx')
3438 call assert_equal('foobar', g:word)
3439 call feedkeys("S\<C-x>\<C-o>好", 'tx')
3440 call assert_equal("你好吗", g:word)
3441
3442 set cot+=noselect
3443 call feedkeys("S\<C-x>\<C-o>好", 'tx')
3444 call assert_equal(v:null, g:word)
3445 call feedkeys("S\<C-x>\<C-o>好\<C-N>", 'tx')
3446 call assert_equal('你好吗', g:word)
3447
3448 " "nosort" shouldn't enable fuzzy filtering when "fuzzy" isn't present.
3449 set cot=menuone,noinsert,nosort
3450 call feedkeys("S\<C-x>\<C-o>fooB\<C-Y>", 'tx')
3451 call assert_equal('fooBaz', getline('.'))
3452
3453 set cot=menuone,fuzzy,nosort
3454 func CompAnother()
3455 call complete(col('.'), [#{word: "do" }, #{word: "echo"}, #{word: "for (${1:expr1}, ${2:expr2}, ${3:expr3}) {\n\t$0\n}", abbr: "for" }, #{word: "foo"}])
3456 return ''
3457 endfunc
3458 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>", 'tx')
3459 call assert_equal("for", g:abbr)
3460 call assert_equal(2, g:selected)
3461
3462 set cot+=noinsert
3463 call feedkeys("i\<C-R>=CompAnother()\<CR>f", 'tx')
3464 call assert_equal("for", g:abbr)
3465 call assert_equal(2, g:selected)
3466
3467 set cot=menu,menuone,noselect,fuzzy
3468 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-N>\<C-N>\<C-N>\<C-N>", 'tx')
3469 call assert_equal("foo", g:word)
3470 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>", 'tx')
3471 call assert_equal("foo", g:word)
3472 call feedkeys("i\<C-R>=CompAnother()\<CR>\<C-P>\<C-P>", 'tx')
3473 call assert_equal("for", g:abbr)
3474
glepnire4e4d1c2025-04-02 20:18:25 +02003475 set cot=menu,fuzzy
3476 call feedkeys("Sblue\<CR>bar\<CR>b\<C-X>\<C-P>\<C-Y>\<ESC>", 'tx')
3477 call assert_equal('bar', getline('.'))
3478 call feedkeys("Sb\<C-X>\<C-N>\<C-Y>\<ESC>", 'tx')
3479 call assert_equal('blue', getline('.'))
glepnir3e50a282025-04-03 21:17:06 +02003480 call feedkeys("Sb\<C-X>\<C-P>\<C-N>\<C-Y>\<ESC>", 'tx')
3481 call assert_equal('b', getline('.'))
glepnire4e4d1c2025-04-02 20:18:25 +02003482
glepnirf31cfa22025-03-06 21:59:13 +01003483 " clean up
3484 set omnifunc=
3485 bw!
3486 set complete& completeopt&
3487 autocmd! AAAAA_Group
3488 augroup! AAAAA_Group
3489 delfunc OnPumChange
3490 delfunc Omni_test
3491 delfunc Comp
3492 unlet g:item
3493 unlet g:word
3494 unlet g:abbr
3495endfunc
3496
3497func Test_complete_fuzzy_collect()
3498 new
3499 set completefuzzycollect=keyword,files,whole_line
glepniraced8c22024-06-15 15:13:05 +02003500 call setline(1, ['hello help hero h'])
zeertzjqacc87462024-06-16 08:44:05 +02003501 " Use "!" flag of feedkeys() so that ex_normal_busy is not set and
3502 " ins_compl_check_keys() is not skipped.
3503 " Add a "0" after the <Esc> to avoid waiting for an escape sequence.
3504 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
glepniraced8c22024-06-15 15:13:05 +02003505 call assert_equal('hello help hero hello', getline('.'))
3506 set completeopt+=noinsert
3507 call setline(1, ['hello help hero h'])
zeertzjqacc87462024-06-16 08:44:05 +02003508 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
glepniraced8c22024-06-15 15:13:05 +02003509 call assert_equal('hello help hero h', getline('.'))
3510
glepnir8159fb12024-07-17 20:32:54 +02003511 set completeopt-=noinsert
3512 call setline(1, ['xyz yxz x'])
3513 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
3514 call assert_equal('xyz yxz xyz', getline('.'))
3515 " can fuzzy get yxz when use Ctrl-N twice
3516 call setline(1, ['xyz yxz x'])
3517 call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!')
3518 call assert_equal('xyz yxz yxz', getline('.'))
3519
3520 call setline(1, ['你好 你'])
3521 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
3522 call assert_equal('你好 你好', getline('.'))
3523 call setline(1, ['你的 我的 的'])
3524 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
3525 call assert_equal('你的 我的 你的', getline('.'))
3526 " can fuzzy get multiple-byte word when use Ctrl-N twice
3527 call setline(1, ['你的 我的 的'])
3528 call feedkeys("A\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!')
3529 call assert_equal('你的 我的 我的', getline('.'))
3530
glepnir8159fb12024-07-17 20:32:54 +02003531 " fuzzy on file
3532 call writefile([''], 'fobar', 'D')
3533 call writefile([''], 'foobar', 'D')
3534 call setline(1, ['fob'])
3535 call cursor(1, 1)
3536 call feedkeys("A\<C-X>\<C-f>\<Esc>0", 'tx!')
3537 call assert_equal('fobar', getline('.'))
3538 call feedkeys("Sfob\<C-X>\<C-f>\<C-N>\<Esc>0", 'tx!')
3539 call assert_equal('foobar', getline('.'))
glepnir0be03e12024-07-19 16:45:05 +02003540 call feedkeys("S../\<C-X>\<C-f>\<Esc>0", 'tx!')
3541 call assert_match('../*', getline('.'))
3542 call feedkeys("S../td\<C-X>\<C-f>\<Esc>0", 'tx!')
3543 call assert_match('../testdir', getline('.'))
glepnir8159fb12024-07-17 20:32:54 +02003544
3545 " can get completion from other buffer
glepnir8159fb12024-07-17 20:32:54 +02003546 vnew
3547 call setline(1, ["completeness,", "compatibility", "Composite", "Omnipotent"])
3548 wincmd p
3549 call feedkeys("Somp\<C-N>\<Esc>0", 'tx!')
3550 call assert_equal('completeness', getline('.'))
3551 call feedkeys("Somp\<C-N>\<C-N>\<Esc>0", 'tx!')
3552 call assert_equal('compatibility', getline('.'))
3553 call feedkeys("Somp\<C-P>\<Esc>0", 'tx!')
3554 call assert_equal('Omnipotent', getline('.'))
3555 call feedkeys("Somp\<C-P>\<C-P>\<Esc>0", 'tx!')
3556 call assert_equal('Composite', getline('.'))
glepnir0be03e12024-07-19 16:45:05 +02003557 call feedkeys("S omp\<C-N>\<Esc>0", 'tx!')
3558 call assert_equal(' completeness', getline('.'))
glepnir8159fb12024-07-17 20:32:54 +02003559
3560 " fuzzy on whole line completion
3561 call setline(1, ["world is on fire", "no one can save me but you", 'user can execute', ''])
3562 call cursor(4, 1)
3563 call feedkeys("Swio\<C-X>\<C-L>\<Esc>0", 'tx!')
3564 call assert_equal('world is on fire', getline('.'))
3565 call feedkeys("Su\<C-X>\<C-L>\<C-P>\<Esc>0", 'tx!')
3566 call assert_equal('no one can save me but you', getline('.'))
3567
glepnir7cfe6932024-09-15 20:06:28 +02003568 " issue #15412
3569 call setline(1, ['alpha bravio charlie'])
3570 call feedkeys("Salpha\<C-X>\<C-N>\<Esc>0", 'tx!')
3571 call assert_equal('alpha bravio', getline('.'))
3572 call feedkeys("Salp\<C-X>\<C-N>\<Esc>0", 'tx!')
3573 call assert_equal('alpha', getline('.'))
3574 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
3575 call assert_equal('alpha bravio', getline('.'))
3576 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
3577 call assert_equal('alpha bravio charlie', getline('.'))
3578
3579 set complete-=i
3580 call feedkeys("Salp\<C-X>\<C-N>\<Esc>0", 'tx!')
3581 call assert_equal('alpha', getline('.'))
3582 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
3583 call assert_equal('alpha bravio', getline('.'))
3584 call feedkeys("A\<C-X>\<C-N>\<Esc>0", 'tx!')
3585 call assert_equal('alpha bravio charlie', getline('.'))
3586
3587 call setline(1, ['alpha bravio charlie', 'alpha another'])
3588 call feedkeys("Salpha\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!')
3589 call assert_equal('alpha another', getline('.'))
3590 call setline(1, ['你好 我好', '你好 他好'])
3591 call feedkeys("S你好\<C-X>\<C-N>\<Esc>0", 'tx!')
3592 call assert_equal('你好 我好', getline('.'))
3593 call feedkeys("S你好\<C-X>\<C-N>\<C-N>\<Esc>0", 'tx!')
3594 call assert_equal('你好 他好', getline('.'))
3595
glepnir753794b2024-08-20 19:58:44 +02003596 " issue #15526
glepnirf31cfa22025-03-06 21:59:13 +01003597 set completeopt=menuone,menu,noselect
glepnir753794b2024-08-20 19:58:44 +02003598 call setline(1, ['Text', 'ToText', ''])
glepnir7cfe6932024-09-15 20:06:28 +02003599 call cursor(3, 1)
glepnir753794b2024-08-20 19:58:44 +02003600 call feedkeys("STe\<C-X>\<C-N>x\<CR>\<Esc>0", 'tx!')
glepnir07f0dbe2025-02-18 20:27:30 +01003601 call assert_equal('Tex', getline(line('.') - 1))
glepnir753794b2024-08-20 19:58:44 +02003602
glepnir53b14572025-03-12 21:28:39 +01003603 call setline(1, ['fuzzy', 'fuzzycollect', 'completefuzzycollect'])
3604 call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!')
3605 call assert_equal('fuzzycollect', getline(line('.') - 1))
3606 call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!')
3607 call assert_equal('completefuzzycollect', getline(line('.') - 1))
3608
glepnir58760162025-03-13 21:39:51 +01003609 " keywords in 'dictonary'
3610 call writefile(['hello', 'think'], 'test_dict.txt', 'D')
3611 set dict=test_dict.txt
3612 call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<CR>\<Esc>0", 'tx!')
3613 call assert_equal('hello', getline(line('.') - 1))
3614 call feedkeys("Sh\<C-X>\<C-K>\<C-N>\<C-N>\<CR>\<Esc>0", 'tx!')
3615 call assert_equal('think', getline(line('.') - 1))
3616
glepnir57530842025-03-21 17:16:21 +01003617 call setline(1, ['foo bar fuzzy', 'completefuzzycollect'])
3618 call feedkeys("Gofuzzy\<C-X>\<C-N>\<C-N>\<C-N>\<C-Y>\<Esc>0", 'tx!')
3619 call assert_equal('completefuzzycollect', getline('.'))
3620
glepnira218cc62024-06-03 19:32:39 +02003621 bw!
glepnir8159fb12024-07-17 20:32:54 +02003622 bw!
glepnir58760162025-03-13 21:39:51 +01003623 set dict&
glepnirf31cfa22025-03-06 21:59:13 +01003624 set completeopt& cfc& cpt&
glepnira218cc62024-06-03 19:32:39 +02003625endfunc
3626
glepnirf31cfa22025-03-06 21:59:13 +01003627func Test_cfc_with_longest()
3628 new
3629 set completefuzzycollect=keyword,files,whole_line
3630 set completeopt=menu,menuone,longest,fuzzy
3631
3632 " keyword
3633 exe "normal ggdGShello helio think h\<C-X>\<C-N>\<ESC>"
3634 call assert_equal("hello helio think hel", getline('.'))
3635 exe "normal hello helio think h\<C-X>\<C-P>\<ESC>"
3636 call assert_equal("hello helio think hel", getline('.'))
3637
3638 " skip non-consecutive prefixes
3639 exe "normal ggdGShello helio heo\<C-X>\<C-N>\<ESC>"
3640 call assert_equal("hello helio heo", getline('.'))
3641
3642 " kdcit
3643 call writefile(['help'], 'test_keyword.txt', 'D')
3644 set complete=ktest_keyword.txt
3645 exe "normal ggdGSh\<C-N>\<ESC>"
3646 " auto insert help when only have one match
3647 call assert_equal("help", getline('.'))
3648 call writefile(['hello', 'help', 'think'], 'xtest_keyword.txt', 'D')
3649 set complete=kxtest_keyword.txt
3650 " auto insert hel
3651 exe "normal ggdGSh\<C-N>\<ESC>"
3652 call assert_equal("hel", getline('.'))
3653
3654 " line start with a space
3655 call writefile([' hello'], 'test_case1.txt', 'D')
3656 set complete=ktest_case1.txt
3657 exe "normal ggdGSh\<C-N>\<ESC>"
3658 call assert_equal("hello", getline('.'))
3659
3660 " multiple matches
3661 set complete=ktest_case2.txt
3662 call writefile([' hello help what'], 'test_case2.txt', 'D')
3663 exe "normal ggdGSh\<C-N>\<C-N>\<C-N>\<C-N>\<ESC>"
3664 call assert_equal("what", getline('.'))
3665
3666 " multiple lines of matches
3667 set complete=ktest_case3.txt
3668 call writefile([' hello help what', 'hola', ' hey'], 'test_case3.txt', 'D')
3669 exe "normal ggdGSh\<C-N>\<C-N>\<ESC>"
3670 call assert_equal("hey", getline('.'))
3671 exe "normal ggdGSh\<C-N>\<C-N>\<C-N>\<C-N>\<ESC>"
3672 call assert_equal("hola", getline('.'))
3673
3674 set complete=ktest_case4.txt
3675 call writefile([' auto int enum register', 'why'], 'test_case4.txt', 'D')
3676 exe "normal ggdGSe\<C-N>\<C-N>\<ESC>"
3677 call assert_equal("enum", getline('.'))
glepnirdd42b052025-03-08 16:52:55 +01003678
3679 set complete=ktest_case5.txt
3680 call writefile(['hello friends', 'go', 'hero'], 'test_case5.txt', 'D')
3681 exe "normal ggdGSh\<C-N>\<C-N>\<ESC>"
3682 call assert_equal("hero", getline('.'))
glepnirf31cfa22025-03-06 21:59:13 +01003683 set complete&
3684
3685 " file
3686 call writefile([''], 'hello', 'D')
3687 call writefile([''], 'helio', 'D')
3688 exe "normal ggdGS./h\<C-X>\<C-f>\<ESC>"
3689 call assert_equal('./hel', getline('.'))
3690
3691 " word
3692 call setline(1, ['what do you think', 'why i have that', ''])
3693 call cursor(3,1)
3694 call feedkeys("Sw\<C-X>\<C-l>\<C-N>\<Esc>0", 'tx!')
3695 call assert_equal('wh', getline('.'))
3696
3697 exe "normal ggdG"
3698 " auto complete when only one match
3699 exe "normal Shello\<CR>h\<C-X>\<C-N>\<esc>"
3700 call assert_equal('hello', getline('.'))
3701 exe "normal Sh\<C-N>\<C-P>\<esc>"
3702 call assert_equal('hello', getline('.'))
3703
3704 exe "normal Shello\<CR>h\<C-X>\<C-N>\<Esc>cch\<C-X>\<C-N>\<Esc>"
3705 call assert_equal('hello', getline('.'))
3706
3707 " continue search for new leader after insert common prefix
3708 exe "normal ohellokate\<CR>h\<C-X>\<C-N>k\<C-y>\<esc>"
3709 call assert_equal('hellokate', getline('.'))
3710
3711 bw!
3712 set completeopt&
3713 set completefuzzycollect&
3714endfunc
3715
3716func Test_completefuzzycollect_with_completeslash()
glepnirb9de1a02024-08-02 19:14:38 +02003717 CheckMSWindows
3718
3719 call writefile([''], 'fobar', 'D')
3720 let orig_shellslash = &shellslash
3721 set cpt&
3722 new
glepnirf31cfa22025-03-06 21:59:13 +01003723 set completefuzzycollect=files
glepnirb9de1a02024-08-02 19:14:38 +02003724 set noshellslash
3725
3726 " Test with completeslash unset
3727 set completeslash=
3728 call setline(1, ['.\fob'])
3729 call feedkeys("A\<C-X>\<C-F>\<Esc>0", 'tx!')
3730 call assert_equal('.\fobar', getline('.'))
3731
3732 " Test with completeslash=backslash
3733 set completeslash=backslash
3734 call feedkeys("S.\\fob\<C-X>\<C-F>\<Esc>0", 'tx!')
3735 call assert_equal('.\fobar', getline('.'))
3736
3737 " Test with completeslash=slash
3738 set completeslash=slash
3739 call feedkeys("S.\\fob\<C-X>\<C-F>\<Esc>0", 'tx!')
3740 call assert_equal('./fobar', getline('.'))
3741
3742 " Reset and clean up
3743 let &shellslash = orig_shellslash
3744 set completeslash=
glepnirf31cfa22025-03-06 21:59:13 +01003745 set completefuzzycollect&
glepnirb9de1a02024-08-02 19:14:38 +02003746 %bw!
3747endfunc
3748
zeertzjq8e567472024-06-14 20:04:42 +02003749" Check that tie breaking is stable for completeopt+=fuzzy (which should
3750" behave the same on different platforms).
3751func Test_complete_fuzzy_match_tie()
3752 new
3753 set completeopt+=fuzzy,noselect
3754 call setline(1, ['aaabbccc', 'aaabbCCC', 'aaabbcccc', 'aaabbCCCC', ''])
3755
3756 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-Y>", 'tx')
3757 call assert_equal('aaabbccc', getline('.'))
3758 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-Y>", 'tx')
3759 call assert_equal('aaabbCCC', getline('.'))
3760 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx')
3761 call assert_equal('aaabbcccc', getline('.'))
3762 call feedkeys("Gcc\<C-X>\<C-N>ab\<C-N>\<C-N>\<C-N>\<C-N>\<C-Y>", 'tx')
3763 call assert_equal('aaabbCCCC', getline('.'))
3764
3765 bwipe!
3766 set completeopt&
3767endfunc
3768
Christian Brabandt13032a42024-07-28 21:16:48 +02003769func Test_complete_backwards_default()
3770 new
3771 call append(1, ['foobar', 'foobaz'])
3772 new
3773 call feedkeys("i\<c-p>", 'tx')
3774 call assert_equal('foobaz', getline('.'))
3775 bw!
3776 bw!
3777endfunc
3778
glepnird4088ed2024-12-31 10:55:22 +01003779func Test_complete_info_matches()
3780 let g:what = ['matches']
3781 func ShownInfo()
3782 let g:compl_info = complete_info(g:what)
3783 return ''
3784 endfunc
3785 set completeopt+=noinsert
3786
3787 new
3788 call setline(1, ['aaa', 'aab', 'aba', 'abb'])
3789 inoremap <buffer><F5> <C-R>=ShownInfo()<CR>
3790
3791 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>dd", 'tx')
3792 call assert_equal([
3793 \ {'word': 'aaa', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
3794 \ {'word': 'aab', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
3795 \ {'word': 'aba', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
3796 \ {'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
3797 \], g:compl_info['matches'])
3798
3799 call feedkeys("Goa\<C-X>\<C-N>b\<F5>\<Esc>dd", 'tx')
3800 call assert_equal([
3801 \ {'word': 'aba', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
3802 \ {'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
3803 \], g:compl_info['matches'])
3804
3805 " items and matches both in what
3806 let g:what = ['items', 'matches']
3807 call feedkeys("Goa\<C-X>\<C-N>b\<F5>\<Esc>dd", 'tx')
3808 call assert_equal([
3809 \ {'word': 'aaa', 'menu': '', 'user_data': '', 'match': v:false, 'info': '', 'kind': '', 'abbr': ''},
3810 \ {'word': 'aab', 'menu': '', 'user_data': '', 'match': v:false, 'info': '', 'kind': '', 'abbr': ''},
3811 \ {'word': 'aba', 'menu': '', 'user_data': '', 'match': v:true, 'info': '', 'kind': '', 'abbr': ''},
3812 \ {'word': 'abb', 'menu': '', 'user_data': '', 'match': v:true, 'info': '', 'kind': '', 'abbr': ''},
3813 \], g:compl_info['items'])
3814 call assert_false(has_key(g:compl_info, 'matches'))
3815
3816 bw!
glepnird4088ed2024-12-31 10:55:22 +01003817 unlet g:what
3818 delfunc ShownInfo
3819 set cot&
3820endfunc
3821
glepnir037b0282025-01-16 14:37:44 +01003822func Test_complete_info_completed()
3823 func ShownInfo()
3824 let g:compl_info = complete_info(['completed'])
3825 return ''
3826 endfunc
3827 set completeopt+=noinsert
3828
3829 new
3830 call setline(1, ['aaa', 'aab', 'aba', 'abb'])
3831 inoremap <buffer><F5> <C-R>=ShownInfo()<CR>
3832
3833 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>dd", 'tx')
3834 call assert_equal({'word': 'aaa', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, g:compl_info['completed'])
3835
3836 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<F5>\<Esc>dd", 'tx')
3837 call assert_equal({'word': 'aab', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, g:compl_info['completed'])
3838
3839 call feedkeys("Go\<C-X>\<C-N>\<C-N>\<C-N>\<C-N>\<F5>\<Esc>dd", 'tx')
3840 call assert_equal({'word': 'abb', 'menu': '', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}, g:compl_info['completed'])
3841
3842 set completeopt+=noselect
3843 call feedkeys("Go\<C-X>\<C-N>\<F5>\<Esc>dd", 'tx')
3844 call assert_equal({}, g:compl_info)
3845
3846 bw!
glepnir037b0282025-01-16 14:37:44 +01003847 delfunc ShownInfo
3848 set cot&
3849endfunc
3850
glepniredd4ac32025-01-29 18:53:51 +01003851function Test_completeopt_preinsert()
3852 func Omni_test(findstart, base)
3853 if a:findstart
3854 return col(".")
3855 endif
3856 return [#{word: "fobar"}, #{word: "foobar"}, #{word: "你的"}, #{word: "你好世界"}]
3857 endfunc
3858 set omnifunc=Omni_test
3859 set completeopt=menu,menuone,preinsert
glepnir84a75032025-03-15 09:59:22 +01003860 func GetLine()
3861 let g:line = getline('.')
3862 let g:col = col('.')
3863 endfunc
glepniredd4ac32025-01-29 18:53:51 +01003864
3865 new
glepnir84a75032025-03-15 09:59:22 +01003866 inoremap <buffer><F5> <C-R>=GetLine()<CR>
3867 call feedkeys("S\<C-X>\<C-O>f\<F5>\<ESC>", 'tx')
3868 call assert_equal("fobar", g:line)
3869 call assert_equal(2, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003870
glepnir84a75032025-03-15 09:59:22 +01003871 call feedkeys("S\<C-X>\<C-O>foo\<F5><ESC>", 'tx')
3872 call assert_equal("foobar", g:line)
glepniredd4ac32025-01-29 18:53:51 +01003873
3874 call feedkeys("S\<C-X>\<C-O>foo\<BS>\<BS>\<BS>", 'tx')
3875 call assert_equal("", getline('.'))
glepniredd4ac32025-01-29 18:53:51 +01003876
3877 " delete a character and input new leader
glepnir84a75032025-03-15 09:59:22 +01003878 call feedkeys("S\<C-X>\<C-O>foo\<BS>b\<F5>\<ESC>", 'tx')
3879 call assert_equal("fobar", g:line)
3880 call assert_equal(4, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003881
3882 " delete preinsert when prepare completion
3883 call feedkeys("S\<C-X>\<C-O>f\<Space>", 'tx')
3884 call assert_equal("f ", getline('.'))
glepniredd4ac32025-01-29 18:53:51 +01003885
glepnir84a75032025-03-15 09:59:22 +01003886 call feedkeys("S\<C-X>\<C-O>你\<F5>\<ESC>", 'tx')
3887 call assert_equal("你的", g:line)
3888 call assert_equal(4, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003889
glepnir84a75032025-03-15 09:59:22 +01003890 call feedkeys("S\<C-X>\<C-O>你好\<F5>\<ESC>", 'tx')
3891 call assert_equal("你好世界", g:line)
3892 call assert_equal(7, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003893
glepnir84a75032025-03-15 09:59:22 +01003894 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>f\<F5>\<ESC>", 'tx')
3895 call assert_equal("hello fobar wo", g:line)
3896 call assert_equal(9, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003897
glepnir84a75032025-03-15 09:59:22 +01003898 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>f\<BS>\<F5>\<ESC>", 'tx')
3899 call assert_equal("hello wo", g:line)
3900 call assert_equal(8, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003901
glepnir84a75032025-03-15 09:59:22 +01003902 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>foo\<F5>\<ESC>", 'tx')
3903 call assert_equal("hello foobar wo", g:line)
3904 call assert_equal(11, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003905
glepnir84a75032025-03-15 09:59:22 +01003906 call feedkeys("Shello wo\<Left>\<Left>\<Left>\<C-X>\<C-O>foo\<BS>b\<F5>\<ESC>", 'tx')
3907 call assert_equal("hello fobar wo", g:line)
3908 call assert_equal(11, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003909
zeertzjq8297e2c2025-01-30 11:04:47 +01003910 " confirm
glepniredd4ac32025-01-29 18:53:51 +01003911 call feedkeys("S\<C-X>\<C-O>f\<C-Y>", 'tx')
3912 call assert_equal("fobar", getline('.'))
3913 call assert_equal(5, col('.'))
3914
3915 " cancel
3916 call feedkeys("S\<C-X>\<C-O>fo\<C-E>", 'tx')
3917 call assert_equal("fo", getline('.'))
3918 call assert_equal(2, col('.'))
3919
glepnir84a75032025-03-15 09:59:22 +01003920 call feedkeys("S hello hero\<CR>h\<C-X>\<C-N>\<F5>\<ESC>", 'tx')
3921 call assert_equal("hello", g:line)
3922 call assert_equal(2, col('.'))
glepniredd4ac32025-01-29 18:53:51 +01003923
3924 call feedkeys("Sh\<C-X>\<C-N>\<C-Y>", 'tx')
3925 call assert_equal("hello", getline('.'))
3926 call assert_equal(5, col('.'))
3927
3928 " delete preinsert part
3929 call feedkeys("S\<C-X>\<C-O>fo ", 'tx')
3930 call assert_equal("fo ", getline('.'))
3931 call assert_equal(3, col('.'))
3932
glepnir001c26c2025-02-02 09:36:22 +01003933 call feedkeys("She\<C-X>\<C-N>\<C-U>", 'tx')
3934 call assert_equal("", getline('.'))
3935 call assert_equal(1, col('.'))
3936
3937 call feedkeys("She\<C-X>\<C-N>\<C-W>", 'tx')
3938 call assert_equal("", getline('.'))
3939 call assert_equal(1, col('.'))
3940
glepniredd4ac32025-01-29 18:53:51 +01003941 " whole line
glepnir84a75032025-03-15 09:59:22 +01003942 call feedkeys("Shello hero\<CR>\<C-X>\<C-L>\<F5>\<ESC>", 'tx')
3943 call assert_equal("hello hero", g:line)
3944 call assert_equal(1, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003945
glepnir84a75032025-03-15 09:59:22 +01003946 call feedkeys("Shello hero\<CR>he\<C-X>\<C-L>\<F5>\<ESC>", 'tx')
3947 call assert_equal("hello hero", g:line)
3948 call assert_equal(3, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003949
glepnir84a75032025-03-15 09:59:22 +01003950 call feedkeys("Shello hero\<CR>h\<C-X>\<C-N>er\<F5>\<ESC>", 'tx')
3951 call assert_equal("hero", g:line)
3952 call assert_equal(4, g:col)
glepnirbfb4eea2025-01-31 15:28:29 +01003953
glepniredd4ac32025-01-29 18:53:51 +01003954 " can not work with fuzzy
3955 set cot+=fuzzy
3956 call feedkeys("S\<C-X>\<C-O>", 'tx')
3957 call assert_equal("fobar", getline('.'))
3958 call assert_equal(5, col('.'))
3959
3960 " test for fuzzy and noinsert
3961 set cot+=noinsert
glepnir84a75032025-03-15 09:59:22 +01003962 call feedkeys("S\<C-X>\<C-O>fb\<F5>\<ESC>", 'tx')
3963 call assert_equal("fb", g:line)
3964 call assert_equal(3, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003965
glepnir84a75032025-03-15 09:59:22 +01003966 call feedkeys("S\<C-X>\<C-O>你\<F5>\<ESC>", 'tx')
3967 call assert_equal("你", g:line)
3968 call assert_equal(4, g:col)
glepniredd4ac32025-01-29 18:53:51 +01003969
3970 call feedkeys("S\<C-X>\<C-O>fb\<C-Y>", 'tx')
3971 call assert_equal("fobar", getline('.'))
3972 call assert_equal(5, col('.'))
3973
glepnira2c55592025-02-28 17:43:42 +01003974 " When the pum is not visible, the preinsert has no effect
glepnir52fd8672025-02-20 22:13:24 +01003975 set cot=preinsert
3976 call feedkeys("Sfoo1 foo2\<CR>f\<C-X>\<C-N>bar", 'tx')
glepnira2c55592025-02-28 17:43:42 +01003977 call assert_equal("foo1bar", getline('.'))
3978 call assert_equal(7, col('.'))
glepnir52fd8672025-02-20 22:13:24 +01003979
glepnir94a045e2025-03-01 16:12:23 +01003980 set cot=preinsert,menuone
glepnir84a75032025-03-15 09:59:22 +01003981 call feedkeys("Sfoo1 foo2\<CR>f\<C-X>\<C-N>\<F5>\<ESC>", 'tx')
3982 call assert_equal("foo1", g:line)
3983 call assert_equal(2, g:col)
3984
3985 inoremap <buffer> <f3> <cmd>call complete(4, [{'word': "fobar"}, {'word': "foobar"}])<CR>
3986 call feedkeys("Swp.\<F3>\<F5>\<BS>\<ESC>", 'tx')
3987 call assert_equal("wp.fobar", g:line)
3988 call assert_equal(4, g:col)
3989 call assert_equal("wp.", getline('.'))
glepnir94a045e2025-03-01 16:12:23 +01003990
glepniredd4ac32025-01-29 18:53:51 +01003991 bw!
glepniredd4ac32025-01-29 18:53:51 +01003992 set cot&
3993 set omnifunc&
3994 delfunc Omni_test
glepniredd4ac32025-01-29 18:53:51 +01003995endfunc
3996
zeertzjq060e6552025-02-21 20:06:26 +01003997" Check that mark positions are correct after triggering multiline completion.
3998func Test_complete_multiline_marks()
3999 func Omni_test(findstart, base)
4000 if a:findstart
4001 return col(".")
4002 endif
4003 return [
4004 \ #{word: "func ()\n\t\nend"},
4005 \ #{word: "foobar"},
4006 \ #{word: "你好\n\t\n我好"}
4007 \ ]
4008 endfunc
4009 set omnifunc=Omni_test
4010
4011 new
4012 let lines = mapnew(range(10), 'string(v:val)')
4013 call setline(1, lines)
4014 call setpos("'a", [0, 3, 1, 0])
4015
4016 call feedkeys("A \<C-X>\<C-O>\<C-E>\<BS>", 'tx')
4017 call assert_equal(lines, getline(1, '$'))
4018 call assert_equal([0, 3, 1, 0], getpos("'a"))
4019
4020 call feedkeys("A \<C-X>\<C-O>\<C-N>\<C-E>\<BS>", 'tx')
4021 call assert_equal(lines, getline(1, '$'))
4022 call assert_equal([0, 3, 1, 0], getpos("'a"))
4023
4024 call feedkeys("A \<C-X>\<C-O>\<C-N>\<C-N>\<C-E>\<BS>", 'tx')
4025 call assert_equal(lines, getline(1, '$'))
4026 call assert_equal([0, 3, 1, 0], getpos("'a"))
4027
4028 call feedkeys("A \<C-X>\<C-O>\<C-N>\<C-N>\<C-N>\<C-E>\<BS>", 'tx')
4029 call assert_equal(lines, getline(1, '$'))
4030 call assert_equal([0, 3, 1, 0], getpos("'a"))
4031
4032 call feedkeys("A \<C-X>\<C-O>\<C-Y>", 'tx')
4033 call assert_equal(['0 func ()', "\t", 'end'] + lines[1:], getline(1, '$'))
4034 call assert_equal([0, 5, 1, 0], getpos("'a"))
4035
4036 bw!
4037 set omnifunc&
4038 delfunc Omni_test
4039endfunc
4040
Christian Brabandt71f17fd2025-03-31 20:57:13 +02004041func Test_complete_append_selected_match_default()
4042 " when typing a normal character during completion,
4043 " completion is ended, see
4044 " :h popupmenu-completion ("There are three states:")
4045 func PrintMenuWords()
4046 let info = complete_info(["selected", "matches"])
4047 call map(info.matches, {_, v -> v.word})
4048 return info
4049 endfunc
4050
4051 new
4052 call setline(1, ["fo", "foo", "foobar", "fobarbaz"])
4053 exe "normal! Gof\<c-n>\<c-r>=PrintMenuWords()\<cr>"
4054 call assert_equal('fo{''matches'': [''fo'', ''foo'', ''foobar'', ''fobarbaz''], ''selected'': 0}', getline(5))
4055 %d
4056 call setline(1, ["fo", "foo", "foobar", "fobarbaz"])
4057 exe "normal! Gof\<c-n>o\<c-r>=PrintMenuWords()\<cr>"
4058 call assert_equal('foo{''matches'': [], ''selected'': -1}', getline(5))
4059 %d
4060 set completeopt=menu,noselect
4061 call setline(1, ["fo", "foo", "foobar", "fobarbaz"])
4062 exe "normal! Gof\<c-n>\<c-n>o\<c-r>=PrintMenuWords()\<cr>"
4063 call assert_equal('foo{''matches'': [], ''selected'': -1}', getline(5))
4064 bw!
4065
4066 set completeopt&
4067 delfunc PrintMenuWords
4068endfunc
4069
Christian Brabandtfef66302024-01-29 21:46:58 +01004070" vim: shiftwidth=2 sts=2 expandtab nofoldenable