xref: /vim-8.2.3635/src/testdir/test_popup.vim (revision e16b00a1)
1" Test for completion menu
2
3let g:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
4let g:setting = ''
5
6func! ListMonths()
7  if g:setting != ''
8    exe ":set" g:setting
9  endif
10  let mth = copy(g:months)
11  let entered = strcharpart(getline('.'),0,col('.'))
12  if !empty(entered)
13    let mth = filter(mth, 'v:val=~"^".entered')
14  endif
15  call complete(1, mth)
16  return ''
17endfunc
18
19func! Test_popup_complete2()
20  " Although the popupmenu is not visible, this does not mean completion mode
21  " has ended. After pressing <f5> to complete the currently typed char, Vim
22  " still stays in the first state of the completion (:h ins-completion-menu),
23  " although the popupmenu wasn't shown <c-e> will remove the inserted
24  " completed text (:h complete_CTRL-E), while the following <c-e> will behave
25  " like expected (:h i_CTRL-E)
26  new
27  inoremap <f5> <c-r>=ListMonths()<cr>
28  call append(1, ["December2015"])
29  :1
30  call feedkeys("aD\<f5>\<C-E>\<C-E>\<C-E>\<C-E>\<enter>\<esc>", 'tx')
31  call assert_equal(["Dece", "", "December2015"], getline(1,3))
32  %d
33  bw!
34endfu
35
36func! Test_popup_complete()
37  new
38  inoremap <f5> <c-r>=ListMonths()<cr>
39
40  " <C-E> - select original typed text before the completion started
41  call feedkeys("aJu\<f5>\<down>\<c-e>\<esc>", 'tx')
42  call assert_equal(["Ju"], getline(1,2))
43  %d
44
45  " <C-Y> - accept current match
46  call feedkeys("a\<f5>". repeat("\<down>",7). "\<c-y>\<esc>", 'tx')
47  call assert_equal(["August"], getline(1,2))
48  %d
49
50  " <BS> - Delete one character from the inserted text (state: 1)
51  " TODO: This should not end the completion, but it does.
52  " This should according to the documentation:
53  " January
54  " but instead, this does
55  " Januar
56  " (idea is, C-L inserts the match from the popup menu
57  " but if the menu is closed, it will insert the character <c-l>
58  call feedkeys("aJ\<f5>\<bs>\<c-l>\<esc>", 'tx')
59  call assert_equal(["Januar"], getline(1,2))
60  %d
61
62  " any-non special character: Stop completion without changing the match
63  " and insert the typed character
64  call feedkeys("a\<f5>20", 'tx')
65  call assert_equal(["January20"], getline(1,2))
66  %d
67
68  " any-non printable, non-white character: Add this character and
69  " reduce number of matches
70  call feedkeys("aJu\<f5>\<c-p>l\<c-y>", 'tx')
71  call assert_equal(["Jul"], getline(1,2))
72  %d
73
74  " any-non printable, non-white character: Add this character and
75  " reduce number of matches
76  call feedkeys("aJu\<f5>\<c-p>l\<c-n>\<c-y>", 'tx')
77  call assert_equal(["July"], getline(1,2))
78  %d
79
80  " any-non printable, non-white character: Add this character and
81  " reduce number of matches
82  call feedkeys("aJu\<f5>\<c-p>l\<c-e>", 'tx')
83  call assert_equal(["Jul"], getline(1,2))
84  %d
85
86  " <BS> - Delete one character from the inserted text (state: 2)
87  call feedkeys("a\<f5>\<c-n>\<bs>", 'tx')
88  call assert_equal(["Februar"], getline(1,2))
89  %d
90
91  " <c-l> - Insert one character from the current match
92  call feedkeys("aJ\<f5>".repeat("\<c-n>",3)."\<c-l>\<esc>", 'tx')
93  call assert_equal(["J"], getline(1,2))
94  %d
95
96  " <c-l> - Insert one character from the current match
97  call feedkeys("aJ\<f5>".repeat("\<c-n>",4)."\<c-l>\<esc>", 'tx')
98  call assert_equal(["January"], getline(1,2))
99  %d
100
101  " <c-y> - Accept current selected match
102  call feedkeys("aJ\<f5>\<c-y>\<esc>", 'tx')
103  call assert_equal(["January"], getline(1,2))
104  %d
105
106  " <c-e> - End completion, go back to what was there before selecting a match
107  call feedkeys("aJu\<f5>\<c-e>\<esc>", 'tx')
108  call assert_equal(["Ju"], getline(1,2))
109  %d
110
111  " <PageUp> - Select a match several entries back
112  call feedkeys("a\<f5>\<PageUp>\<c-y>\<esc>", 'tx')
113  call assert_equal([""], getline(1,2))
114  %d
115
116  " <PageUp><PageUp> - Select a match several entries back
117  call feedkeys("a\<f5>\<PageUp>\<PageUp>\<c-y>\<esc>", 'tx')
118  call assert_equal(["December"], getline(1,2))
119  %d
120
121  " <PageUp><PageUp><PageUp> - Select a match several entries back
122  call feedkeys("a\<f5>\<PageUp>\<PageUp>\<PageUp>\<c-y>\<esc>", 'tx')
123  call assert_equal(["February"], getline(1,2))
124  %d
125
126  " <PageDown> - Select a match several entries further
127  call feedkeys("a\<f5>\<PageDown>\<c-y>\<esc>", 'tx')
128  call assert_equal(["November"], getline(1,2))
129  %d
130
131  " <PageDown><PageDown> - Select a match several entries further
132  call feedkeys("a\<f5>\<PageDown>\<PageDown>\<c-y>\<esc>", 'tx')
133  call assert_equal(["December"], getline(1,2))
134  %d
135
136  " <PageDown><PageDown><PageDown> - Select a match several entries further
137  call feedkeys("a\<f5>\<PageDown>\<PageDown>\<PageDown>\<c-y>\<esc>", 'tx')
138  call assert_equal([""], getline(1,2))
139  %d
140
141  " <PageDown><PageDown><PageDown><PageDown> - Select a match several entries further
142  call feedkeys("a\<f5>".repeat("\<PageDown>",4)."\<c-y>\<esc>", 'tx')
143  call assert_equal(["October"], getline(1,2))
144  %d
145
146  " <Up> - Select a match don't insert yet
147  call feedkeys("a\<f5>\<Up>\<c-y>\<esc>", 'tx')
148  call assert_equal([""], getline(1,2))
149  %d
150
151  " <Up><Up> - Select a match don't insert yet
152  call feedkeys("a\<f5>\<Up>\<Up>\<c-y>\<esc>", 'tx')
153  call assert_equal(["December"], getline(1,2))
154  %d
155
156  " <Up><Up><Up> - Select a match don't insert yet
157  call feedkeys("a\<f5>\<Up>\<Up>\<Up>\<c-y>\<esc>", 'tx')
158  call assert_equal(["November"], getline(1,2))
159  %d
160
161  " <Tab> - Stop completion and insert the match
162  call feedkeys("a\<f5>\<Tab>\<c-y>\<esc>", 'tx')
163  call assert_equal(["January	"], getline(1,2))
164  %d
165
166  " <Space> - Stop completion and insert the match
167  call feedkeys("a\<f5>".repeat("\<c-p>",5)." \<esc>", 'tx')
168  call assert_equal(["September "], getline(1,2))
169  %d
170
171  " <Enter> - Use the text and insert line break (state: 1)
172  call feedkeys("a\<f5>\<enter>\<esc>", 'tx')
173  call assert_equal(["January", ''], getline(1,2))
174  %d
175
176  " <Enter> - Insert the current selected text (state: 2)
177  call feedkeys("a\<f5>".repeat("\<Up>",5)."\<enter>\<esc>", 'tx')
178  call assert_equal(["September"], getline(1,2))
179  %d
180
181  " Insert match immediately, if there is only one match
182  " <c-y> selects a character from the line above
183  call append(0, ["December2015"])
184  call feedkeys("aD\<f5>\<C-Y>\<C-Y>\<C-Y>\<C-Y>\<enter>\<esc>", 'tx')
185  call assert_equal(["December2015", "December2015", ""], getline(1,3))
186  %d
187
188  " use menuone for 'completeopt'
189  " Since for the first <c-y> the menu is still shown, will only select
190  " three letters from the line above
191  set completeopt&vim
192  set completeopt+=menuone
193  call append(0, ["December2015"])
194  call feedkeys("aD\<f5>\<C-Y>\<C-Y>\<C-Y>\<C-Y>\<enter>\<esc>", 'tx')
195  call assert_equal(["December2015", "December201", ""], getline(1,3))
196  %d
197
198  " use longest for 'completeopt'
199  set completeopt&vim
200  call feedkeys("aM\<f5>\<C-N>\<C-P>\<c-e>\<enter>\<esc>", 'tx')
201  set completeopt+=longest
202  call feedkeys("aM\<f5>\<C-N>\<C-P>\<c-e>\<enter>\<esc>", 'tx')
203  call assert_equal(["M", "Ma", ""], getline(1,3))
204  %d
205
206  " use noselect/noinsert for 'completeopt'
207  set completeopt&vim
208  call feedkeys("aM\<f5>\<enter>\<esc>", 'tx')
209  set completeopt+=noselect
210  call feedkeys("aM\<f5>\<enter>\<esc>", 'tx')
211  set completeopt-=noselect completeopt+=noinsert
212  call feedkeys("aM\<f5>\<enter>\<esc>", 'tx')
213  call assert_equal(["March", "M", "March"], getline(1,4))
214  %d
215endfu
216
217
218func! Test_popup_completion_insertmode()
219  new
220  inoremap <F5> <C-R>=ListMonths()<CR>
221
222  call feedkeys("a\<f5>\<down>\<enter>\<esc>", 'tx')
223  call assert_equal('February', getline(1))
224  %d
225  " Set noinsertmode
226  let g:setting = 'noinsertmode'
227  call feedkeys("a\<f5>\<down>\<enter>\<esc>", 'tx')
228  call assert_equal('February', getline(1))
229  call assert_false(pumvisible())
230  %d
231  " Go through all matches, until none is selected
232  let g:setting = ''
233  call feedkeys("a\<f5>". repeat("\<c-n>",12)."\<enter>\<esc>", 'tx')
234  call assert_equal('', getline(1))
235  %d
236  " select previous entry
237  call feedkeys("a\<f5>\<c-p>\<enter>\<esc>", 'tx')
238  call assert_equal('', getline(1))
239  %d
240  " select last entry
241  call feedkeys("a\<f5>\<c-p>\<c-p>\<enter>\<esc>", 'tx')
242  call assert_equal('December', getline(1))
243
244  iunmap <F5>
245endfunc
246
247func Test_noinsert_complete()
248  function! s:complTest1() abort
249    call complete(1, ['source', 'soundfold'])
250    return ''
251  endfunction
252
253  function! s:complTest2() abort
254    call complete(1, ['source', 'soundfold'])
255    return ''
256  endfunction
257
258  new
259  set completeopt+=noinsert
260  inoremap <F5>  <C-R>=s:complTest1()<CR>
261  call feedkeys("i\<F5>soun\<CR>\<CR>\<ESC>.", 'tx')
262  call assert_equal('soundfold', getline(1))
263  call assert_equal('soundfold', getline(2))
264  bwipe!
265
266  new
267  inoremap <F5>  <C-R>=s:complTest2()<CR>
268  call feedkeys("i\<F5>\<CR>\<ESC>", 'tx')
269  call assert_equal('source', getline(1))
270  bwipe!
271
272  set completeopt-=noinsert
273  iunmap <F5>
274endfunc
275
276func Test_compl_vim_cmds_after_register_expr()
277  function! s:test_func()
278    return 'autocmd '
279  endfunction
280  augroup AAAAA_Group
281    au!
282  augroup END
283
284  new
285  call feedkeys("i\<c-r>=s:test_func()\<CR>\<C-x>\<C-v>\<Esc>", 'tx')
286  call assert_equal('autocmd AAAAA_Group', getline(1))
287  autocmd! AAAAA_Group
288  augroup! AAAAA_Group
289  bwipe!
290endfunc
291
292func DummyCompleteOne(findstart, base)
293  if a:findstart
294    return 0
295  else
296    wincmd n
297    return ['onedef', 'oneDEF']
298  endif
299endfunc
300
301" Test that nothing happens if the 'completefunc' opens
302" a new window (no completion, no crash)
303func Test_completefunc_opens_new_window_one()
304  new
305  let winid = win_getid()
306  setlocal completefunc=DummyCompleteOne
307  call setline(1, 'one')
308  /^one
309  call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E839:')
310  call assert_notequal(winid, win_getid())
311  q!
312  call assert_equal(winid, win_getid())
313  call assert_equal('', getline(1))
314  q!
315endfunc
316
317" Test that nothing happens if the 'completefunc' opens
318" a new window (no completion, no crash)
319func DummyCompleteTwo(findstart, base)
320  if a:findstart
321    wincmd n
322    return 0
323  else
324    return ['twodef', 'twoDEF']
325  endif
326endfunction
327
328" Test that nothing happens if the 'completefunc' opens
329" a new window (no completion, no crash)
330func Test_completefunc_opens_new_window_two()
331  new
332  let winid = win_getid()
333  setlocal completefunc=DummyCompleteTwo
334  call setline(1, 'two')
335  /^two
336  call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E764:')
337  call assert_notequal(winid, win_getid())
338  q!
339  call assert_equal(winid, win_getid())
340  call assert_equal('two', getline(1))
341  q!
342endfunc
343
344func DummyCompleteThree(findstart, base)
345  if a:findstart
346    return 0
347  else
348    return ['threedef', 'threeDEF']
349  endif
350endfunc
351
352:"Test that 'completefunc' works when it's OK.
353func Test_completefunc_works()
354  new
355  let winid = win_getid()
356  setlocal completefunc=DummyCompleteThree
357  call setline(1, 'three')
358  /^three
359  call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")
360  call assert_equal(winid, win_getid())
361  call assert_equal('threeDEF', getline(1))
362  q!
363endfunc
364
365func DummyCompleteFour(findstart, base)
366  if a:findstart
367    return 0
368  else
369    call complete_add('four1')
370    call complete_add('four2')
371    call complete_check()
372    call complete_add('four3')
373    call complete_add('four4')
374    call complete_check()
375    call complete_add('four5')
376    call complete_add('four6')
377    return []
378  endif
379endfunc
380
381" Test that 'omnifunc' works when it's OK.
382func Test_omnifunc_with_check()
383  new
384  setlocal omnifunc=DummyCompleteFour
385  call setline(1, 'four')
386  /^four
387  call feedkeys("A\<C-X>\<C-O>\<C-N>\<Esc>", "x")
388  call assert_equal('four2', getline(1))
389
390  call setline(1, 'four')
391  /^four
392  call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<Esc>", "x")
393  call assert_equal('four3', getline(1))
394
395  call setline(1, 'four')
396  /^four
397  call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<C-N>\<C-N>\<Esc>", "x")
398  call assert_equal('four5', getline(1))
399
400  q!
401endfunc
402
403function UndoComplete()
404  call complete(1, ['January', 'February', 'March',
405        \ 'April', 'May', 'June', 'July', 'August', 'September',
406        \ 'October', 'November', 'December'])
407  return ''
408endfunc
409
410" Test that no undo item is created when no completion is inserted
411func Test_complete_no_undo()
412  set completeopt=menu,preview,noinsert,noselect
413  inoremap <Right> <C-R>=UndoComplete()<CR>
414  new
415  call feedkeys("ixxx\<CR>\<CR>yyy\<Esc>k", 'xt')
416  call feedkeys("iaaa\<Esc>0", 'xt')
417  call assert_equal('aaa', getline(2))
418  call feedkeys("i\<Right>\<Esc>", 'xt')
419  call assert_equal('aaa', getline(2))
420  call feedkeys("u", 'xt')
421  call assert_equal('', getline(2))
422
423  call feedkeys("ibbb\<Esc>0", 'xt')
424  call assert_equal('bbb', getline(2))
425  call feedkeys("A\<Right>\<Down>\<CR>\<Esc>", 'xt')
426  call assert_equal('January', getline(2))
427  call feedkeys("u", 'xt')
428  call assert_equal('bbb', getline(2))
429
430  call feedkeys("A\<Right>\<C-N>\<Esc>", 'xt')
431  call assert_equal('January', getline(2))
432  call feedkeys("u", 'xt')
433  call assert_equal('bbb', getline(2))
434
435  iunmap <Right>
436  set completeopt&
437  q!
438endfunc
439
440function! DummyCompleteFive(findstart, base)
441  if a:findstart
442    return 0
443  else
444    return [
445          \   { 'word': 'January', 'info': "info1-1\n1-2\n1-3" },
446          \   { 'word': 'February', 'info': "info2-1\n2-2\n2-3" },
447          \   { 'word': 'March', 'info': "info3-1\n3-2\n3-3" },
448          \   { 'word': 'April', 'info': "info4-1\n4-2\n4-3" },
449          \   { 'word': 'May', 'info': "info5-1\n5-2\n5-3" },
450          \ ]
451  endif
452endfunc
453
454" Test that 'completefunc' on Scratch buffer with preview window works when
455" it's OK.
456func Test_completefunc_with_scratch_buffer()
457  new +setlocal\ buftype=nofile\ bufhidden=wipe\ noswapfile
458  set completeopt+=preview
459  setlocal completefunc=DummyCompleteFive
460  call feedkeys("A\<C-X>\<C-U>\<C-N>\<C-N>\<C-N>\<Esc>", "x")
461  call assert_equal(['April'], getline(1, '$'))
462  pclose
463  q!
464  set completeopt&
465endfunc
466
467" <C-E> - select original typed text before the completion started without
468" auto-wrap text.
469func Test_completion_ctrl_e_without_autowrap()
470  new
471  let tw_save = &tw
472  set tw=78
473  let li = [
474        \ '"                                                        zzz',
475        \ '" zzzyyyyyyyyyyyyyyyyyyy']
476  call setline(1, li)
477  0
478  call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx")
479  call assert_equal(li, getline(1, '$'))
480
481  let &tw = tw_save
482  q!
483endfunc
484
485function! DummyCompleteSix()
486  call complete(1, ['Hello', 'World'])
487  return ''
488endfunction
489
490" complete() correctly clears the list of autocomplete candidates
491" See #1411
492func Test_completion_clear_candidate_list()
493  new
494  %d
495  " select first entry from the completion popup
496  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>", "tx")
497  call assert_equal('Hello', getline(1))
498  %d
499  " select second entry from the completion popup
500  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>", "tx")
501  call assert_equal('World', getline(1))
502  %d
503  " select original text
504  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>", "tx")
505  call assert_equal('    xxx', getline(1))
506  %d
507  " back at first entry from completion list
508  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>\<C-N>", "tx")
509  call assert_equal('Hello', getline(1))
510
511  bw!
512endfunc
513
514func Test_completion_respect_bs_option()
515  new
516  let li = ["aaa", "aaa12345", "aaaabcdef", "aaaABC"]
517
518  set bs=indent,eol
519  call setline(1, li)
520  1
521  call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx")
522  call assert_equal('aaa', getline(1))
523
524  %d
525  set bs=indent,eol,start
526  call setline(1, li)
527  1
528  call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx")
529  call assert_equal('', getline(1))
530
531  bw!
532endfunc
533
534func CompleteUndo() abort
535  call complete(1, g:months)
536  return ''
537endfunc
538
539func Test_completion_can_undo()
540  inoremap <Right> <c-r>=CompleteUndo()<cr>
541  set completeopt+=noinsert,noselect
542
543  new
544  call feedkeys("a\<Right>a\<Esc>", 'xt')
545  call assert_equal('a', getline(1))
546  undo
547  call assert_equal('', getline(1))
548
549  bwipe!
550  set completeopt&
551  iunmap <Right>
552endfunc
553
554func Test_completion_comment_formatting()
555  new
556  setl formatoptions=tcqro
557  call feedkeys("o/*\<cr>\<cr>/\<esc>", 'tx')
558  call assert_equal(['', '/*', ' *', ' */'], getline(1,4))
559  %d
560  call feedkeys("o/*\<cr>foobar\<cr>/\<esc>", 'tx')
561  call assert_equal(['', '/*', ' * foobar', ' */'], getline(1,4))
562  %d
563  try
564    call feedkeys("o/*\<cr>\<cr>\<c-x>\<c-u>/\<esc>", 'tx')
565    call assert_report('completefunc not set, should have failed')
566  catch
567    call assert_exception('E764:')
568  endtry
569  call assert_equal(['', '/*', ' *', ' */'], getline(1,4))
570  bwipe!
571endfunc
572
573fun MessCompleteMonths()
574  for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep")
575    call complete_add(m)
576    if complete_check()
577      break
578    endif
579  endfor
580  return []
581endfun
582
583fun MessCompleteMore()
584  call complete(1, split("Oct Nov Dec"))
585  return []
586endfun
587
588fun MessComplete(findstart, base)
589  if a:findstart
590    let line = getline('.')
591    let start = col('.') - 1
592    while start > 0 && line[start - 1] =~ '\a'
593      let start -= 1
594    endwhile
595    return start
596  else
597    call MessCompleteMonths()
598    call MessCompleteMore()
599    return []
600  endif
601endf
602
603func Test_complete_func_mess()
604  " Calling complete() after complete_add() in 'completefunc' is wrong, but it
605  " should not crash.
606  set completefunc=MessComplete
607  new
608  call setline(1, 'Ju')
609  call feedkeys("A\<c-x>\<c-u>/\<esc>", 'tx')
610  call assert_equal('Oct/Oct', getline(1))
611  bwipe!
612  set completefunc=
613endfunc
614
615func Test_complete_CTRLN_startofbuffer()
616  new
617  call setline(1, [ 'organize(cupboard, 3, 2);',
618        \ 'prioritize(bureau, 8, 7);',
619        \ 'realize(bannister, 4, 4);',
620        \ 'moralize(railing, 3,9);'])
621  let expected=['cupboard.organize(3, 2);',
622        \ 'bureau.prioritize(8, 7);',
623        \ 'bannister.realize(4, 4);',
624        \ 'railing.moralize(3,9);']
625  call feedkeys("qai\<c-n>\<c-n>.\<esc>3wdW\<cr>q3@a", 'tx')
626  call assert_equal(expected, getline(1,'$'))
627  bwipe!
628endfunc
629
630" vim: shiftwidth=2 sts=2 expandtab
631