xref: /vim-8.2.3635/src/testdir/test_search.vim (revision 35a319b7)
1" Test for the search command
2
3source shared.vim
4source screendump.vim
5source check.vim
6
7func Test_search_cmdline()
8  CheckOption incsearch
9
10  " need to disable char_avail,
11  " so that expansion of commandline works
12  call test_override("char_avail", 1)
13  new
14  call setline(1, ['  1', '  2 these', '  3 the', '  4 their', '  5 there', '  6 their', '  7 the', '  8 them', '  9 these', ' 10 foobar'])
15  " Test 1
16  " CTRL-N / CTRL-P skips through the previous search history
17  set noincsearch
18  :1
19  call feedkeys("/foobar\<cr>", 'tx')
20  call feedkeys("/the\<cr>", 'tx')
21  call assert_equal('the', @/)
22  call feedkeys("/thes\<C-P>\<C-P>\<cr>", 'tx')
23  call assert_equal('foobar', @/)
24
25  " Test 2
26  " Ctrl-G goes from one match to the next
27  " until the end of the buffer
28  set incsearch nowrapscan
29  :1
30  " first match
31  call feedkeys("/the\<cr>", 'tx')
32  call assert_equal('  2 these', getline('.'))
33  :1
34  " second match
35  call feedkeys("/the\<C-G>\<cr>", 'tx')
36  call assert_equal('  3 the', getline('.'))
37  call assert_equal([0, 0, 0, 0], getpos('"'))
38  :1
39  " third match
40  call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
41  call assert_equal('  4 their', getline('.'))
42  :1
43  " fourth match
44  call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
45  call assert_equal('  5 there', getline('.'))
46  :1
47  " fifth match
48  call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
49  call assert_equal('  6 their', getline('.'))
50  :1
51  " sixth match
52  call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
53  call assert_equal('  7 the', getline('.'))
54  :1
55  " seventh match
56  call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
57  call assert_equal('  8 them', getline('.'))
58  :1
59  " eighth match
60  call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
61  call assert_equal('  9 these', getline('.'))
62  :1
63  " no further match
64  call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
65  call assert_equal('  9 these', getline('.'))
66  call assert_equal([0, 0, 0, 0], getpos('"'))
67
68  " Test 3
69  " Ctrl-G goes from one match to the next
70  " and continues back at the top
71  set incsearch wrapscan
72  :1
73  " first match
74  call feedkeys("/the\<cr>", 'tx')
75  call assert_equal('  2 these', getline('.'))
76  :1
77  " second match
78  call feedkeys("/the\<C-G>\<cr>", 'tx')
79  call assert_equal('  3 the', getline('.'))
80  :1
81  " third match
82  call feedkeys("/the".repeat("\<C-G>", 2)."\<cr>", 'tx')
83  call assert_equal('  4 their', getline('.'))
84  :1
85  " fourth match
86  call feedkeys("/the".repeat("\<C-G>", 3)."\<cr>", 'tx')
87  call assert_equal('  5 there', getline('.'))
88  :1
89  " fifth match
90  call feedkeys("/the".repeat("\<C-G>", 4)."\<cr>", 'tx')
91  call assert_equal('  6 their', getline('.'))
92  :1
93  " sixth match
94  call feedkeys("/the".repeat("\<C-G>", 5)."\<cr>", 'tx')
95  call assert_equal('  7 the', getline('.'))
96  :1
97  " seventh match
98  call feedkeys("/the".repeat("\<C-G>", 6)."\<cr>", 'tx')
99  call assert_equal('  8 them', getline('.'))
100  :1
101  " eighth match
102  call feedkeys("/the".repeat("\<C-G>", 7)."\<cr>", 'tx')
103  call assert_equal('  9 these', getline('.'))
104  :1
105  " back at first match
106  call feedkeys("/the".repeat("\<C-G>", 8)."\<cr>", 'tx')
107  call assert_equal('  2 these', getline('.'))
108
109  " Test 4
110  " CTRL-T goes to the previous match
111  set incsearch nowrapscan
112  $
113  " first match
114  call feedkeys("?the\<cr>", 'tx')
115  call assert_equal('  9 these', getline('.'))
116  $
117  " first match
118  call feedkeys("?the\<C-G>\<cr>", 'tx')
119  call assert_equal('  9 these', getline('.'))
120  $
121  " second match
122  call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
123  call assert_equal('  8 them', getline('.'))
124  $
125  " last match
126  call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
127  call assert_equal('  2 these', getline('.'))
128  $
129  " last match
130  call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx')
131  call assert_equal('  2 these', getline('.'))
132
133  " Test 5
134  " CTRL-T goes to the previous match
135  set incsearch wrapscan
136  $
137  " first match
138  call feedkeys("?the\<cr>", 'tx')
139  call assert_equal('  9 these', getline('.'))
140  $
141  " first match at the top
142  call feedkeys("?the\<C-G>\<cr>", 'tx')
143  call assert_equal('  2 these', getline('.'))
144  $
145  " second match
146  call feedkeys("?the".repeat("\<C-T>", 1)."\<cr>", 'tx')
147  call assert_equal('  8 them', getline('.'))
148  $
149  " last match
150  call feedkeys("?the".repeat("\<C-T>", 7)."\<cr>", 'tx')
151  call assert_equal('  2 these', getline('.'))
152  $
153  " back at the bottom of the buffer
154  call feedkeys("?the".repeat("\<C-T>", 8)."\<cr>", 'tx')
155  call assert_equal('  9 these', getline('.'))
156
157  " Test 6
158  " CTRL-L adds to the search pattern
159  set incsearch wrapscan
160  1
161  " first match
162  call feedkeys("/the\<c-l>\<cr>", 'tx')
163  call assert_equal('  2 these', getline('.'))
164  1
165  " go to next match of 'thes'
166  call feedkeys("/the\<c-l>\<C-G>\<cr>", 'tx')
167  call assert_equal('  9 these', getline('.'))
168  1
169  " wrap around
170  call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx')
171  call assert_equal('  2 these', getline('.'))
172  1
173  " wrap around
174  set nowrapscan
175  call feedkeys("/the\<c-l>\<C-G>\<C-G>\<cr>", 'tx')
176  call assert_equal('  9 these', getline('.'))
177
178  " Test 7
179  " <bs> remove from match, but stay at current match
180  set incsearch wrapscan
181  1
182  " first match
183  call feedkeys("/thei\<cr>", 'tx')
184  call assert_equal('  4 their', getline('.'))
185  1
186  " delete one char, add another
187  call feedkeys("/thei\<bs>s\<cr>", 'tx')
188  call assert_equal('  2 these', getline('.'))
189  1
190  " delete one char, add another,  go to previous match, add one char
191  call feedkeys("/thei\<bs>s\<bs>\<C-T>\<c-l>\<cr>", 'tx')
192  call assert_equal('  9 these', getline('.'))
193  1
194  " delete all chars, start from the beginning again
195  call feedkeys("/them". repeat("\<bs>",4).'the\>'."\<cr>", 'tx')
196  call assert_equal('  3 the', getline('.'))
197
198  " clean up
199  call test_override("char_avail", 0)
200  bw!
201endfunc
202
203func Test_search_cmdline2()
204  CheckOption incsearch
205
206  " need to disable char_avail,
207  " so that expansion of commandline works
208  call test_override("char_avail", 1)
209  new
210  call setline(1, ['  1', '  2 these', '  3 the theother'])
211  " Test 1
212  " Ctrl-T goes correctly back and forth
213  set incsearch
214  1
215  " first match
216  call feedkeys("/the\<cr>", 'tx')
217  call assert_equal('  2 these', getline('.'))
218  1
219  " go to next match (on next line)
220  call feedkeys("/the\<C-G>\<cr>", 'tx')
221  call assert_equal('  3 the theother', getline('.'))
222  1
223  " go to next match (still on line 3)
224  call feedkeys("/the\<C-G>\<C-G>\<cr>", 'tx')
225  call assert_equal('  3 the theother', getline('.'))
226  1
227  " go to next match (still on line 3)
228  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<cr>", 'tx')
229  call assert_equal('  3 the theother', getline('.'))
230  1
231  " go to previous match (on line 3)
232  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<cr>", 'tx')
233  call assert_equal('  3 the theother', getline('.'))
234  1
235  " go to previous match (on line 3)
236  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<cr>", 'tx')
237  call assert_equal('  3 the theother', getline('.'))
238  1
239  " go to previous match (on line 2)
240  call feedkeys("/the\<C-G>\<C-G>\<C-G>\<C-T>\<C-T>\<C-T>\<cr>", 'tx')
241  call assert_equal('  2 these', getline('.'))
242  1
243  " go to previous match (on line 2)
244  call feedkeys("/the\<C-G>\<C-R>\<C-W>\<cr>", 'tx')
245  call assert_equal('theother', @/)
246
247  " Test 2: keep the view,
248  " after deleting a character from the search cmd
249  call setline(1, ['  1', '  2 these', '  3 the', '  4 their', '  5 there', '  6 their', '  7 the', '  8 them', '  9 these', ' 10 foobar'])
250  resize 5
251  1
252  call feedkeys("/foo\<bs>\<cr>", 'tx')
253  redraw
254  call assert_equal({'lnum': 10, 'leftcol': 0, 'col': 4, 'topfill': 0, 'topline': 6, 'coladd': 0, 'skipcol': 0, 'curswant': 4}, winsaveview())
255
256  " remove all history entries
257  for i in range(11)
258      call histdel('/')
259  endfor
260
261  " Test 3: reset the view,
262  " after deleting all characters from the search cmd
263  norm! 1gg0
264  " unfortunately, neither "/foo\<c-w>\<cr>", nor "/foo\<bs>\<bs>\<bs>\<cr>",
265  " nor "/foo\<c-u>\<cr>" works to delete the commandline.
266  " In that case Vim should return "E35 no previous regular expression",
267  " but it looks like Vim still sees /foo and therefore the test fails.
268  " Therefore, disabling this test
269  "call assert_fails(feedkeys("/foo\<c-w>\<cr>", 'tx'), 'E35:')
270  "call assert_equal({'lnum': 1, 'leftcol': 0, 'col': 0, 'topfill': 0, 'topline': 1, 'coladd': 0, 'skipcol': 0, 'curswant': 0}, winsaveview())
271
272  " clean up
273  set noincsearch
274  call test_override("char_avail", 0)
275  bw!
276endfunc
277
278func Test_use_sub_pat()
279  split
280  let @/ = ''
281  func X()
282    s/^/a/
283    /
284  endfunc
285  call X()
286  bwipe!
287endfunc
288
289func Test_searchpair()
290  new
291  call setline(1, ['other code', 'here [', ' [', ' " cursor here', ' ]]'])
292
293  " should not give an error for using "42"
294  call assert_equal(0, searchpair('a', 'b', 'c', '', 42))
295
296  4
297  call assert_equal(3, searchpair('\[', '', ']', 'bW'))
298  call assert_equal([0, 3, 2, 0], getpos('.'))
299  4
300  call assert_equal(2, searchpair('\[', '', ']', 'bWr'))
301  call assert_equal([0, 2, 6, 0], getpos('.'))
302  4
303  call assert_equal(1, searchpair('\[', '', ']', 'bWm'))
304  call assert_equal([0, 3, 2, 0], getpos('.'))
305  4|norm ^
306  call assert_equal(5, searchpair('\[', '', ']', 'Wn'))
307  call assert_equal([0, 4, 2, 0], getpos('.'))
308  4
309  call assert_equal(2, searchpair('\[', '', ']', 'bW',
310        \                         'getline(".") =~ "^\\s*\["'))
311  call assert_equal([0, 2, 6, 0], getpos('.'))
312  set nomagic
313  4
314  call assert_equal(3, searchpair('\[', '', ']', 'bW'))
315  call assert_equal([0, 3, 2, 0], getpos('.'))
316  set magic
317  4|norm ^
318  call assert_equal(0, searchpair('{', '', '}', 'bW'))
319  call assert_equal([0, 4, 2, 0], getpos('.'))
320
321  %d
322  call setline(1, ['if 1', '  if 2', '  else', '  endif 2', 'endif 1'])
323
324  /\<if 1
325  call assert_equal(5, searchpair('\<if\>', '\<else\>', '\<endif\>', 'W'))
326  call assert_equal([0, 5, 1, 0], getpos('.'))
327  /\<if 2
328  call assert_equal(3, searchpair('\<if\>', '\<else\>', '\<endif\>', 'W'))
329  call assert_equal([0, 3, 3, 0], getpos('.'))
330
331  q!
332endfunc
333
334func Test_searchpairpos()
335  new
336  call setline(1, ['other code', 'here [', ' [', ' " cursor here', ' ]]'])
337
338  4
339  call assert_equal([3, 2], searchpairpos('\[', '', ']', 'bW'))
340  call assert_equal([0, 3, 2, 0], getpos('.'))
341  4
342  call assert_equal([2, 6], searchpairpos('\[', '', ']', 'bWr'))
343  call assert_equal([0, 2, 6, 0], getpos('.'))
344  4|norm ^
345  call assert_equal([5, 2], searchpairpos('\[', '', ']', 'Wn'))
346  call assert_equal([0, 4, 2, 0], getpos('.'))
347  4
348  call assert_equal([2, 6], searchpairpos('\[', '', ']', 'bW',
349        \                                 'getline(".") =~ "^\\s*\["'))
350  call assert_equal([0, 2, 6, 0], getpos('.'))
351  4
352  call assert_equal([2, 6], searchpairpos('\[', '', ']', 'bWr'))
353  call assert_equal([0, 2, 6, 0], getpos('.'))
354  set nomagic
355  4
356  call assert_equal([3, 2], searchpairpos('\[', '', ']', 'bW'))
357  call assert_equal([0, 3, 2, 0], getpos('.'))
358  set magic
359  4|norm ^
360  call assert_equal([0, 0], searchpairpos('{', '', '}', 'bW'))
361  call assert_equal([0, 4, 2, 0], getpos('.'))
362
363  %d
364  call setline(1, ['if 1', '  if 2', '  else', '  endif 2', 'endif 1'])
365  /\<if 1
366  call assert_equal([5, 1], searchpairpos('\<if\>', '\<else\>', '\<endif\>', 'W'))
367  call assert_equal([0, 5, 1, 0], getpos('.'))
368  /\<if 2
369  call assert_equal([3, 3], searchpairpos('\<if\>', '\<else\>', '\<endif\>', 'W'))
370  call assert_equal([0, 3, 3, 0], getpos('.'))
371
372  q!
373endfunc
374
375func Test_searchpair_errors()
376  call assert_fails("call searchpair([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: Using a List as a String')
377  call assert_fails("call searchpair('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: Using a Funcref as a String')
378  call assert_fails("call searchpair('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: Using a Dictionary as a String')
379  call assert_fails("call searchpair('start', 'middle', 'end', 'flags', 'skip', 99, 100)", 'E475: Invalid argument: flags')
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 a List as a String')
388  call assert_fails("call searchpairpos('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: Using a Funcref as a String')
389  call assert_fails("call searchpairpos('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: Using a 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', 'func', -99, 100)", 'E475: Invalid argument: -99')
392  call assert_fails("call searchpairpos('start', 'middle', 'end', 'bW', 'func', 99, -100)", 'E475: Invalid argument: -100')
393  call assert_fails("call searchpairpos('start', 'middle', 'end', 'e')", 'E475: Invalid argument: e')
394  call assert_fails("call searchpairpos('start', 'middle', 'end', 'sn')", 'E475: Invalid argument: sn')
395endfunc
396
397func Test_searchpair_skip()
398    func Zero()
399      return 0
400    endfunc
401    func Partial(x)
402      return a:x
403    endfunc
404    new
405    call setline(1, ['{', 'foo', 'foo', 'foo', '}'])
406    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', ''))
407    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', '0'))
408    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', {-> 0}))
409    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', function('Zero')))
410    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', function('Partial', [0])))
411    bw!
412endfunc
413
414func Test_searchpair_leak()
415  new
416  call setline(1, 'if one else another endif')
417
418  " The error in the skip expression caused memory to leak.
419  call assert_fails("call searchpair('\\<if\\>', '\\<else\\>', '\\<endif\\>', '', '\"foo\" 2')", 'E15:')
420
421  bwipe!
422endfunc
423
424func Test_searchc()
425  " These commands used to cause memory overflow in searchc().
426  new
427  norm ixx
428  exe "norm 0t\u93cf"
429  bw!
430endfunc
431
432func Cmdline3_prep()
433  " need to disable char_avail,
434  " so that expansion of commandline works
435  call test_override("char_avail", 1)
436  new
437  call setline(1, ['  1', '  2 the~e', '  3 the theother'])
438  set incsearch
439endfunc
440
441func Incsearch_cleanup()
442  set noincsearch
443  call test_override("char_avail", 0)
444  bw!
445endfunc
446
447func Test_search_cmdline3()
448  CheckOption incsearch
449
450  call Cmdline3_prep()
451  1
452  " first match
453  call feedkeys("/the\<c-l>\<cr>", 'tx')
454  call assert_equal('  2 the~e', getline('.'))
455
456  call Incsearch_cleanup()
457endfunc
458
459func Test_search_cmdline3s()
460  CheckOption incsearch
461
462  call Cmdline3_prep()
463  1
464  call feedkeys(":%s/the\<c-l>/xxx\<cr>", 'tx')
465  call assert_equal('  2 xxxe', getline('.'))
466  undo
467  call feedkeys(":%subs/the\<c-l>/xxx\<cr>", 'tx')
468  call assert_equal('  2 xxxe', getline('.'))
469  undo
470  call feedkeys(":%substitute/the\<c-l>/xxx\<cr>", 'tx')
471  call assert_equal('  2 xxxe', getline('.'))
472  undo
473  call feedkeys(":%smagic/the.e/xxx\<cr>", 'tx')
474  call assert_equal('  2 xxx', getline('.'))
475  undo
476  call assert_fails(":%snomagic/the.e/xxx\<cr>", 'E486:')
477  "
478  call feedkeys(":%snomagic/the\\.e/xxx\<cr>", 'tx')
479  call assert_equal('  2 xxx', getline('.'))
480
481  call Incsearch_cleanup()
482endfunc
483
484func Test_search_cmdline3g()
485  CheckOption incsearch
486
487  call Cmdline3_prep()
488  1
489  call feedkeys(":g/the\<c-l>/d\<cr>", 'tx')
490  call assert_equal('  3 the theother', getline(2))
491  undo
492  call feedkeys(":global/the\<c-l>/d\<cr>", 'tx')
493  call assert_equal('  3 the theother', getline(2))
494  undo
495  call feedkeys(":g!/the\<c-l>/d\<cr>", 'tx')
496  call assert_equal(1, line('$'))
497  call assert_equal('  2 the~e', getline(1))
498  undo
499  call feedkeys(":global!/the\<c-l>/d\<cr>", 'tx')
500  call assert_equal(1, line('$'))
501  call assert_equal('  2 the~e', getline(1))
502
503  call Incsearch_cleanup()
504endfunc
505
506func Test_search_cmdline3v()
507  CheckOption incsearch
508
509  call Cmdline3_prep()
510  1
511  call feedkeys(":v/the\<c-l>/d\<cr>", 'tx')
512  call assert_equal(1, line('$'))
513  call assert_equal('  2 the~e', getline(1))
514  undo
515  call feedkeys(":vglobal/the\<c-l>/d\<cr>", 'tx')
516  call assert_equal(1, line('$'))
517  call assert_equal('  2 the~e', getline(1))
518
519  call Incsearch_cleanup()
520endfunc
521
522func Test_search_cmdline4()
523  CheckOption incsearch
524
525  " need to disable char_avail,
526  " so that expansion of commandline works
527  call test_override("char_avail", 1)
528  new
529  call setline(1, ['  1 the first', '  2 the second', '  3 the third'])
530  set incsearch
531  $
532  call feedkeys("?the\<c-g>\<cr>", 'tx')
533  call assert_equal('  3 the third', getline('.'))
534  $
535  call feedkeys("?the\<c-g>\<c-g>\<cr>", 'tx')
536  call assert_equal('  1 the first', getline('.'))
537  $
538  call feedkeys("?the\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
539  call assert_equal('  2 the second', getline('.'))
540  $
541  call feedkeys("?the\<c-t>\<cr>", 'tx')
542  call assert_equal('  1 the first', getline('.'))
543  $
544  call feedkeys("?the\<c-t>\<c-t>\<cr>", 'tx')
545  call assert_equal('  3 the third', getline('.'))
546  $
547  call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx')
548  call assert_equal('  2 the second', getline('.'))
549  " clean up
550  set noincsearch
551  call test_override("char_avail", 0)
552  bw!
553endfunc
554
555func Test_search_cmdline5()
556  CheckOption incsearch
557
558  " Do not call test_override("char_avail", 1) so that <C-g> and <C-t> work
559  " regardless char_avail.
560  new
561  call setline(1, ['  1 the first', '  2 the second', '  3 the third', ''])
562  set incsearch
563  1
564  call feedkeys("/the\<c-g>\<c-g>\<cr>", 'tx')
565  call assert_equal('  3 the third', getline('.'))
566  $
567  call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx')
568  call assert_equal('  1 the first', getline('.'))
569  " clean up
570  set noincsearch
571  bw!
572endfunc
573
574func Test_search_cmdline6()
575  " Test that consecutive matches
576  " are caught by <c-g>/<c-t>
577  CheckOption incsearch
578
579  " need to disable char_avail,
580  " so that expansion of commandline works
581  call test_override("char_avail", 1)
582  new
583  call setline(1, [' bbvimb', ''])
584  set incsearch
585  " first match
586  norm! gg0
587  call feedkeys("/b\<cr>", 'tx')
588  call assert_equal([0,1,2,0], getpos('.'))
589  " second match
590  norm! gg0
591  call feedkeys("/b\<c-g>\<cr>", 'tx')
592  call assert_equal([0,1,3,0], getpos('.'))
593  " third match
594  norm! gg0
595  call feedkeys("/b\<c-g>\<c-g>\<cr>", 'tx')
596  call assert_equal([0,1,7,0], getpos('.'))
597  " first match again
598  norm! gg0
599  call feedkeys("/b\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
600  call assert_equal([0,1,2,0], getpos('.'))
601  set nowrapscan
602  " last match
603  norm! gg0
604  call feedkeys("/b\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
605  call assert_equal([0,1,7,0], getpos('.'))
606  " clean up
607  set wrapscan&vim
608  set noincsearch
609  call test_override("char_avail", 0)
610  bw!
611endfunc
612
613func Test_search_cmdline7()
614  " Test that pressing <c-g> in an empty command line
615  " does not move the cursor
616  CheckOption incsearch
617
618  " need to disable char_avail,
619  " so that expansion of commandline works
620  call test_override("char_avail", 1)
621  new
622  let @/ = 'b'
623  call setline(1, [' bbvimb', ''])
624  set incsearch
625  " first match
626  norm! gg0
627  " moves to next match of previous search pattern, just like /<cr>
628  call feedkeys("/\<c-g>\<cr>", 'tx')
629  call assert_equal([0,1,2,0], getpos('.'))
630  " moves to next match of previous search pattern, just like /<cr>
631  call feedkeys("/\<cr>", 'tx')
632  call assert_equal([0,1,3,0], getpos('.'))
633  " moves to next match of previous search pattern, just like /<cr>
634  call feedkeys("/\<c-t>\<cr>", 'tx')
635  call assert_equal([0,1,7,0], getpos('.'))
636
637  " using an offset uses the last search pattern
638  call cursor(1, 1)
639  call setline(1, ['1 bbvimb', ' 2 bbvimb'])
640  let @/ = 'b'
641  call feedkeys("//e\<c-g>\<cr>", 'tx')
642  call assert_equal('1 bbvimb', getline('.'))
643  call assert_equal(4, col('.'))
644
645  set noincsearch
646  call test_override("char_avail", 0)
647  bw!
648endfunc
649
650func Test_search_cmdline8()
651  " Highlighting is cleared in all windows
652  " since hls applies to all windows
653  CheckOption incsearch
654  CheckFeature terminal
655  CheckNotGui
656  if has("win32")
657    throw "Skipped: Bug with sending <ESC> to terminal window not fixed yet"
658  endif
659
660  let h = winheight(0)
661  if h < 3
662    return
663  endif
664  " Prepare buffer text
665  let lines = ['abb vim vim vi', 'vimvivim']
666  call writefile(lines, 'Xsearch.txt')
667  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', 'Xsearch.txt'], {'term_rows': 3})
668
669  call WaitForAssert({-> assert_equal(lines, [term_getline(buf, 1), term_getline(buf, 2)])})
670
671  call term_sendkeys(buf, ":set incsearch hlsearch\<cr>")
672  call term_sendkeys(buf, ":14vsp\<cr>")
673  call term_sendkeys(buf, "/vim\<cr>")
674  call term_sendkeys(buf, "/b\<esc>")
675  call term_sendkeys(buf, "gg0")
676  call TermWait(buf, 250)
677  let screen_line = term_scrape(buf, 1)
678  let [a0,a1,a2,a3] = [screen_line[3].attr, screen_line[4].attr,
679        \ screen_line[18].attr, screen_line[19].attr]
680  call assert_notequal(a0, a1)
681  call assert_notequal(a0, a3)
682  call assert_notequal(a1, a2)
683  call assert_equal(a0, a2)
684  call assert_equal(a1, a3)
685  " clean up
686  call delete('Xsearch.txt')
687
688  bwipe!
689endfunc
690
691" Tests for regexp with various magic settings
692func Run_search_regexp_magic_opt()
693  put ='1 a aa abb abbccc'
694  exe 'normal! /a*b\{2}c\+/e' . "\<CR>"
695  call assert_equal([0, 2, 17, 0], getpos('.'))
696
697  put ='2 d dd dee deefff'
698  exe 'normal! /\Md\*e\{2}f\+/e' . "\<CR>"
699  call assert_equal([0, 3, 17, 0], getpos('.'))
700
701  set nomagic
702  put ='3 g gg ghh ghhiii'
703  exe 'normal! /g\*h\{2}i\+/e' . "\<CR>"
704  call assert_equal([0, 4, 17, 0], getpos('.'))
705
706  put ='4 j jj jkk jkklll'
707  exe 'normal! /\mj*k\{2}l\+/e' . "\<CR>"
708  call assert_equal([0, 5, 17, 0], getpos('.'))
709
710  put ='5 m mm mnn mnnooo'
711  exe 'normal! /\vm*n{2}o+/e' . "\<CR>"
712  call assert_equal([0, 6, 17, 0], getpos('.'))
713
714  put ='6 x ^aa$ x'
715  exe 'normal! /\V^aa$' . "\<CR>"
716  call assert_equal([0, 7, 5, 0], getpos('.'))
717
718  set magic
719  put ='7 (a)(b) abbaa'
720  exe 'normal! /\v(a)(b)\2\1\1/e' . "\<CR>"
721  call assert_equal([0, 8, 14, 0], getpos('.'))
722
723  put ='8 axx [ab]xx'
724  exe 'normal! /\V[ab]\(\[xy]\)\1' . "\<CR>"
725  call assert_equal([0, 9, 7, 0], getpos('.'))
726
727  %d
728endfunc
729
730func Test_search_regexp()
731  enew!
732
733  set regexpengine=1
734  call Run_search_regexp_magic_opt()
735  set regexpengine=2
736  call Run_search_regexp_magic_opt()
737  set regexpengine&
738
739  set undolevels=100
740  put ='9 foobar'
741  put =''
742  exe "normal! a\<C-G>u\<Esc>"
743  normal G
744  exe 'normal! dv?bar?' . "\<CR>"
745  call assert_equal('9 foo', getline('.'))
746  call assert_equal([0, 2, 5, 0], getpos('.'))
747  call assert_equal(2, line('$'))
748  normal u
749  call assert_equal('9 foobar', getline('.'))
750  call assert_equal([0, 2, 6, 0], getpos('.'))
751  call assert_equal(3, line('$'))
752
753  set undolevels&
754  enew!
755endfunc
756
757func Test_search_cmdline_incsearch_highlight()
758  CheckOption incsearch
759
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 TermWait(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 TermWait(buf, 100)
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 TermWait(buf, 100)
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 TermWait(buf, 100)
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 TermWait(buf, 100)
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 TermWait(buf, 100)
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 TermWait(buf, 100)
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  CheckOption incsearch
878
879  call test_override("char_avail", 1)
880  new
881  call setline(1, ['foo'])
882  set incsearch
883  " Test that error E14 does not occur in parsing command modifier.
884  call feedkeys("V:tab", 'tx')
885
886  call Incsearch_cleanup()
887endfunc
888
889func Test_incsearch_scrolling()
890  CheckRunVimInTerminal
891  call assert_equal(0, &scrolloff)
892  call writefile([
893	\ 'let dots = repeat(".", 120)',
894	\ 'set incsearch cmdheight=2 scrolloff=0',
895	\ 'call setline(1, [dots, dots, dots, "", "target", dots, dots])',
896	\ 'normal gg',
897	\ 'redraw',
898	\ ], 'Xscript')
899  let buf = RunVimInTerminal('-S Xscript', {'rows': 9, 'cols': 70})
900  " Need to send one key at a time to force a redraw
901  call term_sendkeys(buf, '/')
902  sleep 100m
903  call term_sendkeys(buf, 't')
904  sleep 100m
905  call term_sendkeys(buf, 'a')
906  sleep 100m
907  call term_sendkeys(buf, 'r')
908  sleep 100m
909  call term_sendkeys(buf, 'g')
910  call VerifyScreenDump(buf, 'Test_incsearch_scrolling_01', {})
911
912  call term_sendkeys(buf, "\<Esc>")
913  call StopVimInTerminal(buf)
914  call delete('Xscript')
915endfunc
916
917func Test_incsearch_search_dump()
918  CheckOption incsearch
919  CheckScreendump
920
921  call writefile([
922	\ 'set incsearch hlsearch scrolloff=0',
923	\ 'for n in range(1, 8)',
924	\ '  call setline(n, "foo " . n)',
925	\ 'endfor',
926	\ '3',
927	\ ], 'Xis_search_script')
928  let buf = RunVimInTerminal('-S Xis_search_script', {'rows': 9, 'cols': 70})
929  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
930  " the 'ambiwidth' check.
931  sleep 100m
932
933  " Need to send one key at a time to force a redraw.
934  call term_sendkeys(buf, '/fo')
935  call VerifyScreenDump(buf, 'Test_incsearch_search_01', {})
936  call term_sendkeys(buf, "\<Esc>")
937  sleep 100m
938
939  call term_sendkeys(buf, '/\v')
940  call VerifyScreenDump(buf, 'Test_incsearch_search_02', {})
941  call term_sendkeys(buf, "\<Esc>")
942
943  call StopVimInTerminal(buf)
944  call delete('Xis_search_script')
945endfunc
946
947func Test_hlsearch_dump()
948  CheckOption hlsearch
949  CheckScreendump
950
951  call writefile([
952	\ 'set hlsearch cursorline',
953        \ 'call setline(1, ["xxx", "xxx", "xxx"])',
954	\ '/.*',
955	\ '2',
956	\ ], 'Xhlsearch_script')
957  let buf = RunVimInTerminal('-S Xhlsearch_script', {'rows': 6, 'cols': 50})
958  call VerifyScreenDump(buf, 'Test_hlsearch_1', {})
959
960  call term_sendkeys(buf, "/\\_.*\<CR>")
961  call VerifyScreenDump(buf, 'Test_hlsearch_2', {})
962
963  call StopVimInTerminal(buf)
964  call delete('Xhlsearch_script')
965endfunc
966
967func Test_hlsearch_and_visual()
968  CheckOption hlsearch
969  CheckScreendump
970
971  call writefile([
972	\ 'set hlsearch',
973        \ 'call setline(1, repeat(["xxx yyy zzz"], 3))',
974        \ 'hi Search cterm=bold',
975	\ '/yyy',
976	\ 'call cursor(1, 6)',
977	\ ], 'Xhlvisual_script')
978  let buf = RunVimInTerminal('-S Xhlvisual_script', {'rows': 6, 'cols': 40})
979  call term_sendkeys(buf, "vjj")
980  call VerifyScreenDump(buf, 'Test_hlsearch_visual_1', {})
981  call term_sendkeys(buf, "\<Esc>")
982
983  call StopVimInTerminal(buf)
984  call delete('Xhlvisual_script')
985endfunc
986
987func Test_hlsearch_block_visual_match()
988  CheckScreendump
989
990  let lines =<< trim END
991    set hlsearch
992    call setline(1, ['aa', 'bbbb', 'cccccc'])
993  END
994  call writefile(lines, 'Xhlsearch_block')
995  let buf = RunVimInTerminal('-S Xhlsearch_block', {'rows': 9, 'cols': 60})
996
997  call term_sendkeys(buf, "G\<C-V>$kk\<Esc>")
998  sleep 100m
999  call term_sendkeys(buf, "/\\%V\<CR>")
1000  sleep 100m
1001  call VerifyScreenDump(buf, 'Test_hlsearch_block_visual_match', {})
1002
1003  call StopVimInTerminal(buf)
1004  call delete('Xhlsearch_block')
1005endfunc
1006
1007func Test_incsearch_substitute()
1008  CheckOption incsearch
1009
1010  call test_override("char_avail", 1)
1011  new
1012  set incsearch
1013  for n in range(1, 10)
1014    call setline(n, 'foo ' . n)
1015  endfor
1016  4
1017  call feedkeys(":.,.+2s/foo\<BS>o\<BS>o/xxx\<cr>", 'tx')
1018  call assert_equal('foo 3', getline(3))
1019  call assert_equal('xxx 4', getline(4))
1020  call assert_equal('xxx 5', getline(5))
1021  call assert_equal('xxx 6', getline(6))
1022  call assert_equal('foo 7', getline(7))
1023
1024  call Incsearch_cleanup()
1025endfunc
1026
1027func Test_incsearch_substitute_long_line()
1028  new
1029  call test_override("char_avail", 1)
1030  set incsearch
1031
1032  call repeat('x', 100000)->setline(1)
1033  call feedkeys(':s/\%c', 'xt')
1034  redraw
1035  call feedkeys("\<Esc>", 'xt')
1036
1037  call Incsearch_cleanup()
1038  bwipe!
1039endfunc
1040
1041" Similar to Test_incsearch_substitute() but with a screendump halfway.
1042func Test_incsearch_substitute_dump()
1043  CheckOption incsearch
1044  CheckScreendump
1045
1046  call writefile([
1047	\ 'set incsearch hlsearch scrolloff=0',
1048	\ 'for n in range(1, 10)',
1049	\ '  call setline(n, "foo " . n)',
1050	\ 'endfor',
1051	\ 'call setline(11, "bar 11")',
1052	\ '3',
1053	\ ], 'Xis_subst_script')
1054  let buf = RunVimInTerminal('-S Xis_subst_script', {'rows': 9, 'cols': 70})
1055  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1056  " the 'ambiwidth' check.
1057  sleep 100m
1058
1059  " Need to send one key at a time to force a redraw.
1060  " Select three lines at the cursor with typed pattern.
1061  call term_sendkeys(buf, ':.,.+2s/')
1062  sleep 100m
1063  call term_sendkeys(buf, 'f')
1064  sleep 100m
1065  call term_sendkeys(buf, 'o')
1066  sleep 100m
1067  call term_sendkeys(buf, 'o')
1068  call VerifyScreenDump(buf, 'Test_incsearch_substitute_01', {})
1069  call term_sendkeys(buf, "\<Esc>")
1070
1071  " Select three lines at the cursor using previous pattern.
1072  call term_sendkeys(buf, "/foo\<CR>")
1073  sleep 100m
1074  call term_sendkeys(buf, ':.,.+2s//')
1075  call VerifyScreenDump(buf, 'Test_incsearch_substitute_02', {})
1076
1077  " Deleting last slash should remove the match.
1078  call term_sendkeys(buf, "\<BS>")
1079  call VerifyScreenDump(buf, 'Test_incsearch_substitute_03', {})
1080  call term_sendkeys(buf, "\<Esc>")
1081
1082  " Reverse range is accepted
1083  call term_sendkeys(buf, ':5,2s/foo')
1084  call VerifyScreenDump(buf, 'Test_incsearch_substitute_04', {})
1085  call term_sendkeys(buf, "\<Esc>")
1086
1087  " White space after the command is skipped
1088  call term_sendkeys(buf, ':2,3sub  /fo')
1089  call VerifyScreenDump(buf, 'Test_incsearch_substitute_05', {})
1090  call term_sendkeys(buf, "\<Esc>")
1091
1092  " Command modifiers are skipped
1093  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.')
1094  call VerifyScreenDump(buf, 'Test_incsearch_substitute_06', {})
1095  call term_sendkeys(buf, "\<Esc>")
1096
1097  " Cursorline highlighting at match
1098  call term_sendkeys(buf, ":set cursorline\<CR>")
1099  call term_sendkeys(buf, 'G9G')
1100  call term_sendkeys(buf, ':9,11s/bar')
1101  call VerifyScreenDump(buf, 'Test_incsearch_substitute_07', {})
1102  call term_sendkeys(buf, "\<Esc>")
1103
1104  " Cursorline highlighting at cursor when no match
1105  call term_sendkeys(buf, ':9,10s/bar')
1106  call VerifyScreenDump(buf, 'Test_incsearch_substitute_08', {})
1107  call term_sendkeys(buf, "\<Esc>")
1108
1109  " Only \v handled as empty pattern, does not move cursor
1110  call term_sendkeys(buf, '3G4G')
1111  call term_sendkeys(buf, ":nohlsearch\<CR>")
1112  call term_sendkeys(buf, ':6,7s/\v')
1113  call VerifyScreenDump(buf, 'Test_incsearch_substitute_09', {})
1114  call term_sendkeys(buf, "\<Esc>")
1115
1116  call term_sendkeys(buf, ":set nocursorline\<CR>")
1117
1118  " All matches are highlighted for 'hlsearch' after the incsearch canceled
1119  call term_sendkeys(buf, "1G*")
1120  call term_sendkeys(buf, ":2,5s/foo")
1121  sleep 100m
1122  call term_sendkeys(buf, "\<Esc>")
1123  call VerifyScreenDump(buf, 'Test_incsearch_substitute_10', {})
1124
1125  call term_sendkeys(buf, ":split\<CR>")
1126  call term_sendkeys(buf, ":let @/ = 'xyz'\<CR>")
1127  call term_sendkeys(buf, ":%s/.")
1128  call VerifyScreenDump(buf, 'Test_incsearch_substitute_11', {})
1129  call term_sendkeys(buf, "\<BS>")
1130  call VerifyScreenDump(buf, 'Test_incsearch_substitute_12', {})
1131  call term_sendkeys(buf, "\<Esc>")
1132  call VerifyScreenDump(buf, 'Test_incsearch_substitute_13', {})
1133  call term_sendkeys(buf, ":%bwipe!\<CR>")
1134  call term_sendkeys(buf, ":only!\<CR>")
1135
1136  "  get :'<,'>s command in history
1137  call term_sendkeys(buf, ":set cmdheight=2\<CR>")
1138  call term_sendkeys(buf, "aasdfasdf\<Esc>")
1139  call term_sendkeys(buf, "V:s/a/b/g\<CR>")
1140  " Using '<,'> does not give E20
1141  call term_sendkeys(buf, ":new\<CR>")
1142  call term_sendkeys(buf, "aasdfasdf\<Esc>")
1143  call term_sendkeys(buf, ":\<Up>\<Up>")
1144  call VerifyScreenDump(buf, 'Test_incsearch_substitute_14', {})
1145  call term_sendkeys(buf, "<Esc>")
1146
1147  call StopVimInTerminal(buf)
1148  call delete('Xis_subst_script')
1149endfunc
1150
1151func Test_incsearch_highlighting()
1152  CheckOption incsearch
1153  CheckScreendump
1154
1155  call writefile([
1156	\ 'set incsearch hlsearch',
1157	\ 'call setline(1, "hello/there")',
1158	\ ], 'Xis_subst_hl_script')
1159  let buf = RunVimInTerminal('-S Xis_subst_hl_script', {'rows': 4, 'cols': 20})
1160  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1161  " the 'ambiwidth' check.
1162  sleep 300m
1163
1164  " Using a different search delimiter should still highlight matches
1165  " that contain a '/'.
1166  call term_sendkeys(buf, ":%s;ello/the")
1167  call VerifyScreenDump(buf, 'Test_incsearch_substitute_15', {})
1168  call term_sendkeys(buf, "<Esc>")
1169
1170  call StopVimInTerminal(buf)
1171  call delete('Xis_subst_hl_script')
1172endfunc
1173
1174func Test_incsearch_with_change()
1175  CheckFeature timers
1176  CheckOption incsearch
1177  CheckScreendump
1178
1179  call writefile([
1180	\ 'set incsearch hlsearch scrolloff=0',
1181	\ 'call setline(1, ["one", "two ------ X", "three"])',
1182	\ 'call timer_start(200, { _ -> setline(2, "x")})',
1183	\ ], 'Xis_change_script')
1184  let buf = RunVimInTerminal('-S Xis_change_script', {'rows': 9, 'cols': 70})
1185  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1186  " the 'ambiwidth' check.
1187  sleep 300m
1188
1189  " Highlight X, it will be deleted by the timer callback.
1190  call term_sendkeys(buf, ':%s/X')
1191  call VerifyScreenDump(buf, 'Test_incsearch_change_01', {})
1192  call term_sendkeys(buf, "\<Esc>")
1193
1194  call StopVimInTerminal(buf)
1195  call delete('Xis_change_script')
1196endfunc
1197
1198" Similar to Test_incsearch_substitute_dump() for :sort
1199func Test_incsearch_sort_dump()
1200  CheckOption incsearch
1201  CheckScreendump
1202
1203  call writefile([
1204	\ 'set incsearch hlsearch scrolloff=0',
1205	\ 'call setline(1, ["another one 2", "that one 3", "the one 1"])',
1206	\ ], 'Xis_sort_script')
1207  let buf = RunVimInTerminal('-S Xis_sort_script', {'rows': 9, 'cols': 70})
1208  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1209  " the 'ambiwidth' check.
1210  sleep 100m
1211
1212  call term_sendkeys(buf, ':sort ni u /on')
1213  call VerifyScreenDump(buf, 'Test_incsearch_sort_01', {})
1214  call term_sendkeys(buf, "\<Esc>")
1215
1216  call term_sendkeys(buf, ':sort! /on')
1217  call VerifyScreenDump(buf, 'Test_incsearch_sort_02', {})
1218  call term_sendkeys(buf, "\<Esc>")
1219
1220  call StopVimInTerminal(buf)
1221  call delete('Xis_sort_script')
1222endfunc
1223
1224" Similar to Test_incsearch_substitute_dump() for :vimgrep famiry
1225func Test_incsearch_vimgrep_dump()
1226  CheckOption incsearch
1227  CheckScreendump
1228
1229  call writefile([
1230	\ 'set incsearch hlsearch scrolloff=0',
1231	\ 'call setline(1, ["another one 2", "that one 3", "the one 1"])',
1232	\ ], 'Xis_vimgrep_script')
1233  let buf = RunVimInTerminal('-S Xis_vimgrep_script', {'rows': 9, 'cols': 70})
1234  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1235  " the 'ambiwidth' check.
1236  sleep 100m
1237
1238  " Need to send one key at a time to force a redraw.
1239  call term_sendkeys(buf, ':vimgrep on')
1240  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_01', {})
1241  call term_sendkeys(buf, "\<Esc>")
1242
1243  call term_sendkeys(buf, ':vimg /on/ *.txt')
1244  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_02', {})
1245  call term_sendkeys(buf, "\<Esc>")
1246
1247  call term_sendkeys(buf, ':vimgrepadd "\<on')
1248  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_03', {})
1249  call term_sendkeys(buf, "\<Esc>")
1250
1251  call term_sendkeys(buf, ':lv "tha')
1252  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_04', {})
1253  call term_sendkeys(buf, "\<Esc>")
1254
1255  call term_sendkeys(buf, ':lvimgrepa "the" **/*.txt')
1256  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_05', {})
1257  call term_sendkeys(buf, "\<Esc>")
1258
1259  call StopVimInTerminal(buf)
1260  call delete('Xis_vimgrep_script')
1261endfunc
1262
1263func Test_keep_last_search_pattern()
1264  CheckOption incsearch
1265
1266  new
1267  call setline(1, ['foo', 'foo', 'foo'])
1268  set incsearch
1269  call test_override("char_avail", 1)
1270  let @/ = 'bar'
1271  call feedkeys(":/foo/s//\<Esc>", 'ntx')
1272  call assert_equal('bar', @/)
1273
1274  " no error message if pattern not found
1275  call feedkeys(":/xyz/s//\<Esc>", 'ntx')
1276  call assert_equal('bar', @/)
1277
1278  bwipe!
1279  call test_override("ALL", 0)
1280  set noincsearch
1281endfunc
1282
1283func Test_word_under_cursor_after_match()
1284  CheckOption incsearch
1285
1286  new
1287  call setline(1, 'foo bar')
1288  set incsearch
1289  call test_override("char_avail", 1)
1290  try
1291    call feedkeys("/foo\<C-R>\<C-W>\<CR>", 'ntx')
1292  catch /E486:/
1293  endtry
1294  call assert_equal('foobar', @/)
1295
1296  bwipe!
1297  call test_override("ALL", 0)
1298  set noincsearch
1299endfunc
1300
1301func Test_subst_word_under_cursor()
1302  CheckOption incsearch
1303
1304  new
1305  call setline(1, ['int SomeLongName;', 'for (xxx = 1; xxx < len; ++xxx)'])
1306  set incsearch
1307  call test_override("char_avail", 1)
1308  call feedkeys("/LongName\<CR>", 'ntx')
1309  call feedkeys(":%s/xxx/\<C-R>\<C-W>/g\<CR>", 'ntx')
1310  call assert_equal('for (SomeLongName = 1; SomeLongName < len; ++SomeLongName)', getline(2))
1311
1312  bwipe!
1313  call test_override("ALL", 0)
1314  set noincsearch
1315endfunc
1316
1317func Test_search_undefined_behaviour()
1318  CheckFeature terminal
1319
1320  let h = winheight(0)
1321  if h < 3
1322    return
1323  endif
1324  " did cause an undefined left shift
1325  let g:buf = term_start([GetVimProg(), '--clean', '-e', '-s', '-c', 'call search(getline("."))', 'samples/test000'], {'term_rows': 3})
1326  call assert_equal([''], getline(1, '$'))
1327  call term_sendkeys(g:buf, ":qa!\<cr>")
1328  bwipe!
1329endfunc
1330
1331func Test_search_undefined_behaviour2()
1332  call search("\%UC0000000")
1333endfunc
1334
1335" Test for search('multi-byte char', 'bce')
1336func Test_search_multibyte()
1337  let save_enc = &encoding
1338  set encoding=utf8
1339  enew!
1340  call append('$', 'A')
1341  call cursor(2, 1)
1342  call assert_equal(2, search('A', 'bce', line('.')))
1343  enew!
1344  let &encoding = save_enc
1345endfunc
1346
1347" This was causing E874.  Also causes an invalid read?
1348func Test_look_behind()
1349  new
1350  call setline(1, '0\|\&\n\@<=')
1351  call search(getline("."))
1352  bwipe!
1353endfunc
1354
1355func Test_search_visual_area_linewise()
1356  new
1357  call setline(1, ['aa', 'bb', 'cc'])
1358  exe "normal 2GV\<Esc>"
1359  for engine in [1, 2]
1360    exe 'set regexpengine=' .. engine
1361    exe "normal gg/\\%'<\<CR>>"
1362    call assert_equal([0, 2, 1, 0, 1], getcurpos(), 'engine ' .. engine)
1363    exe "normal gg/\\%'>\<CR>"
1364    call assert_equal([0, 2, 2, 0, 2], getcurpos(), 'engine ' .. engine)
1365  endfor
1366
1367  bwipe!
1368  set regexpengine&
1369endfunc
1370
1371func Test_search_sentence()
1372  new
1373  " this used to cause a crash
1374  /\%'(
1375  /
1376  bwipe
1377endfunc
1378
1379" Test that there is no crash when there is a last search pattern but no last
1380" substitute pattern.
1381func Test_no_last_substitute_pat()
1382  " Use viminfo to set the last search pattern to a string and make the last
1383  " substitute pattern the most recent used and make it empty (NULL).
1384  call writefile(['~MSle0/bar', '~MSle0~&'], 'Xviminfo')
1385  rviminfo! Xviminfo
1386  call assert_fails('normal n', 'E35:')
1387
1388  call delete('Xviminfo')
1389endfunc
1390
1391func Test_search_Ctrl_L_combining()
1392  " Make sure, that Ctrl-L works correctly with combining characters.
1393  " It uses an artificial example of an 'a' with 4 combining chars:
1394    " 'a' U+0061 Dec:97 LATIN SMALL LETTER A &#x61; /\%u61\Z "\u0061"
1395    " ' ̀' U+0300 Dec:768 COMBINING GRAVE ACCENT &#x300; /\%u300\Z "\u0300"
1396    " ' ́' U+0301 Dec:769 COMBINING ACUTE ACCENT &#x301; /\%u301\Z "\u0301"
1397    " ' ̇' U+0307 Dec:775 COMBINING DOT ABOVE &#x307; /\%u307\Z "\u0307"
1398    " ' ̣' U+0323 Dec:803 COMBINING DOT BELOW &#x323; /\%u323 "\u0323"
1399  " Those should also appear on the commandline
1400  CheckOption incsearch
1401
1402  call Cmdline3_prep()
1403  1
1404  let bufcontent = ['', 'Miạ̀́̇m']
1405  call append('$', bufcontent)
1406  call feedkeys("/Mi\<c-l>\<c-l>\<cr>", 'tx')
1407  call assert_equal(5, line('.'))
1408  call assert_equal(bufcontent[1], @/)
1409  call Incsearch_cleanup()
1410endfunc
1411
1412func Test_large_hex_chars1()
1413  " This used to cause a crash, the character becomes an NFA state.
1414  try
1415    /\%Ufffffc23
1416  catch
1417    call assert_match('E678:', v:exception)
1418  endtry
1419  try
1420    set re=1
1421    /\%Ufffffc23
1422  catch
1423    call assert_match('E678:', v:exception)
1424  endtry
1425  set re&
1426endfunc
1427
1428func Test_large_hex_chars2()
1429  " This used to cause a crash, the character becomes an NFA state.
1430  try
1431    /[\Ufffffc1f]
1432  catch
1433    call assert_match('E486:', v:exception)
1434  endtry
1435  try
1436    set re=1
1437    /[\Ufffffc1f]
1438  catch
1439    call assert_match('E486:', v:exception)
1440  endtry
1441  set re&
1442endfunc
1443
1444func Test_one_error_msg()
1445  " This was also giving an internal error
1446  call assert_fails('call search(" \\((\\v[[=P=]]){185}+             ")', 'E871:')
1447endfunc
1448
1449func Test_incsearch_add_char_under_cursor()
1450  CheckOption incsearch
1451
1452  set incsearch
1453  new
1454  call setline(1, ['find match', 'anything'])
1455  1
1456  call test_override('char_avail', 1)
1457  call feedkeys("fc/m\<C-L>\<C-L>\<C-L>\<C-L>\<C-L>\<CR>", 'tx')
1458  call assert_equal('match', @/)
1459  call test_override('char_avail', 0)
1460
1461  set incsearch&
1462  bwipe!
1463endfunc
1464
1465" Test for the search() function with match at the cursor position
1466func Test_search_match_at_curpos()
1467  new
1468  call append(0, ['foobar', '', 'one two', ''])
1469
1470  normal gg
1471
1472  eval 'foobar'->search('c')
1473  call assert_equal([1, 1], [line('.'), col('.')])
1474
1475  normal j
1476  call search('^$', 'c')
1477  call assert_equal([2, 1], [line('.'), col('.')])
1478
1479  call search('^$', 'bc')
1480  call assert_equal([2, 1], [line('.'), col('.')])
1481
1482  exe "normal /two\<CR>"
1483  call search('.', 'c')
1484  call assert_equal([3, 5], [line('.'), col('.')])
1485
1486  close!
1487endfunc
1488
1489" Test for error cases with the search() function
1490func Test_search_errors()
1491  call assert_fails("call search('pat', [])", 'E730:')
1492  call assert_fails("call search('pat', 'b', {})", 'E728:')
1493  call assert_fails("call search('pat', 'b', 1, [])", 'E745:')
1494  call assert_fails("call search('pat', 'ns')", 'E475:')
1495  call assert_fails("call search('pat', 'mr')", 'E475:')
1496
1497  new
1498  call setline(1, ['foo', 'bar'])
1499  call assert_fails('call feedkeys("/foo/;/bar/;\<CR>", "tx")', 'E386:')
1500  bwipe!
1501endfunc
1502
1503func Test_search_display_pattern()
1504  new
1505  call setline(1, ['foo', 'bar', 'foobar'])
1506
1507  call cursor(1, 1)
1508  let @/ = 'foo'
1509  let pat = @/->escape('()*?'. '\s\+')
1510  let g:a = execute(':unsilent :norm! n')
1511  call assert_match(pat, g:a)
1512
1513  " right-left
1514  if exists("+rightleft")
1515    set rl
1516    call cursor(1, 1)
1517    let @/ = 'foo'
1518    let pat = 'oof/\s\+'
1519    let g:a = execute(':unsilent :norm! n')
1520    call assert_match(pat, g:a)
1521    set norl
1522  endif
1523endfunc
1524
1525func Test_searchdecl()
1526  let lines =<< trim END
1527     int global;
1528
1529     func()
1530     {
1531       int global;
1532       if (cond) {
1533	 int local;
1534       }
1535       int local;
1536       // comment
1537     }
1538  END
1539  new
1540  call setline(1, lines)
1541  10
1542  call assert_equal(0, searchdecl('local', 0, 0))
1543  call assert_equal(7, getcurpos()[1])
1544
1545  10
1546  call assert_equal(0, 'local'->searchdecl(0, 1))
1547  call assert_equal(9, getcurpos()[1])
1548
1549  10
1550  call assert_equal(0, searchdecl('global'))
1551  call assert_equal(5, getcurpos()[1])
1552
1553  10
1554  call assert_equal(0, searchdecl('global', 1))
1555  call assert_equal(1, getcurpos()[1])
1556
1557  bwipe!
1558endfunc
1559
1560func Test_search_special()
1561  " this was causing illegal memory access and an endless loop
1562  set t_PE=
1563  exe "norm /\x80PS"
1564endfunc
1565
1566" Test for command failures when the last search pattern is not set.
1567" Need to run this in a new vim instance where last search pattern is not set.
1568func Test_search_with_no_last_pat()
1569  let lines =<< trim [SCRIPT]
1570    call assert_fails("normal i\<C-R>/\e", 'E35:')
1571    call assert_fails("exe '/'", 'E35:')
1572    call assert_fails("exe '?'", 'E35:')
1573    call assert_fails("/", 'E35:')
1574    call assert_fails("?", 'E35:')
1575    call assert_fails("normal n", 'E35:')
1576    call assert_fails("normal N", 'E35:')
1577    call assert_fails("normal gn", 'E35:')
1578    call assert_fails("normal gN", 'E35:')
1579    call assert_fails("normal cgn", 'E35:')
1580    call assert_fails("normal cgN", 'E35:')
1581    let p = []
1582    let p = @/
1583    call assert_equal('', p)
1584    call assert_fails("normal :\<C-R>/", 'E35:')
1585    call assert_fails("//p", 'E35:')
1586    call assert_fails(";//p", 'E35:')
1587    call assert_fails("??p", 'E35:')
1588    call assert_fails(";??p", 'E35:')
1589    call assert_fails('g//p', ['E35:', 'E476:'])
1590    call assert_fails('v//p', ['E35:', 'E476:'])
1591    call writefile(v:errors, 'Xresult')
1592    qall!
1593  [SCRIPT]
1594  call writefile(lines, 'Xscript')
1595
1596  if RunVim([], [], '--clean -S Xscript')
1597    call assert_equal([], readfile('Xresult'))
1598  endif
1599  call delete('Xscript')
1600  call delete('Xresult')
1601endfunc
1602
1603" Test for using tilde (~) atom in search. This should use the last used
1604" substitute pattern
1605func Test_search_tilde_pat()
1606  let lines =<< trim [SCRIPT]
1607    set regexpengine=1
1608    call assert_fails('exe "normal /~\<CR>"', 'E33:')
1609    call assert_fails('exe "normal ?~\<CR>"', 'E33:')
1610    set regexpengine=2
1611    call assert_fails('exe "normal /~\<CR>"', ['E33:', 'E383:'])
1612    call assert_fails('exe "normal ?~\<CR>"', ['E33:', 'E383:'])
1613    set regexpengine&
1614    call writefile(v:errors, 'Xresult')
1615    qall!
1616  [SCRIPT]
1617  call writefile(lines, 'Xscript')
1618  if RunVim([], [], '--clean -S Xscript')
1619    call assert_equal([], readfile('Xresult'))
1620  endif
1621  call delete('Xscript')
1622  call delete('Xresult')
1623endfunc
1624
1625" Test for searching a pattern that is not present with 'nowrapscan'
1626func Test_search_pat_not_found()
1627  new
1628  set nowrapscan
1629  let @/ = '1abcxyz2'
1630  call assert_fails('normal n', 'E385:')
1631  call assert_fails('normal N', 'E384:')
1632  set wrapscan&
1633  close
1634endfunc
1635
1636" Test for v:searchforward variable
1637func Test_searchforward_var()
1638  new
1639  call setline(1, ['foo', '', 'foo'])
1640  call cursor(2, 1)
1641  let @/ = 'foo'
1642  let v:searchforward = 0
1643  normal N
1644  call assert_equal(3, line('.'))
1645  call cursor(2, 1)
1646  let v:searchforward = 1
1647  normal N
1648  call assert_equal(1, line('.'))
1649  close!
1650endfunc
1651
1652" Test for invalid regular expressions
1653func Test_invalid_regexp()
1654  set regexpengine=1
1655  call assert_fails("call search(repeat('\\(.\\)', 10))", 'E51:')
1656  call assert_fails("call search('\\%(')", 'E53:')
1657  call assert_fails("call search('\\(')", 'E54:')
1658  call assert_fails("call search('\\)')", 'E55:')
1659  call assert_fails("call search('x\\@#')", 'E59:')
1660  call assert_fails('call search(''\v%(%(%(%(%(%(%(%(%(%(%(a){1}){1}){1}){1}){1}){1}){1}){1}){1}){1}){1}'')', 'E60:')
1661  call assert_fails("call search('a\\+*')", 'E61:')
1662  call assert_fails("call search('\\_m')", 'E63:')
1663  call assert_fails("call search('\\+')", 'E64:')
1664  call assert_fails("call search('\\1')", 'E65:')
1665  call assert_fails("call search('\\z\\(\\)')", 'E66:')
1666  call assert_fails("call search('\\z2')", 'E67:')
1667  call assert_fails("call search('\\zx')", 'E68:')
1668  call assert_fails("call search('\\%[ab')", 'E69:')
1669  call assert_fails("call search('\\%[]')", 'E70:')
1670  call assert_fails("call search('\\%a')", 'E71:')
1671  call assert_fails("call search('ab\\%[\\(cd\\)]')", 'E369:')
1672  call assert_fails("call search('ab\\%[\\%(cd\\)]')", 'E369:')
1673  set regexpengine=2
1674  call assert_fails("call search('\\_')", 'E865:')
1675  call assert_fails("call search('\\+')", 'E866:')
1676  call assert_fails("call search('\\zx')", 'E867:')
1677  call assert_fails("call search('\\%a')", 'E867:')
1678  call assert_fails("call search('x\\@#')", 'E869:')
1679  call assert_fails("call search(repeat('\\(.\\)', 10))", 'E872:')
1680  call assert_fails("call search('\\_m')", 'E877:')
1681  call assert_fails("call search('\\%(')", 'E53:')
1682  call assert_fails("call search('\\(')", 'E54:')
1683  call assert_fails("call search('\\)')", 'E55:')
1684  call assert_fails("call search('\\z\\(\\)')", 'E66:')
1685  call assert_fails("call search('\\%[ab')", 'E69:')
1686  call assert_fails("call search('\\%[]')", 'E70:')
1687  call assert_fails("call search('\\%9999999999999999999999999999v')", 'E951:')
1688  set regexpengine&
1689  call assert_fails("call search('\\%#=3ab')", 'E864:')
1690endfunc
1691
1692" Test for searching a very complex pattern in a string. Should switch the
1693" regexp engine from NFA to the old engine.
1694func Test_regexp_switch_engine()
1695  let l = readfile('samples/re.freeze.txt')
1696  let v = substitute(l[4], '..\@<!', '', '')
1697  call assert_equal(l[4], v)
1698endfunc
1699
1700" Test for the \%V atom to search within visually selected text
1701func Test_search_in_visual_area()
1702  new
1703  call setline(1, ['foo bar1', 'foo bar2', 'foo bar3', 'foo bar4'])
1704  exe "normal 2GVjo/\\%Vbar\<CR>\<Esc>"
1705  call assert_equal([2, 5], [line('.'), col('.')])
1706  exe "normal 2GVj$?\\%Vbar\<CR>\<Esc>"
1707  call assert_equal([3, 5], [line('.'), col('.')])
1708  close!
1709endfunc
1710
1711" Test for searching with 'smartcase' and 'ignorecase'
1712func Test_search_smartcase()
1713  new
1714  call setline(1, ['', 'Hello'])
1715  set noignorecase nosmartcase
1716  call assert_fails('exe "normal /\\a\\_.\\(.*\\)O\<CR>"', 'E486:')
1717
1718  set ignorecase nosmartcase
1719  exe "normal /\\a\\_.\\(.*\\)O\<CR>"
1720  call assert_equal([2, 1], [line('.'), col('.')])
1721
1722  call cursor(1, 1)
1723  set ignorecase smartcase
1724  call assert_fails('exe "normal /\\a\\_.\\(.*\\)O\<CR>"', 'E486:')
1725
1726  exe "normal /\\a\\_.\\(.*\\)o\<CR>"
1727  call assert_equal([2, 1], [line('.'), col('.')])
1728
1729  " Test for using special atoms with 'smartcase'
1730  call setline(1, ['', '    Hello\ '])
1731  call cursor(1, 1)
1732  call feedkeys('/\_.\%(\uello\)\' .. "\<CR>", 'xt')
1733  call assert_equal([2, 4], [line('.'), col('.')])
1734
1735  set ignorecase& smartcase&
1736  close!
1737endfun
1738
1739" Test 'smartcase' with utf-8.
1740func Test_search_smartcase_utf8()
1741  new
1742  let save_enc = &encoding
1743  set encoding=utf8 ignorecase smartcase
1744
1745  call setline(1, 'Café cafÉ')
1746  1s/café/x/g
1747  call assert_equal('x x', getline(1))
1748
1749  call setline(1, 'Café cafÉ')
1750  1s/cafÉ/x/g
1751  call assert_equal('Café x', getline(1))
1752
1753  set ignorecase& smartcase&
1754  let &encoding = save_enc
1755  close!
1756endfunc
1757
1758" Test searching past the end of a file
1759func Test_search_past_eof()
1760  new
1761  call setline(1, ['Line'])
1762  exe "normal /\\n\\zs\<CR>"
1763  call assert_equal([1, 4], [line('.'), col('.')])
1764  close!
1765endfunc
1766
1767" Test for various search offsets
1768func Test_search_offset()
1769  " With /e, for a match in the first column of a line, the cursor should be
1770  " placed at the end of the previous line.
1771  new
1772  call setline(1, ['one two', 'three four'])
1773  call search('two\_.', 'e')
1774  call assert_equal([1, 7], [line('.'), col('.')])
1775
1776  " with cursor at the beginning of the file, use /s+1
1777  call cursor(1, 1)
1778  exe "normal /two/s+1\<CR>"
1779  call assert_equal([1, 6], [line('.'), col('.')])
1780
1781  " with cursor at the end of the file, use /e-1
1782  call cursor(2, 10)
1783  exe "normal ?three?e-1\<CR>"
1784  call assert_equal([2, 4], [line('.'), col('.')])
1785
1786  " line offset - after the last line
1787  call cursor(1, 1)
1788  exe "normal /three/+1\<CR>"
1789  call assert_equal([2, 1], [line('.'), col('.')])
1790
1791  " line offset - before the first line
1792  call cursor(2, 1)
1793  exe "normal ?one?-1\<CR>"
1794  call assert_equal([1, 1], [line('.'), col('.')])
1795
1796  " character offset - before the first character in the file
1797  call cursor(2, 1)
1798  exe "normal ?one?s-1\<CR>"
1799  call assert_equal([1, 1], [line('.'), col('.')])
1800  call cursor(2, 1)
1801  exe "normal ?one?e-3\<CR>"
1802  call assert_equal([1, 1], [line('.'), col('.')])
1803
1804  " character offset - after the last character in the file
1805  call cursor(1, 1)
1806  exe "normal /four/s+4\<CR>"
1807  call assert_equal([2, 10], [line('.'), col('.')])
1808  call cursor(1, 1)
1809  exe "normal /four/e+1\<CR>"
1810  call assert_equal([2, 10], [line('.'), col('.')])
1811
1812  close!
1813endfunc
1814
1815" Test for searching for matching parenthesis using %
1816func Test_search_match_paren()
1817  new
1818  call setline(1, "abc(def')'ghi'('jk'\\t'lm)no")
1819  " searching for a matching parenthesis should skip single quoted characters
1820  call cursor(1, 4)
1821  normal %
1822  call assert_equal([1, 25], [line('.'), col('.')])
1823  normal %
1824  call assert_equal([1, 4], [line('.'), col('.')])
1825  call cursor(1, 5)
1826  normal ])
1827  call assert_equal([1, 25], [line('.'), col('.')])
1828  call cursor(1, 24)
1829  normal [(
1830  call assert_equal([1, 4], [line('.'), col('.')])
1831
1832  " matching parenthesis in 'virtualedit' mode with cursor after the eol
1833  call setline(1, 'abc(defgh)')
1834  set virtualedit=all
1835  normal 20|%
1836  call assert_equal(4, col('.'))
1837  set virtualedit&
1838  close!
1839endfunc
1840
1841" Test for searching a pattern and stopping before a specified line
1842func Test_search_stopline()
1843  new
1844  call setline(1, ['', '', '', 'vim'])
1845  call assert_equal(0, search('vim', 'n', 3))
1846  call assert_equal(4, search('vim', 'n', 4))
1847  call setline(1, ['vim', '', '', ''])
1848  call cursor(4, 1)
1849  call assert_equal(0, search('vim', 'bn', 2))
1850  call assert_equal(1, search('vim', 'bn', 1))
1851  close!
1852endfunc
1853
1854func Test_incsearch_highlighting_newline()
1855  CheckRunVimInTerminal
1856  CheckOption incsearch
1857  CheckScreendump
1858  new
1859  call test_override("char_avail", 1)
1860
1861  let commands =<< trim [CODE]
1862    set incsearch nohls
1863    call setline(1, ['test', 'xxx'])
1864  [CODE]
1865  call writefile(commands, 'Xincsearch_nl')
1866  let buf = RunVimInTerminal('-S Xincsearch_nl', {'rows': 5, 'cols': 10})
1867  call term_sendkeys(buf, '/test')
1868  call VerifyScreenDump(buf, 'Test_incsearch_newline1', {})
1869  " Need to send one key at a time to force a redraw
1870  call term_sendkeys(buf, '\n')
1871  call VerifyScreenDump(buf, 'Test_incsearch_newline2', {})
1872  call term_sendkeys(buf, 'x')
1873  call VerifyScreenDump(buf, 'Test_incsearch_newline3', {})
1874  call term_sendkeys(buf, 'x')
1875  call VerifyScreenDump(buf, 'Test_incsearch_newline4', {})
1876  call term_sendkeys(buf, "\<CR>")
1877  call VerifyScreenDump(buf, 'Test_incsearch_newline5', {})
1878  call StopVimInTerminal(buf)
1879
1880  " clean up
1881  call delete('Xincsearch_nl')
1882  call test_override("char_avail", 0)
1883  bw
1884endfunc
1885
1886func Test_incsearch_substitute_dump2()
1887  CheckOption incsearch
1888  CheckScreendump
1889
1890  call writefile([
1891	\ 'set incsearch hlsearch scrolloff=0',
1892	\ 'for n in range(1, 4)',
1893	\ '  call setline(n, "foo " . n)',
1894	\ 'endfor',
1895	\ 'call setline(5, "abc|def")',
1896	\ '3',
1897	\ ], 'Xis_subst_script2')
1898  let buf = RunVimInTerminal('-S Xis_subst_script2', {'rows': 9, 'cols': 70})
1899
1900  call term_sendkeys(buf, ':%s/\vabc|')
1901  sleep 100m
1902  call VerifyScreenDump(buf, 'Test_incsearch_sub_01', {})
1903  call term_sendkeys(buf, "\<Esc>")
1904
1905  " The following should not be highlighted
1906  call term_sendkeys(buf, ':1,5s/\v|')
1907  sleep 100m
1908  call VerifyScreenDump(buf, 'Test_incsearch_sub_02', {})
1909
1910
1911  call StopVimInTerminal(buf)
1912  call delete('Xis_subst_script2')
1913endfunc
1914
1915func Test_pattern_is_uppercase_smartcase()
1916  new
1917  let input=['abc', 'ABC', 'Abc', 'abC']
1918  call setline(1, input)
1919  call cursor(1,1)
1920  " default, matches firstline
1921  %s/abc//g
1922  call assert_equal(['', 'ABC', 'Abc', 'abC'],
1923        \ getline(1, '$'))
1924
1925  set smartcase ignorecase
1926  sil %d
1927  call setline(1, input)
1928  call cursor(1,1)
1929  " with smartcase and incsearch set, matches everything
1930  %s/abc//g
1931  call assert_equal(['', '', '', ''], getline(1, '$'))
1932
1933  sil %d
1934  call setline(1, input)
1935  call cursor(1,1)
1936  " with smartcase and incsearch set and found an uppercase letter,
1937  " match only that.
1938  %s/abC//g
1939  call assert_equal(['abc', 'ABC', 'Abc', ''],
1940        \ getline(1, '$'))
1941
1942  sil %d
1943  call setline(1, input)
1944  call cursor(1,1)
1945  exe "norm! vG$\<esc>"
1946  " \%V should not be detected as uppercase letter
1947  %s/\%Vabc//g
1948  call assert_equal(['', '', '', ''], getline(1, '$'))
1949
1950  call setline(1, input)
1951  call cursor(1,1)
1952  exe "norm! vG$\<esc>"
1953  " \v%V should not be detected as uppercase letter
1954  %s/\v%Vabc//g
1955  call assert_equal(['', '', '', ''], getline(1, '$'))
1956
1957  call setline(1, input)
1958  call cursor(1,1)
1959  exe "norm! vG$\<esc>"
1960  " \v%VabC should be detected as uppercase letter
1961  %s/\v%VabC//g
1962  call assert_equal(['abc', 'ABC', 'Abc', ''],
1963        \ getline(1, '$'))
1964
1965  call setline(1, input)
1966  call cursor(1,1)
1967  " \Vabc should match everything
1968  %s/\Vabc//g
1969  call assert_equal(['', '', '', ''], getline(1, '$'))
1970
1971  call setline(1, input + ['_abc'])
1972  " _ matches normally
1973  %s/\v_.*//g
1974  call assert_equal(['abc', 'ABC', 'Abc', 'abC', ''], getline(1, '$'))
1975
1976  set smartcase& ignorecase&
1977  bw!
1978endfunc
1979
1980func Test_no_last_search_pattern()
1981  CheckOption incsearch
1982
1983  let @/ = ""
1984  set incsearch
1985  " these were causing a crash
1986  call feedkeys("//\<C-G>", 'xt')
1987  call feedkeys("//\<C-T>", 'xt')
1988  call feedkeys("??\<C-G>", 'xt')
1989  call feedkeys("??\<C-T>", 'xt')
1990endfunc
1991
1992func Test_search_with_invalid_range()
1993  new
1994  let lines =<< trim END
1995    /\%.v
1996    5/
1997    c
1998  END
1999  call writefile(lines, 'Xrangesearch')
2000  source Xrangesearch
2001
2002  bwipe!
2003  call delete('Xrangesearch')
2004endfunc
2005
2006
2007" vim: shiftwidth=2 sts=2 expandtab
2008