xref: /vim-8.2.3635/src/testdir/test_search.vim (revision bc93cebb)
1" Test for the search command
2
3source shared.vim
4source screendump.vim
5source check.vim
6
7func Test_search_cmdline()
8  if !exists('+incsearch')
9    return
10  endif
11  " need to disable char_avail,
12  " so that expansion of commandline works
13  call test_override("char_avail", 1)
14  new
15  call setline(1, ['  1', '  2 these', '  3 the', '  4 their', '  5 there', '  6 their', '  7 the', '  8 them', '  9 these', ' 10 foobar'])
16  " Test 1
17  " CTRL-N / CTRL-P skips through the previous search history
18  set noincsearch
19  :1
20  call feedkeys("/foobar\<cr>", 'tx')
21  call feedkeys("/the\<cr>",'tx')
22  call assert_equal('the', @/)
23  call feedkeys("/thes\<C-P>\<C-P>\<cr>",'tx')
24  call assert_equal('foobar', @/)
25
26  " Test 2
27  " Ctrl-G goes from one match to the next
28  " until the end of the buffer
29  set incsearch nowrapscan
30  :1
31  " first match
32  call feedkeys("/the\<cr>", 'tx')
33  call assert_equal('  2 these', getline('.'))
34  :1
35  " second match
36  call feedkeys("/the\<C-G>\<cr>", 'tx')
37  call assert_equal('  3 the', getline('.'))
38  call assert_equal([0, 0, 0, 0], getpos('"'))
39  :1
40  " third match
41  call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
42  call assert_equal('  4 their', getline('.'))
43  :1
44  " fourth match
45  call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
46  call assert_equal('  5 there', getline('.'))
47  :1
48  " fifth match
49  call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
50  call assert_equal('  6 their', getline('.'))
51  :1
52  " sixth match
53  call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
54  call assert_equal('  7 the', getline('.'))
55  :1
56  " seventh match
57  call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
58  call assert_equal('  8 them', getline('.'))
59  :1
60  " eighth match
61  call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
62  call assert_equal('  9 these', getline('.'))
63  :1
64  " no further match
65  call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
66  call assert_equal('  9 these', getline('.'))
67  call assert_equal([0, 0, 0, 0], getpos('"'))
68
69  " Test 3
70  " Ctrl-G goes from one match to the next
71  " and continues back at the top
72  set incsearch wrapscan
73  :1
74  " first match
75  call feedkeys("/the\<cr>", 'tx')
76  call assert_equal('  2 these', getline('.'))
77  :1
78  " second match
79  call feedkeys("/the\<C-G>\<cr>", 'tx')
80  call assert_equal('  3 the', getline('.'))
81  :1
82  " third match
83  call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
84  call assert_equal('  4 their', getline('.'))
85  :1
86  " fourth match
87  call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
88  call assert_equal('  5 there', getline('.'))
89  :1
90  " fifth match
91  call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
92  call assert_equal('  6 their', getline('.'))
93  :1
94  " sixth match
95  call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
96  call assert_equal('  7 the', getline('.'))
97  :1
98  " seventh match
99  call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
100  call assert_equal('  8 them', getline('.'))
101  :1
102  " eighth match
103  call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
104  call assert_equal('  9 these', getline('.'))
105  :1
106  " back at first match
107  call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
108  call assert_equal('  2 these', getline('.'))
109
110  " Test 4
111  " CTRL-T goes to the previous match
112  set incsearch nowrapscan
113  $
114  " first match
115  call feedkeys("?the\<cr>", 'tx')
116  call assert_equal('  9 these', getline('.'))
117  $
118  " first match
119  call feedkeys("?the\<C-G>\<cr>", 'tx')
120  call assert_equal('  9 these', getline('.'))
121  $
122  " second match
123  call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
124  call assert_equal('  8 them', getline('.'))
125  $
126  " last match
127  call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
128  call assert_equal('  2 these', getline('.'))
129  $
130  " last match
131  call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx')
132  call assert_equal('  2 these', getline('.'))
133
134  " Test 5
135  " CTRL-T goes to the previous match
136  set incsearch wrapscan
137  $
138  " first match
139  call feedkeys("?the\<cr>", 'tx')
140  call assert_equal('  9 these', getline('.'))
141  $
142  " first match at the top
143  call feedkeys("?the\<C-G>\<cr>", 'tx')
144  call assert_equal('  2 these', getline('.'))
145  $
146  " second match
147  call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
148  call assert_equal('  8 them', getline('.'))
149  $
150  " last match
151  call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
152  call assert_equal('  2 these', getline('.'))
153  $
154  " back at the bottom of the buffer
155  call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx')
156  call assert_equal('  9 these', getline('.'))
157
158  " Test 6
159  " CTRL-L adds to the search pattern
160  set incsearch wrapscan
161  1
162  " first match
163  call feedkeys("/the\<c-l>\<cr>", 'tx')
164  call assert_equal('  2 these', getline('.'))
165  1
166  " go to next match of 'thes'
167  call feedkeys("/the\<c-l>\<C-G>\<cr>", 'tx')
168  call assert_equal('  9 these', getline('.'))
169  1
170  " wrap around
171  call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx')
172  call assert_equal('  2 these', getline('.'))
173  1
174  " wrap around
175  set nowrapscan
176  call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx')
177  call assert_equal('  9 these', getline('.'))
178
179  " Test 7
180  " <bs> remove from match, but stay at current match
181  set incsearch wrapscan
182  1
183  " first match
184  call feedkeys("/thei\<cr>", 'tx')
185  call assert_equal('  4 their', getline('.'))
186  1
187  " delete one char, add another
188  call feedkeys("/thei\<bs>s\<cr>", 'tx')
189  call assert_equal('  2 these', getline('.'))
190  1
191  " delete one char, add another,  go to previous match, add one char
192  call feedkeys("/thei\<bs>s\<bs>\<C-T>\<c-l>\<cr>", 'tx')
193  call assert_equal('  9 these', getline('.'))
194  1
195  " delete all chars, start from the beginning again
196  call feedkeys("/them". repeat("\<bs>",4).'the\>'."\<cr>", 'tx')
197  call assert_equal('  3 the', getline('.'))
198
199  " clean up
200  call test_override("char_avail", 0)
201  bw!
202endfunc
203
204func Test_search_cmdline2()
205  if !exists('+incsearch')
206    return
207  endif
208  " need to disable char_avail,
209  " so that expansion of commandline works
210  call test_override("char_avail", 1)
211  new
212  call setline(1, ['  1', '  2 these', '  3 the theother'])
213  " Test 1
214  " Ctrl-T goes correctly back and forth
215  set incsearch
216  1
217  " first match
218  call feedkeys("/the\<cr>", 'tx')
219  call assert_equal('  2 these', getline('.'))
220  1
221  " go to next match (on next line)
222  call feedkeys("/the\<C-G>\<cr>", 'tx')
223  call assert_equal('  3 the theother', getline('.'))
224  1
225  " go to next match (still on line 3)
226  call feedkeys("/the\<C-G>\<C-G>\<cr>", 'tx')
227  call assert_equal('  3 the theother', getline('.'))
228  1
229  " go to next match (still on line 3)
230  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<cr>", 'tx')
231  call assert_equal('  3 the theother', getline('.'))
232  1
233  " go to previous match (on line 3)
234  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<cr>", 'tx')
235  call assert_equal('  3 the theother', getline('.'))
236  1
237  " go to previous match (on line 3)
238  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<cr>", 'tx')
239  call assert_equal('  3 the theother', getline('.'))
240  1
241  " go to previous match (on line 2)
242  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<C-T>\<cr>", 'tx')
243  call assert_equal('  2 these', getline('.'))
244  1
245  " go to previous match (on line 2)
246  call feedkeys("/the\<C-G>\<C-R>\<C-W>\<cr>", 'tx')
247  call assert_equal('theother', @/)
248
249  " Test 2: keep the view,
250  " after deleting a character from the search cmd
251  call setline(1, ['  1', '  2 these', '  3 the', '  4 their', '  5 there', '  6 their', '  7 the', '  8 them', '  9 these', ' 10 foobar'])
252  resize 5
253  1
254  call feedkeys("/foo\<bs>\<cr>", 'tx')
255  redraw
256  call assert_equal({'lnum': 10, 'leftcol': 0, 'col': 4, 'topfill': 0, 'topline': 6, 'coladd': 0, 'skipcol': 0, 'curswant': 4}, winsaveview())
257
258  " remove all history entries
259  for i in range(11)
260      call histdel('/')
261  endfor
262
263  " Test 3: reset the view,
264  " after deleting all characters from the search cmd
265  norm! 1gg0
266  " unfortunately, neither "/foo\<c-w>\<cr>", nor "/foo\<bs>\<bs>\<bs>\<cr>",
267  " nor "/foo\<c-u>\<cr>" works to delete the commandline.
268  " In that case Vim should return "E35 no previous regular expression",
269  " but it looks like Vim still sees /foo and therefore the test fails.
270  " Therefore, disabling this test
271  "call assert_fails(feedkeys("/foo\<c-w>\<cr>", 'tx'), 'E35')
272  "call assert_equal({'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0}, winsaveview())
273
274  " clean up
275  set noincsearch
276  call test_override("char_avail", 0)
277  bw!
278endfunc
279
280func Test_use_sub_pat()
281  split
282  let @/ = ''
283  func X()
284    s/^/a/
285    /
286  endfunc
287  call X()
288  bwipe!
289endfunc
290
291func Test_searchpair()
292  new
293  call setline(1, ['other code', 'here [', ' [', ' " cursor here', ' ]]'])
294
295  4
296  call assert_equal(3, searchpair('\[', '', ']', 'bW'))
297  call assert_equal([0, 3, 2, 0], getpos('.'))
298  4
299  call assert_equal(2, searchpair('\[', '', ']', 'bWr'))
300  call assert_equal([0, 2, 6, 0], getpos('.'))
301  4
302  call assert_equal(1, searchpair('\[', '', ']', 'bWm'))
303  call assert_equal([0, 3, 2, 0], getpos('.'))
304  4|norm ^
305  call assert_equal(5, searchpair('\[', '', ']', 'Wn'))
306  call assert_equal([0, 4, 2, 0], getpos('.'))
307  4
308  call assert_equal(2, searchpair('\[', '', ']', 'bW',
309        \                         'getline(".") =~ "^\\s*\["'))
310  call assert_equal([0, 2, 6, 0], getpos('.'))
311  set nomagic
312  4
313  call assert_equal(3, searchpair('\[', '', ']', 'bW'))
314  call assert_equal([0, 3, 2, 0], getpos('.'))
315  set magic
316  4|norm ^
317  call assert_equal(0, searchpair('{', '', '}', 'bW'))
318  call assert_equal([0, 4, 2, 0], getpos('.'))
319
320  %d
321  call setline(1, ['if 1', '  if 2', '  else', '  endif 2', 'endif 1'])
322
323  /\<if 1
324  call assert_equal(5, searchpair('\<if\>', '\<else\>', '\<endif\>', 'W'))
325  call assert_equal([0, 5, 1, 0], getpos('.'))
326  /\<if 2
327  call assert_equal(3, searchpair('\<if\>', '\<else\>', '\<endif\>', 'W'))
328  call assert_equal([0, 3, 3, 0], getpos('.'))
329
330  q!
331endfunc
332
333func Test_searchpairpos()
334  new
335  call setline(1, ['other code', 'here [', ' [', ' " cursor here', ' ]]'])
336
337  4
338  call assert_equal([3, 2], searchpairpos('\[', '', ']', 'bW'))
339  call assert_equal([0, 3, 2, 0], getpos('.'))
340  4
341  call assert_equal([2, 6], searchpairpos('\[', '', ']', 'bWr'))
342  call assert_equal([0, 2, 6, 0], getpos('.'))
343  4|norm ^
344  call assert_equal([5, 2], searchpairpos('\[', '', ']', 'Wn'))
345  call assert_equal([0, 4, 2, 0], getpos('.'))
346  4
347  call assert_equal([2, 6], searchpairpos('\[', '', ']', 'bW',
348        \                                 'getline(".") =~ "^\\s*\["'))
349  call assert_equal([0, 2, 6, 0], getpos('.'))
350  4
351  call assert_equal([2, 6], searchpairpos('\[', '', ']', 'bWr'))
352  call assert_equal([0, 2, 6, 0], getpos('.'))
353  set nomagic
354  4
355  call assert_equal([3, 2], searchpairpos('\[', '', ']', 'bW'))
356  call assert_equal([0, 3, 2, 0], getpos('.'))
357  set magic
358  4|norm ^
359  call assert_equal([0, 0], searchpairpos('{', '', '}', 'bW'))
360  call assert_equal([0, 4, 2, 0], getpos('.'))
361
362  %d
363  call setline(1, ['if 1', '  if 2', '  else', '  endif 2', 'endif 1'])
364  /\<if 1
365  call assert_equal([5, 1], searchpairpos('\<if\>', '\<else\>', '\<endif\>', 'W'))
366  call assert_equal([0, 5, 1, 0], getpos('.'))
367  /\<if 2
368  call assert_equal([3, 3], searchpairpos('\<if\>', '\<else\>', '\<endif\>', 'W'))
369  call assert_equal([0, 3, 3, 0], getpos('.'))
370
371  q!
372endfunc
373
374func Test_searchpair_errors()
375  call assert_fails("call searchpair([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: using List as a String')
376  call assert_fails("call searchpair('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: using Funcref as a String')
377  call assert_fails("call searchpair('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: using Dictionary as a String')
378  call assert_fails("call searchpair('start', 'middle', 'end', 'flags', 'skip', 99, 100)", 'E475: Invalid argument: flags')
379  call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 0, 99, 100)", 'E475: Invalid argument: 0')
380  call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 'func', -99, 100)", 'E475: Invalid argument: -99')
381  call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 'func', 99, -100)", 'E475: Invalid argument: -100')
382  call assert_fails("call searchpair('start', 'middle', 'end', 'e')", 'E475: Invalid argument: e')
383  call assert_fails("call searchpair('start', 'middle', 'end', 'sn')", 'E475: Invalid argument: sn')
384endfunc
385
386func Test_searchpairpos_errors()
387  call assert_fails("call searchpairpos([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: using List as a String')
388  call assert_fails("call searchpairpos('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: using Funcref as a String')
389  call assert_fails("call searchpairpos('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: using Dictionary as a String')
390  call assert_fails("call searchpairpos('start', 'middle', 'end', 'flags', 'skip', 99, 100)", 'E475: Invalid argument: flags')
391  call assert_fails("call searchpairpos('start', 'middle', 'end', 'bW', 0, 99, 100)", 'E475: Invalid argument: 0')
392  call assert_fails("call searchpairpos('start', 'middle', 'end', 'bW', 'func', -99, 100)", 'E475: Invalid argument: -99')
393  call assert_fails("call searchpairpos('start', 'middle', 'end', 'bW', 'func', 99, -100)", 'E475: Invalid argument: -100')
394  call assert_fails("call searchpairpos('start', 'middle', 'end', 'e')", 'E475: Invalid argument: e')
395  call assert_fails("call searchpairpos('start', 'middle', 'end', 'sn')", 'E475: Invalid argument: sn')
396endfunc
397
398func Test_searchpair_skip()
399    func Zero()
400      return 0
401    endfunc
402    func Partial(x)
403      return a:x
404    endfunc
405    new
406    call setline(1, ['{', 'foo', 'foo', 'foo', '}'])
407    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', ''))
408    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', '0'))
409    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', {-> 0}))
410    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', function('Zero')))
411    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', function('Partial', [0])))
412    bw!
413endfunc
414
415func Test_searchpair_leak()
416  new
417  call setline(1, 'if one else another endif')
418
419  " The error in the skip expression caused memory to leak.
420  call assert_fails("call searchpair('\\<if\\>', '\\<else\\>', '\\<endif\\>', '', '\"foo\" 2')", 'E15:')
421
422  bwipe!
423endfunc
424
425func Test_searchc()
426  " These commands used to cause memory overflow in searchc().
427  new
428  norm ixx
429  exe "norm 0t\u93cf"
430  bw!
431endfunc
432
433func Cmdline3_prep()
434  " need to disable char_avail,
435  " so that expansion of commandline works
436  call test_override("char_avail", 1)
437  new
438  call setline(1, ['  1', '  2 the~e', '  3 the theother'])
439  set incsearch
440endfunc
441
442func Incsearch_cleanup()
443  set noincsearch
444  call test_override("char_avail", 0)
445  bw!
446endfunc
447
448func Test_search_cmdline3()
449  if !exists('+incsearch')
450    return
451  endif
452  call Cmdline3_prep()
453  1
454  " first match
455  call feedkeys("/the\<c-l>\<cr>", 'tx')
456  call assert_equal('  2 the~e', getline('.'))
457
458  call Incsearch_cleanup()
459endfunc
460
461func Test_search_cmdline3s()
462  if !exists('+incsearch')
463    return
464  endif
465  call Cmdline3_prep()
466  1
467  call feedkeys(":%s/the\<c-l>/xxx\<cr>", 'tx')
468  call assert_equal('  2 xxxe', getline('.'))
469  undo
470  call feedkeys(":%subs/the\<c-l>/xxx\<cr>", 'tx')
471  call assert_equal('  2 xxxe', getline('.'))
472  undo
473  call feedkeys(":%substitute/the\<c-l>/xxx\<cr>", 'tx')
474  call assert_equal('  2 xxxe', getline('.'))
475  undo
476  call feedkeys(":%smagic/the.e/xxx\<cr>", 'tx')
477  call assert_equal('  2 xxx', getline('.'))
478  undo
479  call assert_fails(":%snomagic/the.e/xxx\<cr>", 'E486')
480  "
481  call feedkeys(":%snomagic/the\\.e/xxx\<cr>", 'tx')
482  call assert_equal('  2 xxx', getline('.'))
483
484  call Incsearch_cleanup()
485endfunc
486
487func Test_search_cmdline3g()
488  if !exists('+incsearch')
489    return
490  endif
491  call Cmdline3_prep()
492  1
493  call feedkeys(":g/the\<c-l>/d\<cr>", 'tx')
494  call assert_equal('  3 the theother', getline(2))
495  undo
496  call feedkeys(":global/the\<c-l>/d\<cr>", 'tx')
497  call assert_equal('  3 the theother', getline(2))
498  undo
499  call feedkeys(":g!/the\<c-l>/d\<cr>", 'tx')
500  call assert_equal(1, line('$'))
501  call assert_equal('  2 the~e', getline(1))
502  undo
503  call feedkeys(":global!/the\<c-l>/d\<cr>", 'tx')
504  call assert_equal(1, line('$'))
505  call assert_equal('  2 the~e', getline(1))
506
507  call Incsearch_cleanup()
508endfunc
509
510func Test_search_cmdline3v()
511  if !exists('+incsearch')
512    return
513  endif
514  call Cmdline3_prep()
515  1
516  call feedkeys(":v/the\<c-l>/d\<cr>", 'tx')
517  call assert_equal(1, line('$'))
518  call assert_equal('  2 the~e', getline(1))
519  undo
520  call feedkeys(":vglobal/the\<c-l>/d\<cr>", 'tx')
521  call assert_equal(1, line('$'))
522  call assert_equal('  2 the~e', getline(1))
523
524  call Incsearch_cleanup()
525endfunc
526
527func Test_search_cmdline4()
528  if !exists('+incsearch')
529    return
530  endif
531  " need to disable char_avail,
532  " so that expansion of commandline works
533  call test_override("char_avail", 1)
534  new
535  call setline(1, ['  1 the first', '  2 the second', '  3 the third'])
536  set incsearch
537  $
538  call feedkeys("?the\<c-g>\<cr>", 'tx')
539  call assert_equal('  3 the third', getline('.'))
540  $
541  call feedkeys("?the\<c-g>\<c-g>\<cr>", 'tx')
542  call assert_equal('  1 the first', getline('.'))
543  $
544  call feedkeys("?the\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
545  call assert_equal('  2 the second', getline('.'))
546  $
547  call feedkeys("?the\<c-t>\<cr>", 'tx')
548  call assert_equal('  1 the first', getline('.'))
549  $
550  call feedkeys("?the\<c-t>\<c-t>\<cr>", 'tx')
551  call assert_equal('  3 the third', getline('.'))
552  $
553  call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx')
554  call assert_equal('  2 the second', getline('.'))
555  " clean up
556  set noincsearch
557  call test_override("char_avail", 0)
558  bw!
559endfunc
560
561func Test_search_cmdline5()
562  if !exists('+incsearch')
563    return
564  endif
565  " Do not call test_override("char_avail", 1) so that <C-g> and <C-t> work
566  " regardless char_avail.
567  new
568  call setline(1, ['  1 the first', '  2 the second', '  3 the third', ''])
569  set incsearch
570  1
571  call feedkeys("/the\<c-g>\<c-g>\<cr>", 'tx')
572  call assert_equal('  3 the third', getline('.'))
573  $
574  call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx')
575  call assert_equal('  1 the first', getline('.'))
576  " clean up
577  set noincsearch
578  bw!
579endfunc
580
581func Test_search_cmdline6()
582  " Test that consecutive matches
583  " are caught by <c-g>/<c-t>
584  if !exists('+incsearch')
585    return
586  endif
587  " need to disable char_avail,
588  " so that expansion of commandline works
589  call test_override("char_avail", 1)
590  new
591  call setline(1, [' bbvimb', ''])
592  set incsearch
593  " first match
594  norm! gg0
595  call feedkeys("/b\<cr>", 'tx')
596  call assert_equal([0,1,2,0], getpos('.'))
597  " second match
598  norm! gg0
599  call feedkeys("/b\<c-g>\<cr>", 'tx')
600  call assert_equal([0,1,3,0], getpos('.'))
601  " third match
602  norm! gg0
603  call feedkeys("/b\<c-g>\<c-g>\<cr>", 'tx')
604  call assert_equal([0,1,7,0], getpos('.'))
605  " first match again
606  norm! gg0
607  call feedkeys("/b\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
608  call assert_equal([0,1,2,0], getpos('.'))
609  set nowrapscan
610  " last match
611  norm! gg0
612  call feedkeys("/b\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
613  call assert_equal([0,1,7,0], getpos('.'))
614  " clean up
615  set wrapscan&vim
616  set noincsearch
617  call test_override("char_avail", 0)
618  bw!
619endfunc
620
621func Test_search_cmdline7()
622  " Test that an pressing <c-g> in an empty command line
623  " does not move the cursor
624  if !exists('+incsearch')
625    return
626  endif
627  " need to disable char_avail,
628  " so that expansion of commandline works
629  call test_override("char_avail", 1)
630  new
631  let @/ = 'b'
632  call setline(1, [' bbvimb', ''])
633  set incsearch
634  " first match
635  norm! gg0
636  " moves to next match of previous search pattern, just like /<cr>
637  call feedkeys("/\<c-g>\<cr>", 'tx')
638  call assert_equal([0,1,2,0], getpos('.'))
639  " moves to next match of previous search pattern, just like /<cr>
640  call feedkeys("/\<cr>", 'tx')
641  call assert_equal([0,1,3,0], getpos('.'))
642  " moves to next match of previous search pattern, just like /<cr>
643  call feedkeys("/\<c-t>\<cr>", 'tx')
644  call assert_equal([0,1,7,0], getpos('.'))
645
646  " using an offset uses the last search pattern
647  call cursor(1, 1)
648  call setline(1, ['1 bbvimb', ' 2 bbvimb'])
649  let @/ = 'b'
650  call feedkeys("//e\<c-g>\<cr>", 'tx')
651  call assert_equal('1 bbvimb', getline('.'))
652  call assert_equal(4, col('.'))
653
654  set noincsearch
655  call test_override("char_avail", 0)
656  bw!
657endfunc
658
659func Test_search_cmdline8()
660  " Highlighting is cleared in all windows
661  " since hls applies to all windows
662  CheckOption incsearch
663  CheckFeature terminal
664  CheckNotGui
665  if has("win32")
666    throw "Skipped: Bug with sending <ESC> to terminal window not fixed yet"
667  endif
668
669  let h = winheight(0)
670  if h < 3
671    return
672  endif
673  " Prepare buffer text
674  let lines = ['abb vim vim vi', 'vimvivim']
675  call writefile(lines, 'Xsearch.txt')
676  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', 'Xsearch.txt'], {'term_rows': 3})
677
678  call WaitForAssert({-> assert_equal(lines, [term_getline(buf, 1), term_getline(buf, 2)])})
679
680  call term_sendkeys(buf, ":set incsearch hlsearch\<cr>")
681  call term_sendkeys(buf, ":14vsp\<cr>")
682  call term_sendkeys(buf, "/vim\<cr>")
683  call term_sendkeys(buf, "/b\<esc>")
684  call term_sendkeys(buf, "gg0")
685  call term_wait(buf, 500)
686  let screen_line = term_scrape(buf, 1)
687  let [a0,a1,a2,a3] = [screen_line[3].attr, screen_line[4].attr,
688        \ screen_line[18].attr, screen_line[19].attr]
689  call assert_notequal(a0, a1)
690  call assert_notequal(a0, a3)
691  call assert_notequal(a1, a2)
692  call assert_equal(a0, a2)
693  call assert_equal(a1, a3)
694  " clean up
695  call delete('Xsearch.txt')
696
697  bwipe!
698endfunc
699
700" Tests for regexp with various magic settings
701func Test_search_regexp()
702  enew!
703
704  put ='1 a aa abb abbccc'
705  exe 'normal! /a*b\{2}c\+/e' . "\<CR>"
706  call assert_equal([0, 2, 17, 0], getpos('.'))
707
708  put ='2 d dd dee deefff'
709  exe 'normal! /\Md\*e\{2}f\+/e' . "\<CR>"
710  call assert_equal([0, 3, 17, 0], getpos('.'))
711
712  set nomagic
713  put ='3 g gg ghh ghhiii'
714  exe 'normal! /g\*h\{2}i\+/e' . "\<CR>"
715  call assert_equal([0, 4, 17, 0], getpos('.'))
716
717  put ='4 j jj jkk jkklll'
718  exe 'normal! /\mj*k\{2}l\+/e' . "\<CR>"
719  call assert_equal([0, 5, 17, 0], getpos('.'))
720
721  put ='5 m mm mnn mnnooo'
722  exe 'normal! /\vm*n{2}o+/e' . "\<CR>"
723  call assert_equal([0, 6, 17, 0], getpos('.'))
724
725  put ='6 x ^aa$ x'
726  exe 'normal! /\V^aa$' . "\<CR>"
727  call assert_equal([0, 7, 5, 0], getpos('.'))
728
729  set magic
730  put ='7 (a)(b) abbaa'
731  exe 'normal! /\v(a)(b)\2\1\1/e' . "\<CR>"
732  call assert_equal([0, 8, 14, 0], getpos('.'))
733
734  put ='8 axx [ab]xx'
735  exe 'normal! /\V[ab]\(\[xy]\)\1' . "\<CR>"
736  call assert_equal([0, 9, 7, 0], getpos('.'))
737
738  set undolevels=100
739  put ='9 foobar'
740  put =''
741  exe "normal! a\<C-G>u\<Esc>"
742  normal G
743  exe 'normal! dv?bar?' . "\<CR>"
744  call assert_equal('9 foo', getline('.'))
745  call assert_equal([0, 10, 5, 0], getpos('.'))
746  call assert_equal(10, line('$'))
747  normal u
748  call assert_equal('9 foobar', getline('.'))
749  call assert_equal([0, 10, 6, 0], getpos('.'))
750  call assert_equal(11, line('$'))
751
752  set undolevels&
753  enew!
754endfunc
755
756func Test_search_cmdline_incsearch_highlight()
757  if !exists('+incsearch')
758    return
759  endif
760  set incsearch hlsearch
761  " need to disable char_avail,
762  " so that expansion of commandline works
763  call test_override("char_avail", 1)
764  new
765  call setline(1, ['aaa  1 the first', '  2 the second', '  3 the third'])
766
767  1
768  call feedkeys("/second\<cr>", 'tx')
769  call assert_equal('second', @/)
770  call assert_equal('  2 the second', getline('.'))
771
772  " Canceling search won't change @/
773  1
774  let @/ = 'last pattern'
775  call feedkeys("/third\<C-c>", 'tx')
776  call assert_equal('last pattern', @/)
777  call feedkeys("/third\<Esc>", 'tx')
778  call assert_equal('last pattern', @/)
779  call feedkeys("/3\<bs>\<bs>", 'tx')
780  call assert_equal('last pattern', @/)
781  call feedkeys("/third\<c-g>\<c-t>\<Esc>", 'tx')
782  call assert_equal('last pattern', @/)
783
784  " clean up
785  set noincsearch nohlsearch
786  bw!
787endfunc
788
789func Test_search_cmdline_incsearch_highlight_attr()
790  CheckOption incsearch
791  CheckFeature terminal
792  CheckNotGui
793
794  let h = winheight(0)
795  if h < 3
796    return
797  endif
798
799  " Prepare buffer text
800  let lines = ['abb vim vim vi', 'vimvivim']
801  call writefile(lines, 'Xsearch.txt')
802  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', 'Xsearch.txt'], {'term_rows': 3})
803
804  call WaitForAssert({-> assert_equal(lines, [term_getline(buf, 1), term_getline(buf, 2)])})
805  " wait for vim to complete initialization
806  call term_wait(buf)
807
808  " Get attr of normal(a0), incsearch(a1), hlsearch(a2) highlight
809  call term_sendkeys(buf, ":set incsearch hlsearch\<cr>")
810  call term_sendkeys(buf, '/b')
811  call term_wait(buf, 200)
812  let screen_line1 = term_scrape(buf, 1)
813  call assert_true(len(screen_line1) > 2)
814  " a0: attr_normal
815  let a0 = screen_line1[0].attr
816  " a1: attr_incsearch
817  let a1 = screen_line1[1].attr
818  " a2: attr_hlsearch
819  let a2 = screen_line1[2].attr
820  call assert_notequal(a0, a1)
821  call assert_notequal(a0, a2)
822  call assert_notequal(a1, a2)
823  call term_sendkeys(buf, "\<cr>gg0")
824
825  " Test incremental highlight search
826  call term_sendkeys(buf, "/vim")
827  call term_wait(buf, 200)
828  " Buffer:
829  " abb vim vim vi
830  " vimvivim
831  " Search: /vim
832  let attr_line1 = [a0,a0,a0,a0,a1,a1,a1,a0,a2,a2,a2,a0,a0,a0]
833  let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2]
834  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
835  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
836
837  " Test <C-g>
838  call term_sendkeys(buf, "\<C-g>\<C-g>")
839  call term_wait(buf, 200)
840  let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a2,a2,a2,a0,a0,a0]
841  let attr_line2 = [a1,a1,a1,a0,a0,a2,a2,a2]
842  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
843  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
844
845  " Test <C-t>
846  call term_sendkeys(buf, "\<C-t>")
847  call term_wait(buf, 200)
848  let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a1,a1,a1,a0,a0,a0]
849  let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2]
850  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
851  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
852
853  " Type Enter and a1(incsearch highlight) should become a2(hlsearch highlight)
854  call term_sendkeys(buf, "\<cr>")
855  call term_wait(buf, 200)
856  let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a2,a2,a2,a0,a0,a0]
857  let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2]
858  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
859  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
860
861  " Test nohlsearch. a2(hlsearch highlight) should become a0(normal highlight)
862  call term_sendkeys(buf, ":1\<cr>")
863  call term_sendkeys(buf, ":set nohlsearch\<cr>")
864  call term_sendkeys(buf, "/vim")
865  call term_wait(buf, 200)
866  let attr_line1 = [a0,a0,a0,a0,a1,a1,a1,a0,a0,a0,a0,a0,a0,a0]
867  let attr_line2 = [a0,a0,a0,a0,a0,a0,a0,a0]
868  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
869  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
870  call delete('Xsearch.txt')
871
872  call delete('Xsearch.txt')
873  bwipe!
874endfunc
875
876func Test_incsearch_cmdline_modifier()
877  if !exists('+incsearch')
878    return
879  endif
880  call test_override("char_avail", 1)
881  new
882  call setline(1, ['foo'])
883  set incsearch
884  " Test that error E14 does not occur in parsing command modifier.
885  call feedkeys("V:tab", 'tx')
886
887  call Incsearch_cleanup()
888endfunc
889
890func Test_incsearch_scrolling()
891  if !CanRunVimInTerminal()
892    throw 'Skipped: cannot make screendumps'
893  endif
894  call assert_equal(0, &scrolloff)
895  call writefile([
896	\ 'let dots = repeat(".", 120)',
897	\ 'set incsearch cmdheight=2 scrolloff=0',
898	\ 'call setline(1, [dots, dots, dots, "", "target", dots, dots])',
899	\ 'normal gg',
900	\ 'redraw',
901	\ ], 'Xscript')
902  let buf = RunVimInTerminal('-S Xscript', {'rows': 9, 'cols': 70})
903  " Need to send one key at a time to force a redraw
904  call term_sendkeys(buf, '/')
905  sleep 100m
906  call term_sendkeys(buf, 't')
907  sleep 100m
908  call term_sendkeys(buf, 'a')
909  sleep 100m
910  call term_sendkeys(buf, 'r')
911  sleep 100m
912  call term_sendkeys(buf, 'g')
913  call VerifyScreenDump(buf, 'Test_incsearch_scrolling_01', {})
914
915  call term_sendkeys(buf, "\<Esc>")
916  call StopVimInTerminal(buf)
917  call delete('Xscript')
918endfunc
919
920func Test_incsearch_search_dump()
921  if !exists('+incsearch')
922    return
923  endif
924  if !CanRunVimInTerminal()
925    throw 'Skipped: cannot make screendumps'
926  endif
927  call writefile([
928	\ 'set incsearch hlsearch scrolloff=0',
929	\ 'for n in range(1, 8)',
930	\ '  call setline(n, "foo " . n)',
931	\ 'endfor',
932	\ '3',
933	\ ], 'Xis_search_script')
934  let buf = RunVimInTerminal('-S Xis_search_script', {'rows': 9, 'cols': 70})
935  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
936  " the 'ambiwidth' check.
937  sleep 100m
938
939  " Need to send one key at a time to force a redraw.
940  call term_sendkeys(buf, '/fo')
941  call VerifyScreenDump(buf, 'Test_incsearch_search_01', {})
942  call term_sendkeys(buf, "\<Esc>")
943  sleep 100m
944
945  call term_sendkeys(buf, '/\v')
946  call VerifyScreenDump(buf, 'Test_incsearch_search_02', {})
947  call term_sendkeys(buf, "\<Esc>")
948
949  call StopVimInTerminal(buf)
950  call delete('Xis_search_script')
951endfunc
952
953func Test_incsearch_substitute()
954  if !exists('+incsearch')
955    return
956  endif
957  call test_override("char_avail", 1)
958  new
959  set incsearch
960  for n in range(1, 10)
961    call setline(n, 'foo ' . n)
962  endfor
963  4
964  call feedkeys(":.,.+2s/foo\<BS>o\<BS>o/xxx\<cr>", 'tx')
965  call assert_equal('foo 3', getline(3))
966  call assert_equal('xxx 4', getline(4))
967  call assert_equal('xxx 5', getline(5))
968  call assert_equal('xxx 6', getline(6))
969  call assert_equal('foo 7', getline(7))
970
971  call Incsearch_cleanup()
972endfunc
973
974" Similar to Test_incsearch_substitute() but with a screendump halfway.
975func Test_incsearch_substitute_dump()
976  if !exists('+incsearch')
977    return
978  endif
979  if !CanRunVimInTerminal()
980    throw 'Skipped: cannot make screendumps'
981  endif
982  call writefile([
983	\ 'set incsearch hlsearch scrolloff=0',
984	\ 'for n in range(1, 10)',
985	\ '  call setline(n, "foo " . n)',
986	\ 'endfor',
987	\ 'call setline(11, "bar 11")',
988	\ '3',
989	\ ], 'Xis_subst_script')
990  let buf = RunVimInTerminal('-S Xis_subst_script', {'rows': 9, 'cols': 70})
991  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
992  " the 'ambiwidth' check.
993  sleep 100m
994
995  " Need to send one key at a time to force a redraw.
996  " Select three lines at the cursor with typed pattern.
997  call term_sendkeys(buf, ':.,.+2s/')
998  sleep 100m
999  call term_sendkeys(buf, 'f')
1000  sleep 100m
1001  call term_sendkeys(buf, 'o')
1002  sleep 100m
1003  call term_sendkeys(buf, 'o')
1004  call VerifyScreenDump(buf, 'Test_incsearch_substitute_01', {})
1005  call term_sendkeys(buf, "\<Esc>")
1006
1007  " Select three lines at the cursor using previous pattern.
1008  call term_sendkeys(buf, "/foo\<CR>")
1009  sleep 100m
1010  call term_sendkeys(buf, ':.,.+2s//')
1011  call VerifyScreenDump(buf, 'Test_incsearch_substitute_02', {})
1012
1013  " Deleting last slash should remove the match.
1014  call term_sendkeys(buf, "\<BS>")
1015  call VerifyScreenDump(buf, 'Test_incsearch_substitute_03', {})
1016  call term_sendkeys(buf, "\<Esc>")
1017
1018  " Reverse range is accepted
1019  call term_sendkeys(buf, ':5,2s/foo')
1020  call VerifyScreenDump(buf, 'Test_incsearch_substitute_04', {})
1021  call term_sendkeys(buf, "\<Esc>")
1022
1023  " White space after the command is skipped
1024  call term_sendkeys(buf, ':2,3sub  /fo')
1025  call VerifyScreenDump(buf, 'Test_incsearch_substitute_05', {})
1026  call term_sendkeys(buf, "\<Esc>")
1027
1028  " Command modifiers are skipped
1029  call term_sendkeys(buf, ':above below browse botr confirm keepmar keepalt keeppat keepjum filter xxx hide lockm leftabove noau noswap rightbel sandbox silent silent! $tab top unsil vert verbose 4,5s/fo.')
1030  call VerifyScreenDump(buf, 'Test_incsearch_substitute_06', {})
1031  call term_sendkeys(buf, "\<Esc>")
1032
1033  " Cursorline highlighting at match
1034  call term_sendkeys(buf, ":set cursorline\<CR>")
1035  call term_sendkeys(buf, 'G9G')
1036  call term_sendkeys(buf, ':9,11s/bar')
1037  call VerifyScreenDump(buf, 'Test_incsearch_substitute_07', {})
1038  call term_sendkeys(buf, "\<Esc>")
1039
1040  " Cursorline highlighting at cursor when no match
1041  call term_sendkeys(buf, ':9,10s/bar')
1042  call VerifyScreenDump(buf, 'Test_incsearch_substitute_08', {})
1043  call term_sendkeys(buf, "\<Esc>")
1044
1045  " Only \v handled as empty pattern, does not move cursor
1046  call term_sendkeys(buf, '3G4G')
1047  call term_sendkeys(buf, ":nohlsearch\<CR>")
1048  call term_sendkeys(buf, ':6,7s/\v')
1049  call VerifyScreenDump(buf, 'Test_incsearch_substitute_09', {})
1050  call term_sendkeys(buf, "\<Esc>")
1051
1052  call term_sendkeys(buf, ":set nocursorline\<CR>")
1053
1054  " All matches are highlighted for 'hlsearch' after the incsearch canceled
1055  call term_sendkeys(buf, "1G*")
1056  call term_sendkeys(buf, ":2,5s/foo")
1057  sleep 100m
1058  call term_sendkeys(buf, "\<Esc>")
1059  call VerifyScreenDump(buf, 'Test_incsearch_substitute_10', {})
1060
1061  call term_sendkeys(buf, ":split\<CR>")
1062  call term_sendkeys(buf, ":let @/ = 'xyz'\<CR>")
1063  call term_sendkeys(buf, ":%s/.")
1064  call VerifyScreenDump(buf, 'Test_incsearch_substitute_11', {})
1065  call term_sendkeys(buf, "\<BS>")
1066  call VerifyScreenDump(buf, 'Test_incsearch_substitute_12', {})
1067  call term_sendkeys(buf, "\<Esc>")
1068  call VerifyScreenDump(buf, 'Test_incsearch_substitute_13', {})
1069  call term_sendkeys(buf, ":%bwipe!\<CR>")
1070  call term_sendkeys(buf, ":only!\<CR>")
1071
1072  "  get :'<,'>s command in history
1073  call term_sendkeys(buf, ":set cmdheight=2\<CR>")
1074  call term_sendkeys(buf, "aasdfasdf\<Esc>")
1075  call term_sendkeys(buf, "V:s/a/b/g\<CR>")
1076  " Using '<,'> does not give E20
1077  call term_sendkeys(buf, ":new\<CR>")
1078  call term_sendkeys(buf, "aasdfasdf\<Esc>")
1079  call term_sendkeys(buf, ":\<Up>\<Up>")
1080  call VerifyScreenDump(buf, 'Test_incsearch_substitute_14', {})
1081  call term_sendkeys(buf, "<Esc>")
1082
1083  call StopVimInTerminal(buf)
1084  call delete('Xis_subst_script')
1085endfunc
1086
1087func Test_incsearch_highlighting()
1088  if !exists('+incsearch')
1089    return
1090  endif
1091  if !CanRunVimInTerminal()
1092    throw 'Skipped: cannot make screendumps'
1093  endif
1094
1095  call writefile([
1096	\ 'set incsearch hlsearch',
1097	\ 'call setline(1, "hello/there")',
1098	\ ], 'Xis_subst_hl_script')
1099  let buf = RunVimInTerminal('-S Xis_subst_hl_script', {'rows': 4, 'cols': 20})
1100  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1101  " the 'ambiwidth' check.
1102  sleep 300m
1103
1104  " Using a different search delimiter should still highlight matches
1105  " that contain a '/'.
1106  call term_sendkeys(buf, ":%s;ello/the")
1107  call VerifyScreenDump(buf, 'Test_incsearch_substitute_15', {})
1108  call term_sendkeys(buf, "<Esc>")
1109endfunc
1110
1111func Test_incsearch_with_change()
1112  if !has('timers') || !exists('+incsearch') || !CanRunVimInTerminal()
1113    throw 'Skipped: cannot make screendumps and/or timers feature and/or incsearch option missing'
1114  endif
1115
1116  call writefile([
1117	\ 'set incsearch hlsearch scrolloff=0',
1118	\ 'call setline(1, ["one", "two ------ X", "three"])',
1119	\ 'call timer_start(200, { _ -> setline(2, "x")})',
1120	\ ], 'Xis_change_script')
1121  let buf = RunVimInTerminal('-S Xis_change_script', {'rows': 9, 'cols': 70})
1122  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1123  " the 'ambiwidth' check.
1124  sleep 300m
1125
1126  " Highlight X, it will be deleted by the timer callback.
1127  call term_sendkeys(buf, ':%s/X')
1128  call VerifyScreenDump(buf, 'Test_incsearch_change_01', {})
1129  call term_sendkeys(buf, "\<Esc>")
1130
1131  call StopVimInTerminal(buf)
1132  call delete('Xis_change_script')
1133endfunc
1134
1135" Similar to Test_incsearch_substitute_dump() for :sort
1136func Test_incsearch_sort_dump()
1137  if !exists('+incsearch')
1138    return
1139  endif
1140  if !CanRunVimInTerminal()
1141    throw 'Skipped: cannot make screendumps'
1142  endif
1143  call writefile([
1144	\ 'set incsearch hlsearch scrolloff=0',
1145	\ 'call setline(1, ["another one 2", "that one 3", "the one 1"])',
1146	\ ], 'Xis_sort_script')
1147  let buf = RunVimInTerminal('-S Xis_sort_script', {'rows': 9, 'cols': 70})
1148  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1149  " the 'ambiwidth' check.
1150  sleep 100m
1151
1152  " Need to send one key at a time to force a redraw.
1153  call term_sendkeys(buf, ':sort ni u /on')
1154  call VerifyScreenDump(buf, 'Test_incsearch_sort_01', {})
1155  call term_sendkeys(buf, "\<Esc>")
1156
1157  call StopVimInTerminal(buf)
1158  call delete('Xis_sort_script')
1159endfunc
1160
1161" Similar to Test_incsearch_substitute_dump() for :vimgrep famiry
1162func Test_incsearch_vimgrep_dump()
1163  if !exists('+incsearch')
1164    return
1165  endif
1166  if !CanRunVimInTerminal()
1167    throw 'Skipped: cannot make screendumps'
1168  endif
1169  call writefile([
1170	\ 'set incsearch hlsearch scrolloff=0',
1171	\ 'call setline(1, ["another one 2", "that one 3", "the one 1"])',
1172	\ ], 'Xis_vimgrep_script')
1173  let buf = RunVimInTerminal('-S Xis_vimgrep_script', {'rows': 9, 'cols': 70})
1174  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1175  " the 'ambiwidth' check.
1176  sleep 100m
1177
1178  " Need to send one key at a time to force a redraw.
1179  call term_sendkeys(buf, ':vimgrep on')
1180  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_01', {})
1181  call term_sendkeys(buf, "\<Esc>")
1182
1183  call term_sendkeys(buf, ':vimg /on/ *.txt')
1184  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_02', {})
1185  call term_sendkeys(buf, "\<Esc>")
1186
1187  call term_sendkeys(buf, ':vimgrepadd "\<on')
1188  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_03', {})
1189  call term_sendkeys(buf, "\<Esc>")
1190
1191  call term_sendkeys(buf, ':lv "tha')
1192  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_04', {})
1193  call term_sendkeys(buf, "\<Esc>")
1194
1195  call term_sendkeys(buf, ':lvimgrepa "the" **/*.txt')
1196  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_05', {})
1197  call term_sendkeys(buf, "\<Esc>")
1198
1199  call StopVimInTerminal(buf)
1200  call delete('Xis_vimgrep_script')
1201endfunc
1202
1203func Test_keep_last_search_pattern()
1204  if !exists('+incsearch')
1205    return
1206  endif
1207  new
1208  call setline(1, ['foo', 'foo', 'foo'])
1209  set incsearch
1210  call test_override("char_avail", 1)
1211  let @/ = 'bar'
1212  call feedkeys(":/foo/s//\<Esc>", 'ntx')
1213  call assert_equal('bar', @/)
1214
1215  " no error message if pattern not found
1216  call feedkeys(":/xyz/s//\<Esc>", 'ntx')
1217  call assert_equal('bar', @/)
1218
1219  bwipe!
1220  call test_override("ALL", 0)
1221  set noincsearch
1222endfunc
1223
1224func Test_word_under_cursor_after_match()
1225  if !exists('+incsearch')
1226    return
1227  endif
1228  new
1229  call setline(1, 'foo bar')
1230  set incsearch
1231  call test_override("char_avail", 1)
1232  try
1233    call feedkeys("/foo\<C-R>\<C-W>\<CR>", 'ntx')
1234  catch /E486:/
1235  endtry
1236  call assert_equal('foobar', @/)
1237
1238  bwipe!
1239  call test_override("ALL", 0)
1240  set noincsearch
1241endfunc
1242
1243func Test_subst_word_under_cursor()
1244  if !exists('+incsearch')
1245    return
1246  endif
1247  new
1248  call setline(1, ['int SomeLongName;', 'for (xxx = 1; xxx < len; ++xxx)'])
1249  set incsearch
1250  call test_override("char_avail", 1)
1251  call feedkeys("/LongName\<CR>", 'ntx')
1252  call feedkeys(":%s/xxx/\<C-R>\<C-W>/g\<CR>", 'ntx')
1253  call assert_equal('for (SomeLongName = 1; SomeLongName < len; ++SomeLongName)', getline(2))
1254
1255  bwipe!
1256  call test_override("ALL", 0)
1257  set noincsearch
1258endfunc
1259
1260func Test_search_undefined_behaviour()
1261  if !has("terminal")
1262    return
1263  endif
1264  let h = winheight(0)
1265  if h < 3
1266    return
1267  endif
1268  " did cause an undefined left shift
1269  let g:buf = term_start([GetVimProg(), '--clean', '-e', '-s', '-c', 'call search(getline("."))', 'samples/test000'], {'term_rows': 3})
1270  call assert_equal([''], getline(1, '$'))
1271  call term_sendkeys(g:buf, ":qa!\<cr>")
1272  bwipe!
1273endfunc
1274
1275func Test_search_undefined_behaviour2()
1276  call search("\%UC0000000")
1277endfunc
1278
1279" Test for search('multi-byte char', 'bce')
1280func Test_search_multibyte()
1281  let save_enc = &encoding
1282  set encoding=utf8
1283  enew!
1284  call append('$', 'A')
1285  call cursor(2, 1)
1286  call assert_equal(2, search('A', 'bce', line('.')))
1287  enew!
1288  let &encoding = save_enc
1289endfunc
1290
1291" This was causing E874.  Also causes an invalid read?
1292func Test_look_behind()
1293  new
1294  call setline(1, '0\|\&\n\@<=')
1295  call search(getline("."))
1296  bwipe!
1297endfunc
1298
1299func Test_search_sentence()
1300  new
1301  " this used to cause a crash
1302  call assert_fails("/\\%')", 'E486')
1303  call assert_fails("/", 'E486')
1304  /\%'(
1305  /
1306endfunc
1307
1308" Test that there is no crash when there is a last search pattern but no last
1309" substitute pattern.
1310func Test_no_last_substitute_pat()
1311  " Use viminfo to set the last search pattern to a string and make the last
1312  " substitute pattern the most recent used and make it empty (NULL).
1313  call writefile(['~MSle0/bar', '~MSle0~&'], 'Xviminfo')
1314  rviminfo! Xviminfo
1315  call assert_fails('normal n', 'E35:')
1316
1317  call delete('Xviminfo')
1318endfunc
1319
1320func Test_search_Ctrl_L_combining()
1321  " Make sure, that Ctrl-L works correctly with combining characters.
1322  " It uses an artificial example of an 'a' with 4 combining chars:
1323    " 'a' U+0061 Dec:97 LATIN SMALL LETTER A &#x61; /\%u61\Z "\u0061"
1324    " ' ̀' U+0300 Dec:768 COMBINING GRAVE ACCENT &#x300; /\%u300\Z "\u0300"
1325    " ' ́' U+0301 Dec:769 COMBINING ACUTE ACCENT &#x301; /\%u301\Z "\u0301"
1326    " ' ̇' U+0307 Dec:775 COMBINING DOT ABOVE &#x307; /\%u307\Z "\u0307"
1327    " ' ̣' U+0323 Dec:803 COMBINING DOT BELOW &#x323; /\%u323 "\u0323"
1328  " Those should also appear on the commandline
1329  if !exists('+incsearch')
1330    return
1331  endif
1332  call Cmdline3_prep()
1333  1
1334  let bufcontent = ['', 'Miạ̀́̇m']
1335  call append('$', bufcontent)
1336  call feedkeys("/Mi\<c-l>\<c-l>\<cr>", 'tx')
1337  call assert_equal(5, line('.'))
1338  call assert_equal(bufcontent[1], @/)
1339  call Incsearch_cleanup()
1340endfunc
1341
1342func Test_large_hex_chars1()
1343  " This used to cause a crash, the character becomes an NFA state.
1344  try
1345    /\%Ufffffc23
1346  catch
1347    call assert_match('E678:', v:exception)
1348  endtry
1349  try
1350    set re=1
1351    /\%Ufffffc23
1352  catch
1353    call assert_match('E678:', v:exception)
1354  endtry
1355  set re&
1356endfunc
1357
1358func Test_large_hex_chars2()
1359  " This used to cause a crash, the character becomes an NFA state.
1360  try
1361    /[\Ufffffc1f]
1362  catch
1363    call assert_match('E486:', v:exception)
1364  endtry
1365  try
1366    set re=1
1367    /[\Ufffffc1f]
1368  catch
1369    call assert_match('E486:', v:exception)
1370  endtry
1371  set re&
1372endfunc
1373
1374func Test_one_error_msg()
1375  " This  was also giving an internal error
1376  call assert_fails('call search(" \\((\\v[[=P=]]){185}+             ")', 'E871:')
1377endfunc
1378
1379func Test_incsearch_add_char_under_cursor()
1380  if !exists('+incsearch')
1381    return
1382  endif
1383  set incsearch
1384  new
1385  call setline(1, ['find match', 'anything'])
1386  1
1387  call test_override('char_avail', 1)
1388  call feedkeys("fc/m\<C-L>\<C-L>\<C-L>\<C-L>\<C-L>\<CR>", 'tx')
1389  call assert_equal('match', @/)
1390  call test_override('char_avail', 0)
1391
1392  set incsearch&
1393  bwipe!
1394endfunc
1395
1396" Test for the search() function with match at the cursor position
1397func Test_search_match_at_curpos()
1398  new
1399  call append(0, ['foobar', '', 'one two', ''])
1400
1401  normal gg
1402
1403  eval 'foobar'->search('c')
1404  call assert_equal([1, 1], [line('.'), col('.')])
1405
1406  normal j
1407  call search('^$', 'c')
1408  call assert_equal([2, 1], [line('.'), col('.')])
1409
1410  call search('^$', 'bc')
1411  call assert_equal([2, 1], [line('.'), col('.')])
1412
1413  exe "normal /two\<CR>"
1414  call search('.', 'c')
1415  call assert_equal([3, 5], [line('.'), col('.')])
1416
1417  close!
1418endfunc
1419
1420func Test_search_display_pattern()
1421  new
1422  call setline(1, ['foo', 'bar', 'foobar'])
1423
1424  call cursor(1, 1)
1425  let @/ = 'foo'
1426  let pat = @/->escape('()*?'. '\s\+')
1427  let g:a = execute(':unsilent :norm! n')
1428  call assert_match(pat, g:a)
1429
1430  " right-left
1431  if exists("+rightleft")
1432    set rl
1433    call cursor(1, 1)
1434    let @/ = 'foo'
1435    let pat = 'oof/\s\+'
1436    let g:a = execute(':unsilent :norm! n')
1437    call assert_match(pat, g:a)
1438    set norl
1439  endif
1440endfunc
1441
1442func Test_searchdecl()
1443  let lines =<< trim END
1444     int global;
1445
1446     func()
1447     {
1448       int global;
1449       if (cond) {
1450	 int local;
1451       }
1452       int local;
1453       // comment
1454     }
1455  END
1456  new
1457  call setline(1, lines)
1458  10
1459  call assert_equal(0, searchdecl('local', 0, 0))
1460  call assert_equal(7, getcurpos()[1])
1461
1462  10
1463  call assert_equal(0, 'local'->searchdecl(0, 1))
1464  call assert_equal(9, getcurpos()[1])
1465
1466  10
1467  call assert_equal(0, searchdecl('global'))
1468  call assert_equal(5, getcurpos()[1])
1469
1470  10
1471  call assert_equal(0, searchdecl('global', 1))
1472  call assert_equal(1, getcurpos()[1])
1473
1474  bwipe!
1475endfunc
1476
1477func Test_search_special()
1478  " this was causing illegal memory access and an endless loop
1479  set t_PE=
1480  exe "norm /\x80PS"
1481endfunc
1482
1483" Test for command failures when the last search pattern is not set.
1484" Need to run this in a new vim instance where last search pattern is not set.
1485func Test_search_with_no_last_pat()
1486  let lines =<< trim [SCRIPT]
1487    call assert_fails("normal i\<C-R>/\e", 'E35:')
1488    call assert_fails("exe '/'", 'E35:')
1489    call assert_fails("exe '?'", 'E35:')
1490    call assert_fails("/", 'E35:')
1491    call assert_fails("?", 'E35:')
1492    call assert_fails("normal n", 'E35:')
1493    call assert_fails("normal N", 'E35:')
1494    call assert_fails("normal gn", 'E35:')
1495    call assert_fails("normal gN", 'E35:')
1496    call assert_fails("normal cgn", 'E35:')
1497    call assert_fails("normal cgN", 'E35:')
1498    let p = []
1499    let p = @/
1500    call assert_equal('', p)
1501    call assert_fails("normal :\<C-R>/", 'E35:')
1502    call assert_fails("//p", 'E35:')
1503    call assert_fails(";//p", 'E35:')
1504    call assert_fails("??p", 'E35:')
1505    call assert_fails(";??p", 'E35:')
1506    call assert_fails('g//p', 'E476:')
1507    call assert_fails('v//p', 'E476:')
1508    call writefile(v:errors, 'Xresult')
1509    qall!
1510  [SCRIPT]
1511  call writefile(lines, 'Xscript')
1512
1513  if RunVim([], [], '--clean -S Xscript')
1514    call assert_equal([], readfile('Xresult'))
1515  endif
1516  call delete('Xscript')
1517  call delete('Xresult')
1518endfunc
1519
1520" Test for using tilde (~) atom in search. This should use the last used
1521" substitute pattern
1522func Test_search_tilde_pat()
1523  let lines =<< trim [SCRIPT]
1524    set regexpengine=1
1525    call assert_fails('exe "normal /~\<CR>"', 'E33:')
1526    call assert_fails('exe "normal ?~\<CR>"', 'E33:')
1527    set regexpengine=2
1528    call assert_fails('exe "normal /~\<CR>"', 'E383:')
1529    call assert_fails('exe "normal ?~\<CR>"', 'E383:')
1530    set regexpengine&
1531    call writefile(v:errors, 'Xresult')
1532    qall!
1533  [SCRIPT]
1534  call writefile(lines, 'Xscript')
1535  if RunVim([], [], '--clean -S Xscript')
1536    call assert_equal([], readfile('Xresult'))
1537  endif
1538  call delete('Xscript')
1539  call delete('Xresult')
1540endfunc
1541
1542" Test for searching a pattern that is not present with 'nowrapscan'
1543func Test_search_pat_not_found()
1544  new
1545  set nowrapscan
1546  let @/ = '1abcxyz2'
1547  call assert_fails('normal n', 'E385:')
1548  call assert_fails('normal N', 'E384:')
1549  set wrapscan&
1550  close
1551endfunc
1552
1553" Test for v:searchforward variable
1554func Test_searchforward_var()
1555  new
1556  call setline(1, ['foo', '', 'foo'])
1557  call cursor(2, 1)
1558  let @/ = 'foo'
1559  let v:searchforward = 0
1560  normal N
1561  call assert_equal(3, line('.'))
1562  call cursor(2, 1)
1563  let v:searchforward = 1
1564  normal N
1565  call assert_equal(1, line('.'))
1566  close!
1567endfunc
1568
1569" vim: shiftwidth=2 sts=2 expandtab
1570