xref: /vim-8.2.3635/src/testdir/test_popup.vim (revision fcfe1a9b)
1" Test for completion menu
2
3source shared.vim
4source screendump.vim
5
6let g:months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
7let g:setting = ''
8
9func ListMonths()
10  if g:setting != ''
11    exe ":set" g:setting
12  endif
13  let mth = copy(g:months)
14  let entered = strcharpart(getline('.'),0,col('.'))
15  if !empty(entered)
16    let mth = filter(mth, 'v:val=~"^".entered')
17  endif
18  call complete(1, mth)
19  return ''
20endfunc
21
22func Test_popup_complete2()
23  " Although the popupmenu is not visible, this does not mean completion mode
24  " has ended. After pressing <f5> to complete the currently typed char, Vim
25  " still stays in the first state of the completion (:h ins-completion-menu),
26  " although the popupmenu wasn't shown <c-e> will remove the inserted
27  " completed text (:h complete_CTRL-E), while the following <c-e> will behave
28  " like expected (:h i_CTRL-E)
29  new
30  inoremap <f5> <c-r>=ListMonths()<cr>
31  call append(1, ["December2015"])
32  :1
33  call feedkeys("aD\<f5>\<C-E>\<C-E>\<C-E>\<C-E>\<enter>\<esc>", 'tx')
34  call assert_equal(["Dece", "", "December2015"], getline(1,3))
35  %d
36  bw!
37endfunc
38
39func Test_popup_complete()
40  new
41  inoremap <f5> <c-r>=ListMonths()<cr>
42
43  " <C-E> - select original typed text before the completion started
44  call feedkeys("aJu\<f5>\<down>\<c-e>\<esc>", 'tx')
45  call assert_equal(["Ju"], getline(1,2))
46  %d
47
48  " <C-Y> - accept current match
49  call feedkeys("a\<f5>". repeat("\<down>",7). "\<c-y>\<esc>", 'tx')
50  call assert_equal(["August"], getline(1,2))
51  %d
52
53  " <BS> - Delete one character from the inserted text (state: 1)
54  " TODO: This should not end the completion, but it does.
55  " This should according to the documentation:
56  " January
57  " but instead, this does
58  " Januar
59  " (idea is, C-L inserts the match from the popup menu
60  " but if the menu is closed, it will insert the character <c-l>
61  call feedkeys("aJ\<f5>\<bs>\<c-l>\<esc>", 'tx')
62  call assert_equal(["Januar"], getline(1,2))
63  %d
64
65  " any-non special character: Stop completion without changing the match
66  " and insert the typed character
67  call feedkeys("a\<f5>20", 'tx')
68  call assert_equal(["January20"], getline(1,2))
69  %d
70
71  " any-non printable, non-white character: Add this character and
72  " reduce number of matches
73  call feedkeys("aJu\<f5>\<c-p>l\<c-y>", 'tx')
74  call assert_equal(["Jul"], getline(1,2))
75  %d
76
77  " any-non printable, non-white character: Add this character and
78  " reduce number of matches
79  call feedkeys("aJu\<f5>\<c-p>l\<c-n>\<c-y>", 'tx')
80  call assert_equal(["July"], getline(1,2))
81  %d
82
83  " any-non printable, non-white character: Add this character and
84  " reduce number of matches
85  call feedkeys("aJu\<f5>\<c-p>l\<c-e>", 'tx')
86  call assert_equal(["Jul"], getline(1,2))
87  %d
88
89  " <BS> - Delete one character from the inserted text (state: 2)
90  call feedkeys("a\<f5>\<c-n>\<bs>", 'tx')
91  call assert_equal(["Februar"], getline(1,2))
92  %d
93
94  " <c-l> - Insert one character from the current match
95  call feedkeys("aJ\<f5>".repeat("\<c-n>",3)."\<c-l>\<esc>", 'tx')
96  call assert_equal(["J"], getline(1,2))
97  %d
98
99  " <c-l> - Insert one character from the current match
100  call feedkeys("aJ\<f5>".repeat("\<c-n>",4)."\<c-l>\<esc>", 'tx')
101  call assert_equal(["January"], getline(1,2))
102  %d
103
104  " <c-y> - Accept current selected match
105  call feedkeys("aJ\<f5>\<c-y>\<esc>", 'tx')
106  call assert_equal(["January"], getline(1,2))
107  %d
108
109  " <c-e> - End completion, go back to what was there before selecting a match
110  call feedkeys("aJu\<f5>\<c-e>\<esc>", 'tx')
111  call assert_equal(["Ju"], getline(1,2))
112  %d
113
114  " <PageUp> - Select a match several entries back
115  call feedkeys("a\<f5>\<PageUp>\<c-y>\<esc>", 'tx')
116  call assert_equal([""], getline(1,2))
117  %d
118
119  " <PageUp><PageUp> - Select a match several entries back
120  call feedkeys("a\<f5>\<PageUp>\<PageUp>\<c-y>\<esc>", 'tx')
121  call assert_equal(["December"], getline(1,2))
122  %d
123
124  " <PageUp><PageUp><PageUp> - Select a match several entries back
125  call feedkeys("a\<f5>\<PageUp>\<PageUp>\<PageUp>\<c-y>\<esc>", 'tx')
126  call assert_equal(["February"], getline(1,2))
127  %d
128
129  " <PageDown> - Select a match several entries further
130  call feedkeys("a\<f5>\<PageDown>\<c-y>\<esc>", 'tx')
131  call assert_equal(["November"], getline(1,2))
132  %d
133
134  " <PageDown><PageDown> - Select a match several entries further
135  call feedkeys("a\<f5>\<PageDown>\<PageDown>\<c-y>\<esc>", 'tx')
136  call assert_equal(["December"], getline(1,2))
137  %d
138
139  " <PageDown><PageDown><PageDown> - Select a match several entries further
140  call feedkeys("a\<f5>\<PageDown>\<PageDown>\<PageDown>\<c-y>\<esc>", 'tx')
141  call assert_equal([""], getline(1,2))
142  %d
143
144  " <PageDown><PageDown><PageDown><PageDown> - Select a match several entries further
145  call feedkeys("a\<f5>".repeat("\<PageDown>",4)."\<c-y>\<esc>", 'tx')
146  call assert_equal(["October"], getline(1,2))
147  %d
148
149  " <Up> - Select a match don't insert yet
150  call feedkeys("a\<f5>\<Up>\<c-y>\<esc>", 'tx')
151  call assert_equal([""], getline(1,2))
152  %d
153
154  " <Up><Up> - Select a match don't insert yet
155  call feedkeys("a\<f5>\<Up>\<Up>\<c-y>\<esc>", 'tx')
156  call assert_equal(["December"], getline(1,2))
157  %d
158
159  " <Up><Up><Up> - Select a match don't insert yet
160  call feedkeys("a\<f5>\<Up>\<Up>\<Up>\<c-y>\<esc>", 'tx')
161  call assert_equal(["November"], getline(1,2))
162  %d
163
164  " <Tab> - Stop completion and insert the match
165  call feedkeys("a\<f5>\<Tab>\<c-y>\<esc>", 'tx')
166  call assert_equal(["January	"], getline(1,2))
167  %d
168
169  " <Space> - Stop completion and insert the match
170  call feedkeys("a\<f5>".repeat("\<c-p>",5)." \<esc>", 'tx')
171  call assert_equal(["September "], getline(1,2))
172  %d
173
174  " <Enter> - Use the text and insert line break (state: 1)
175  call feedkeys("a\<f5>\<enter>\<esc>", 'tx')
176  call assert_equal(["January", ''], getline(1,2))
177  %d
178
179  " <Enter> - Insert the current selected text (state: 2)
180  call feedkeys("a\<f5>".repeat("\<Up>",5)."\<enter>\<esc>", 'tx')
181  call assert_equal(["September"], getline(1,2))
182  %d
183
184  " Insert match immediately, if there is only one match
185  " <c-y> selects a character from the line above
186  call append(0, ["December2015"])
187  call feedkeys("aD\<f5>\<C-Y>\<C-Y>\<C-Y>\<C-Y>\<enter>\<esc>", 'tx')
188  call assert_equal(["December2015", "December2015", ""], getline(1,3))
189  %d
190
191  " use menuone for 'completeopt'
192  " Since for the first <c-y> the menu is still shown, will only select
193  " three letters from the line above
194  set completeopt&vim
195  set completeopt+=menuone
196  call append(0, ["December2015"])
197  call feedkeys("aD\<f5>\<C-Y>\<C-Y>\<C-Y>\<C-Y>\<enter>\<esc>", 'tx')
198  call assert_equal(["December2015", "December201", ""], getline(1,3))
199  %d
200
201  " use longest for 'completeopt'
202  set completeopt&vim
203  call feedkeys("aM\<f5>\<C-N>\<C-P>\<c-e>\<enter>\<esc>", 'tx')
204  set completeopt+=longest
205  call feedkeys("aM\<f5>\<C-N>\<C-P>\<c-e>\<enter>\<esc>", 'tx')
206  call assert_equal(["M", "Ma", ""], getline(1,3))
207  %d
208
209  " use noselect/noinsert for 'completeopt'
210  set completeopt&vim
211  call feedkeys("aM\<f5>\<enter>\<esc>", 'tx')
212  set completeopt+=noselect
213  call feedkeys("aM\<f5>\<enter>\<esc>", 'tx')
214  set completeopt-=noselect completeopt+=noinsert
215  call feedkeys("aM\<f5>\<enter>\<esc>", 'tx')
216  call assert_equal(["March", "M", "March"], getline(1,4))
217  %d
218endfunc
219
220
221func Test_popup_completion_insertmode()
222  new
223  inoremap <F5> <C-R>=ListMonths()<CR>
224
225  call feedkeys("a\<f5>\<down>\<enter>\<esc>", 'tx')
226  call assert_equal('February', getline(1))
227  %d
228  " Set noinsertmode
229  let g:setting = 'noinsertmode'
230  call feedkeys("a\<f5>\<down>\<enter>\<esc>", 'tx')
231  call assert_equal('February', getline(1))
232  call assert_false(pumvisible())
233  %d
234  " Go through all matches, until none is selected
235  let g:setting = ''
236  call feedkeys("a\<f5>". repeat("\<c-n>",12)."\<enter>\<esc>", 'tx')
237  call assert_equal('', getline(1))
238  %d
239  " select previous entry
240  call feedkeys("a\<f5>\<c-p>\<enter>\<esc>", 'tx')
241  call assert_equal('', getline(1))
242  %d
243  " select last entry
244  call feedkeys("a\<f5>\<c-p>\<c-p>\<enter>\<esc>", 'tx')
245  call assert_equal('December', getline(1))
246
247  iunmap <F5>
248endfunc
249
250func Test_noinsert_complete()
251  func! s:complTest1() abort
252    call complete(1, ['source', 'soundfold'])
253    return ''
254  endfunc
255
256  func! s:complTest2() abort
257    call complete(1, ['source', 'soundfold'])
258    return ''
259  endfunc
260
261  new
262  set completeopt+=noinsert
263  inoremap <F5>  <C-R>=s:complTest1()<CR>
264  call feedkeys("i\<F5>soun\<CR>\<CR>\<ESC>.", 'tx')
265  call assert_equal('soundfold', getline(1))
266  call assert_equal('soundfold', getline(2))
267  bwipe!
268
269  new
270  inoremap <F5>  <C-R>=s:complTest2()<CR>
271  call feedkeys("i\<F5>\<CR>\<ESC>", 'tx')
272  call assert_equal('source', getline(1))
273  bwipe!
274
275  set completeopt-=noinsert
276  iunmap <F5>
277endfunc
278
279func Test_complete_no_filter()
280  func! s:complTest1() abort
281    call complete(1, [{'word': 'foobar'}])
282    return ''
283  endfunc
284  func! s:complTest2() abort
285    call complete(1, [{'word': 'foobar', 'equal': 1}])
286    return ''
287  endfunc
288
289  let completeopt = &completeopt
290
291  " without equal=1
292  new
293  set completeopt=menuone,noinsert,menu
294  inoremap <F5>  <C-R>=s:complTest1()<CR>
295  call feedkeys("i\<F5>z\<CR>\<CR>\<ESC>.", 'tx')
296  call assert_equal('z', getline(1))
297  bwipe!
298
299  " with equal=1
300  new
301  set completeopt=menuone,noinsert,menu
302  inoremap <F5>  <C-R>=s:complTest2()<CR>
303  call feedkeys("i\<F5>z\<CR>\<CR>\<ESC>.", 'tx')
304  call assert_equal('foobar', getline(1))
305  bwipe!
306
307  let &completeopt = completeopt
308  iunmap <F5>
309endfunc
310
311func Test_compl_vim_cmds_after_register_expr()
312  func! s:test_func()
313    return 'autocmd '
314  endfunc
315  augroup AAAAA_Group
316    au!
317  augroup END
318
319  new
320  call feedkeys("i\<c-r>=s:test_func()\<CR>\<C-x>\<C-v>\<Esc>", 'tx')
321  call assert_equal('autocmd AAAAA_Group', getline(1))
322  autocmd! AAAAA_Group
323  augroup! AAAAA_Group
324  bwipe!
325endfunc
326
327func DummyCompleteOne(findstart, base)
328  if a:findstart
329    return 0
330  else
331    wincmd n
332    return ['onedef', 'oneDEF']
333  endif
334endfunc
335
336" Test that nothing happens if the 'completefunc' opens
337" a new window (no completion, no crash)
338func Test_completefunc_opens_new_window_one()
339  new
340  let winid = win_getid()
341  setlocal completefunc=DummyCompleteOne
342  call setline(1, 'one')
343  /^one
344  call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E839:')
345  call assert_notequal(winid, win_getid())
346  q!
347  call assert_equal(winid, win_getid())
348  call assert_equal('', getline(1))
349  q!
350endfunc
351
352" Test that nothing happens if the 'completefunc' opens
353" a new window (no completion, no crash)
354func DummyCompleteTwo(findstart, base)
355  if a:findstart
356    wincmd n
357    return 0
358  else
359    return ['twodef', 'twoDEF']
360  endif
361endfunc
362
363" Test that nothing happens if the 'completefunc' opens
364" a new window (no completion, no crash)
365func Test_completefunc_opens_new_window_two()
366  new
367  let winid = win_getid()
368  setlocal completefunc=DummyCompleteTwo
369  call setline(1, 'two')
370  /^two
371  call assert_fails('call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")', 'E764:')
372  call assert_notequal(winid, win_getid())
373  q!
374  call assert_equal(winid, win_getid())
375  call assert_equal('two', getline(1))
376  q!
377endfunc
378
379func DummyCompleteThree(findstart, base)
380  if a:findstart
381    return 0
382  else
383    return ['threedef', 'threeDEF']
384  endif
385endfunc
386
387:"Test that 'completefunc' works when it's OK.
388func Test_completefunc_works()
389  new
390  let winid = win_getid()
391  setlocal completefunc=DummyCompleteThree
392  call setline(1, 'three')
393  /^three
394  call feedkeys("A\<C-X>\<C-U>\<C-N>\<Esc>", "x")
395  call assert_equal(winid, win_getid())
396  call assert_equal('threeDEF', getline(1))
397  q!
398endfunc
399
400func DummyCompleteFour(findstart, base)
401  if a:findstart
402    return 0
403  else
404    call complete_add('four1')
405    call complete_add('four2')
406    call complete_check()
407    call complete_add('four3')
408    call complete_add('four4')
409    call complete_check()
410    call complete_add('four5')
411    call complete_add('four6')
412    return []
413  endif
414endfunc
415
416" Test that 'omnifunc' works when it's OK.
417func Test_omnifunc_with_check()
418  new
419  setlocal omnifunc=DummyCompleteFour
420  call setline(1, 'four')
421  /^four
422  call feedkeys("A\<C-X>\<C-O>\<C-N>\<Esc>", "x")
423  call assert_equal('four2', getline(1))
424
425  call setline(1, 'four')
426  /^four
427  call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<Esc>", "x")
428  call assert_equal('four3', getline(1))
429
430  call setline(1, 'four')
431  /^four
432  call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<C-N>\<C-N>\<Esc>", "x")
433  call assert_equal('four5', getline(1))
434
435  q!
436endfunc
437
438func UndoComplete()
439  call complete(1, ['January', 'February', 'March',
440        \ 'April', 'May', 'June', 'July', 'August', 'September',
441        \ 'October', 'November', 'December'])
442  return ''
443endfunc
444
445" Test that no undo item is created when no completion is inserted
446func Test_complete_no_undo()
447  set completeopt=menu,preview,noinsert,noselect
448  inoremap <Right> <C-R>=UndoComplete()<CR>
449  new
450  call feedkeys("ixxx\<CR>\<CR>yyy\<Esc>k", 'xt')
451  call feedkeys("iaaa\<Esc>0", 'xt')
452  call assert_equal('aaa', getline(2))
453  call feedkeys("i\<Right>\<Esc>", 'xt')
454  call assert_equal('aaa', getline(2))
455  call feedkeys("u", 'xt')
456  call assert_equal('', getline(2))
457
458  call feedkeys("ibbb\<Esc>0", 'xt')
459  call assert_equal('bbb', getline(2))
460  call feedkeys("A\<Right>\<Down>\<CR>\<Esc>", 'xt')
461  call assert_equal('January', getline(2))
462  call feedkeys("u", 'xt')
463  call assert_equal('bbb', getline(2))
464
465  call feedkeys("A\<Right>\<C-N>\<Esc>", 'xt')
466  call assert_equal('January', getline(2))
467  call feedkeys("u", 'xt')
468  call assert_equal('bbb', getline(2))
469
470  iunmap <Right>
471  set completeopt&
472  q!
473endfunc
474
475func DummyCompleteFive(findstart, base)
476  if a:findstart
477    return 0
478  else
479    return [
480          \   { 'word': 'January', 'info': "info1-1\n1-2\n1-3" },
481          \   { 'word': 'February', 'info': "info2-1\n2-2\n2-3" },
482          \   { 'word': 'March', 'info': "info3-1\n3-2\n3-3" },
483          \   { 'word': 'April', 'info': "info4-1\n4-2\n4-3" },
484          \   { 'word': 'May', 'info': "info5-1\n5-2\n5-3" },
485          \ ]
486  endif
487endfunc
488
489" Test that 'completefunc' on Scratch buffer with preview window works when
490" it's OK.
491func Test_completefunc_with_scratch_buffer()
492  new +setlocal\ buftype=nofile\ bufhidden=wipe\ noswapfile
493  set completeopt+=preview
494  setlocal completefunc=DummyCompleteFive
495  call feedkeys("A\<C-X>\<C-U>\<C-N>\<C-N>\<C-N>\<Esc>", "x")
496  call assert_equal(['April'], getline(1, '$'))
497  pclose
498  q!
499  set completeopt&
500endfunc
501
502" <C-E> - select original typed text before the completion started without
503" auto-wrap text.
504func Test_completion_ctrl_e_without_autowrap()
505  new
506  let tw_save = &tw
507  set tw=78
508  let li = [
509        \ '"                                                        zzz',
510        \ '" zzzyyyyyyyyyyyyyyyyyyy']
511  call setline(1, li)
512  0
513  call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx")
514  call assert_equal(li, getline(1, '$'))
515
516  let &tw = tw_save
517  q!
518endfunc
519
520func DummyCompleteSix()
521  call complete(1, ['Hello', 'World'])
522  return ''
523endfunction
524
525" complete() correctly clears the list of autocomplete candidates
526" See #1411
527func Test_completion_clear_candidate_list()
528  new
529  %d
530  " select first entry from the completion popup
531  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>", "tx")
532  call assert_equal('Hello', getline(1))
533  %d
534  " select second entry from the completion popup
535  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>", "tx")
536  call assert_equal('World', getline(1))
537  %d
538  " select original text
539  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>", "tx")
540  call assert_equal('    xxx', getline(1))
541  %d
542  " back at first entry from completion list
543  call feedkeys("a    xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>\<C-N>", "tx")
544  call assert_equal('Hello', getline(1))
545
546  bw!
547endfunc
548
549func Test_completion_respect_bs_option()
550  new
551  let li = ["aaa", "aaa12345", "aaaabcdef", "aaaABC"]
552
553  set bs=indent,eol
554  call setline(1, li)
555  1
556  call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx")
557  call assert_equal('aaa', getline(1))
558
559  %d
560  set bs=indent,eol,start
561  call setline(1, li)
562  1
563  call feedkeys("A\<C-X>\<C-N>\<C-P>\<BS>\<BS>\<BS>\<Esc>", "tx")
564  call assert_equal('', getline(1))
565
566  bw!
567endfunc
568
569func CompleteUndo() abort
570  call complete(1, g:months)
571  return ''
572endfunc
573
574func Test_completion_can_undo()
575  inoremap <Right> <c-r>=CompleteUndo()<cr>
576  set completeopt+=noinsert,noselect
577
578  new
579  call feedkeys("a\<Right>a\<Esc>", 'xt')
580  call assert_equal('a', getline(1))
581  undo
582  call assert_equal('', getline(1))
583
584  bwipe!
585  set completeopt&
586  iunmap <Right>
587endfunc
588
589func Test_completion_comment_formatting()
590  new
591  setl formatoptions=tcqro
592  call feedkeys("o/*\<cr>\<cr>/\<esc>", 'tx')
593  call assert_equal(['', '/*', ' *', ' */'], getline(1,4))
594  %d
595  call feedkeys("o/*\<cr>foobar\<cr>/\<esc>", 'tx')
596  call assert_equal(['', '/*', ' * foobar', ' */'], getline(1,4))
597  %d
598  try
599    call feedkeys("o/*\<cr>\<cr>\<c-x>\<c-u>/\<esc>", 'tx')
600    call assert_report('completefunc not set, should have failed')
601  catch
602    call assert_exception('E764:')
603  endtry
604  call assert_equal(['', '/*', ' *', ' */'], getline(1,4))
605  bwipe!
606endfunc
607
608func MessCompleteMonths()
609  for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep")
610    call complete_add(m)
611    if complete_check()
612      break
613    endif
614  endfor
615  return []
616endfunc
617
618func MessCompleteMore()
619  call complete(1, split("Oct Nov Dec"))
620  return []
621endfunc
622
623func MessComplete(findstart, base)
624  if a:findstart
625    let line = getline('.')
626    let start = col('.') - 1
627    while start > 0 && line[start - 1] =~ '\a'
628      let start -= 1
629    endwhile
630    return start
631  else
632    call MessCompleteMonths()
633    call MessCompleteMore()
634    return []
635  endif
636endfunc
637
638func Test_complete_func_mess()
639  " Calling complete() after complete_add() in 'completefunc' is wrong, but it
640  " should not crash.
641  set completefunc=MessComplete
642  new
643  call setline(1, 'Ju')
644  call feedkeys("A\<c-x>\<c-u>/\<esc>", 'tx')
645  call assert_equal('Oct/Oct', getline(1))
646  bwipe!
647  set completefunc=
648endfunc
649
650func Test_complete_CTRLN_startofbuffer()
651  new
652  call setline(1, [ 'organize(cupboard, 3, 2);',
653        \ 'prioritize(bureau, 8, 7);',
654        \ 'realize(bannister, 4, 4);',
655        \ 'moralize(railing, 3,9);'])
656  let expected=['cupboard.organize(3, 2);',
657        \ 'bureau.prioritize(8, 7);',
658        \ 'bannister.realize(4, 4);',
659        \ 'railing.moralize(3,9);']
660  call feedkeys("qai\<c-n>\<c-n>.\<esc>3wdW\<cr>q3@a", 'tx')
661  call assert_equal(expected, getline(1,'$'))
662  bwipe!
663endfunc
664
665func Test_popup_and_window_resize()
666  if !has('terminal') || has('gui_running')
667    return
668  endif
669  let h = winheight(0)
670  if h < 15
671    return
672  endif
673  let rows = h / 3
674  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': rows})
675  call term_sendkeys(buf, (h / 3 - 1) . "o\<esc>")
676  " Wait for the nested Vim to exit insert mode, where it will show the ruler.
677  " Need to trigger a redraw.
678  call WaitFor({-> execute("redraw") == "" && term_getline(buf, rows) =~ '\<' . rows . ',.*Bot'})
679
680  call term_sendkeys(buf, "Gi\<c-x>")
681  call term_sendkeys(buf, "\<c-v>")
682  call term_wait(buf, 100)
683  " popup first entry "!" must be at the top
684  call WaitForAssert({-> assert_match('^!\s*$', term_getline(buf, 1))})
685  exe 'resize +' . (h - 1)
686  call term_wait(buf, 100)
687  redraw!
688  " popup shifted down, first line is now empty
689  call WaitForAssert({-> assert_equal('', term_getline(buf, 1))})
690  sleep 100m
691  " popup is below cursor line and shows first match "!"
692  call WaitForAssert({-> assert_match('^!\s*$', term_getline(buf, term_getcursor(buf)[0] + 1))})
693  " cursor line also shows !
694  call assert_match('^!\s*$', term_getline(buf, term_getcursor(buf)[0]))
695  bwipe!
696endfunc
697
698func Test_popup_and_preview_autocommand()
699  " This used to crash Vim
700  if !has('python')
701    return
702  endif
703  let h = winheight(0)
704  if h < 15
705    return
706  endif
707  new
708  augroup MyBufAdd
709    au!
710    au BufAdd * nested tab sball
711  augroup END
712  set omnifunc=pythoncomplete#Complete
713  call setline(1, 'import os')
714  " make the line long
715  call setline(2, '                                 os.')
716  $
717  call feedkeys("A\<C-X>\<C-O>\<C-N>\<C-N>\<C-N>\<enter>\<esc>", 'tx')
718  call assert_equal("import os", getline(1))
719  call assert_match('                                 os.\(EX_IOERR\|O_CREAT\)$', getline(2))
720  call assert_equal(1, winnr('$'))
721  " previewwindow option is not set
722  call assert_equal(0, &previewwindow)
723  norm! gt
724  call assert_equal(0, &previewwindow)
725  norm! gT
726  call assert_equal(10, tabpagenr('$'))
727  tabonly
728  pclose
729  augroup MyBufAdd
730    au!
731  augroup END
732  augroup! MyBufAdd
733  bw!
734endfunc
735
736func Test_popup_and_previewwindow_dump()
737  if !CanRunVimInTerminal()
738    throw 'Skipped: cannot make screendumps'
739  endif
740  let lines =<< trim END
741    set previewheight=9
742    silent! pedit
743    call setline(1, map(repeat(["ab"], 10), "v:val. v:key"))
744    exec "norm! G\<C-E>\<C-E>"
745  END
746  call writefile(lines, 'Xscript')
747  let buf = RunVimInTerminal('-S Xscript', {})
748
749  " Test that popup and previewwindow do not overlap.
750  call term_sendkeys(buf, "o\<C-X>\<C-N>")
751  sleep 100m
752  call VerifyScreenDump(buf, 'Test_popup_and_previewwindow_01', {})
753
754  call term_sendkeys(buf, "\<Esc>u")
755  call StopVimInTerminal(buf)
756  call delete('Xscript')
757endfunc
758
759func Test_balloon_split()
760  if !exists('*balloon_split')
761    return
762  endif
763  call assert_equal([
764        \ 'tempname: 0x555555e380a0 "/home/mool/.viminfz.tmp"',
765        \ ], balloon_split(
766        \ 'tempname: 0x555555e380a0 "/home/mool/.viminfz.tmp"'))
767  call assert_equal([
768        \ 'one two three four one two three four one two thre',
769        \ 'e four',
770        \ ], balloon_split(
771        \ 'one two three four one two three four one two three four'))
772
773  call assert_equal([
774        \ 'struct = {',
775        \ '  one = 1,',
776        \ '  two = 2,',
777        \ '  three = 3}',
778        \ ], balloon_split(
779        \ 'struct = {one = 1, two = 2, three = 3}'))
780
781  call assert_equal([
782        \ 'struct = {',
783        \ '  one = 1,',
784        \ '  nested = {',
785        \ '    n1 = "yes",',
786        \ '    n2 = "no"}',
787        \ '  two = 2}',
788        \ ], balloon_split(
789        \ 'struct = {one = 1, nested = {n1 = "yes", n2 = "no"} two = 2}'))
790  call assert_equal([
791        \ 'struct = 0x234 {',
792        \ '  long = 2343 "\\"some long string that will be wr',
793        \ 'apped in two\\"",',
794        \ '  next = 123}',
795        \ ], balloon_split(
796        \ 'struct = 0x234 {long = 2343 "\\"some long string that will be wrapped in two\\"", next = 123}'))
797endfunc
798
799func Test_popup_position()
800  if !CanRunVimInTerminal()
801    throw 'Skipped: cannot make screendumps'
802  endif
803  let lines =<< trim END
804    123456789_123456789_123456789_a
805    123456789_123456789_123456789_b
806                123
807  END
808  call writefile(lines, 'Xtest')
809  let buf = RunVimInTerminal('Xtest', {})
810  call term_sendkeys(buf, ":vsplit\<CR>")
811
812  " default pumwidth in left window: overlap in right window
813  call term_sendkeys(buf, "GA\<C-N>")
814  call VerifyScreenDump(buf, 'Test_popup_position_01', {'rows': 8})
815  call term_sendkeys(buf, "\<Esc>u")
816
817  " default pumwidth: fill until right of window
818  call term_sendkeys(buf, "\<C-W>l")
819  call term_sendkeys(buf, "GA\<C-N>")
820  call VerifyScreenDump(buf, 'Test_popup_position_02', {'rows': 8})
821
822  " larger pumwidth: used as minimum width
823  call term_sendkeys(buf, "\<Esc>u")
824  call term_sendkeys(buf, ":set pumwidth=30\<CR>")
825  call term_sendkeys(buf, "GA\<C-N>")
826  call VerifyScreenDump(buf, 'Test_popup_position_03', {'rows': 8})
827
828  " completed text wider than the window and 'pumwidth' smaller than available
829  " space
830  call term_sendkeys(buf, "\<Esc>u")
831  call term_sendkeys(buf, ":set pumwidth=20\<CR>")
832  call term_sendkeys(buf, "ggI123456789_\<Esc>")
833  call term_sendkeys(buf, "jI123456789_\<Esc>")
834  call term_sendkeys(buf, "GA\<C-N>")
835  call VerifyScreenDump(buf, 'Test_popup_position_04', {'rows': 10})
836
837  call term_sendkeys(buf, "\<Esc>u")
838  call StopVimInTerminal(buf)
839  call delete('Xtest')
840endfunc
841
842func Test_popup_command()
843  if !CanRunVimInTerminal() || !has('menu')
844    throw 'Skipped: cannot make screendumps and/or menu feature missing'
845  endif
846
847  let lines =<< trim END
848	one two three four five
849	and one two Xthree four five
850	one more two three four five
851  END
852  call writefile(lines, 'Xtest')
853  let buf = RunVimInTerminal('Xtest', {})
854  call term_sendkeys(buf, ":source $VIMRUNTIME/menu.vim\<CR>")
855  call term_sendkeys(buf, "/X\<CR>:popup PopUp\<CR>")
856  call VerifyScreenDump(buf, 'Test_popup_command_01', {})
857
858  " Select a word
859  call term_sendkeys(buf, "jj")
860  call VerifyScreenDump(buf, 'Test_popup_command_02', {})
861
862  " Select a word
863  call term_sendkeys(buf, "j\<CR>")
864  call VerifyScreenDump(buf, 'Test_popup_command_03', {})
865
866  call term_sendkeys(buf, "\<Esc>")
867  call StopVimInTerminal(buf)
868  call delete('Xtest')
869endfunc
870
871func Test_popup_complete_backwards()
872  new
873  call setline(1, ['Post', 'Port', 'Po'])
874  let expected=['Post', 'Port', 'Port']
875  call cursor(3,2)
876  call feedkeys("A\<C-X>". repeat("\<C-P>", 3). "rt\<cr>", 'tx')
877  call assert_equal(expected, getline(1,'$'))
878  bwipe!
879endfunc
880
881func Test_popup_complete_backwards_ctrl_p()
882  new
883  call setline(1, ['Post', 'Port', 'Po'])
884  let expected=['Post', 'Port', 'Port']
885  call cursor(3,2)
886  call feedkeys("A\<C-P>\<C-N>rt\<cr>", 'tx')
887  call assert_equal(expected, getline(1,'$'))
888  bwipe!
889endfunc
890
891func Test_complete_o_tab()
892  let s:o_char_pressed = 0
893
894  fun! s:act_on_text_changed()
895    if s:o_char_pressed
896      let s:o_char_pressed = 0
897      call feedkeys("\<c-x>\<c-n>", 'i')
898    endif
899  endfunc
900
901  set completeopt=menu,noselect
902  new
903  imap <expr> <buffer> <tab> pumvisible() ? "\<c-p>" : "X"
904  autocmd! InsertCharPre <buffer> let s:o_char_pressed = (v:char ==# 'o')
905  autocmd! TextChangedI <buffer> call <sid>act_on_text_changed()
906  call setline(1,  ['hoard', 'hoax', 'hoarse', ''])
907  let l:expected = ['hoard', 'hoax', 'hoarse', 'hoax', 'hoax']
908  call cursor(4,1)
909  call test_override("char_avail", 1)
910  call feedkeys("Ahoa\<tab>\<tab>\<c-y>\<esc>", 'tx')
911  call feedkeys("oho\<tab>\<tab>\<c-y>\<esc>", 'tx')
912  call assert_equal(l:expected, getline(1,'$'))
913
914  call test_override("char_avail", 0)
915  bwipe!
916  set completeopt&
917  delfunc s:act_on_text_changed
918endfunc
919
920func Test_menu_only_exists_in_terminal()
921  if !exists(':tlmenu') || has('gui_running')
922    return
923  endif
924  tlnoremenu  &Edit.&Paste<Tab>"+gP  <C-W>"+
925  aunmenu *
926  try
927    popup Edit
928    call assert_false(1, 'command should have failed')
929  catch
930    call assert_exception('E328:')
931  endtry
932endfunc
933
934func Test_popup_complete_info_01()
935  new
936  inoremap <buffer><F5> <C-R>=complete_info().mode<CR>
937  func s:complTestEval() abort
938    call complete(1, ['aa', 'ab'])
939    return ''
940  endfunc
941  inoremap <buffer><F6> <C-R>=s:complTestEval()<CR>
942  call writefile([
943        \ 'dummy	dummy.txt	1',
944        \], 'Xdummy.txt')
945  setlocal tags=Xdummy.txt
946  setlocal dictionary=Xdummy.txt
947  setlocal thesaurus=Xdummy.txt
948  setlocal omnifunc=syntaxcomplete#Complete
949  setlocal completefunc=syntaxcomplete#Complete
950  setlocal spell
951  for [keys, mode_name] in [
952        \ ["", ''],
953        \ ["\<C-X>", 'ctrl_x'],
954        \ ["\<C-X>\<C-N>", 'keyword'],
955        \ ["\<C-X>\<C-P>", 'keyword'],
956        \ ["\<C-X>\<C-L>", 'whole_line'],
957        \ ["\<C-X>\<C-F>", 'files'],
958        \ ["\<C-X>\<C-]>", 'tags'],
959        \ ["\<C-X>\<C-D>", 'path_defines'],
960        \ ["\<C-X>\<C-I>", 'path_patterns'],
961        \ ["\<C-X>\<C-K>", 'dictionary'],
962        \ ["\<C-X>\<C-T>", 'thesaurus'],
963        \ ["\<C-X>\<C-V>", 'cmdline'],
964        \ ["\<C-X>\<C-U>", 'function'],
965        \ ["\<C-X>\<C-O>", 'omni'],
966        \ ["\<C-X>s", 'spell'],
967        \ ["\<F6>", 'eval'],
968        \]
969    call feedkeys("i" . keys . "\<F5>\<Esc>", 'tx')
970    call assert_equal(mode_name, getline('.'))
971    %d
972  endfor
973  call delete('Xdummy.txt')
974  bwipe!
975endfunc
976
977func UserDefinedComplete(findstart, base)
978  if a:findstart
979    return 0
980  else
981    return [
982          \   { 'word': 'Jan', 'menu': 'January' },
983          \   { 'word': 'Feb', 'menu': 'February' },
984          \   { 'word': 'Mar', 'menu': 'March' },
985          \   { 'word': 'Apr', 'menu': 'April' },
986          \   { 'word': 'May', 'menu': 'May' },
987          \ ]
988  endif
989endfunc
990
991func GetCompleteInfo()
992  if empty(g:compl_what)
993    let g:compl_info = complete_info()
994  else
995    let g:compl_info = complete_info(g:compl_what)
996  endif
997  return ''
998endfunc
999
1000func Test_popup_complete_info_02()
1001  new
1002  inoremap <buffer><F5> <C-R>=GetCompleteInfo()<CR>
1003  setlocal completefunc=UserDefinedComplete
1004
1005  let d = {
1006    \   'mode': 'function',
1007    \   'pum_visible': 1,
1008    \   'items': [
1009    \     {'word': 'Jan', 'menu': 'January', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
1010    \     {'word': 'Feb', 'menu': 'February', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
1011    \     {'word': 'Mar', 'menu': 'March', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
1012    \     {'word': 'Apr', 'menu': 'April', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''},
1013    \     {'word': 'May', 'menu': 'May', 'user_data': '', 'info': '', 'kind': '', 'abbr': ''}
1014    \   ],
1015    \   'selected': 0,
1016    \ }
1017
1018  let g:compl_what = []
1019  call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
1020  call assert_equal(d, g:compl_info)
1021
1022  let g:compl_what = ['mode', 'pum_visible', 'selected']
1023  call remove(d, 'items')
1024  call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
1025  call assert_equal(d, g:compl_info)
1026
1027  let g:compl_what = ['mode']
1028  call remove(d, 'selected')
1029  call remove(d, 'pum_visible')
1030  call feedkeys("i\<C-X>\<C-U>\<F5>", 'tx')
1031  call assert_equal(d, g:compl_info)
1032  bwipe!
1033endfunc
1034
1035func Test_CompleteChanged()
1036  new
1037  call setline(1, ['foo', 'bar', 'foobar', ''])
1038  set complete=. completeopt=noinsert,noselect,menuone
1039  function! OnPumChange()
1040    let g:event = copy(v:event)
1041    let g:item = get(v:event, 'completed_item', {})
1042    let g:word = get(g:item, 'word', v:null)
1043  endfunction
1044  augroup AAAAA_Group
1045    au!
1046    autocmd CompleteChanged * :call OnPumChange()
1047  augroup END
1048  call cursor(4, 1)
1049
1050  call feedkeys("Sf\<C-N>", 'tx')
1051  call assert_equal({'completed_item': {}, 'width': 15,
1052        \ 'height': 2, 'size': 2,
1053        \ 'col': 0, 'row': 4, 'scrollbar': v:false}, g:event)
1054  call feedkeys("a\<C-N>\<C-N>\<C-E>", 'tx')
1055  call assert_equal('foo', g:word)
1056  call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-E>", 'tx')
1057  call assert_equal('foobar', g:word)
1058  call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-N>\<C-E>", 'tx')
1059  call assert_equal(v:null, g:word)
1060  call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 'tx')
1061  call assert_equal('foobar', g:word)
1062
1063  autocmd! AAAAA_Group
1064  set complete& completeopt&
1065  delfunc! OnPumchange
1066  bw!
1067endfunc
1068
1069" vim: shiftwidth=2 sts=2 expandtab
1070