xref: /vim-8.2.3635/src/testdir/test_search.vim (revision 5be4ceec)
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  " eigth 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  " eigth 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  4
295  let a = searchpair('\[','',']','bW')
296  call assert_equal(3, a)
297  set nomagic
298  4
299  let a = searchpair('\[','',']','bW')
300  call assert_equal(3, a)
301  set magic
302  q!
303endfunc
304
305func Test_searchpair_errors()
306  call assert_fails("call searchpair([0], 'middle', 'end', 'bW', 'skip', 99, 100)", 'E730: using List as a String')
307  call assert_fails("call searchpair('start', {-> 0}, 'end', 'bW', 'skip', 99, 100)", 'E729: using Funcref as a String')
308  call assert_fails("call searchpair('start', 'middle', {'one': 1}, 'bW', 'skip', 99, 100)", 'E731: using Dictionary as a String')
309  call assert_fails("call searchpair('start', 'middle', 'end', 'flags', 'skip', 99, 100)", 'E475: Invalid argument: flags')
310  call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 0, 99, 100)", 'E475: Invalid argument: 0')
311  call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 'func', -99, 100)", 'E475: Invalid argument: -99')
312  call assert_fails("call searchpair('start', 'middle', 'end', 'bW', 'func', 99, -100)", 'E475: Invalid argument: -100')
313endfunc
314
315func Test_searchpair_skip()
316    func Zero()
317	return 0
318    endfunc
319    func Partial(x)
320	return a:x
321    endfunc
322    new
323    call setline(1, ['{', 'foo', 'foo', 'foo', '}'])
324    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', ''))
325    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', '0'))
326    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', {-> 0}))
327    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', function('Zero')))
328    3 | call assert_equal(1, searchpair('{', '', '}', 'bWn', function('Partial', [0])))
329    bw!
330endfunc
331
332func Test_searchpair_leak()
333  new
334  call setline(1, 'if one else another endif')
335
336  " The error in the skip expression caused memory to leak.
337  call assert_fails("call searchpair('\\<if\\>', '\\<else\\>', '\\<endif\\>', '', '\"foo\" 2')", 'E15:')
338
339  bwipe!
340endfunc
341
342func Test_searchc()
343  " These commands used to cause memory overflow in searchc().
344  new
345  norm ixx
346  exe "norm 0t\u93cf"
347  bw!
348endfunc
349
350func Cmdline3_prep()
351  " need to disable char_avail,
352  " so that expansion of commandline works
353  call test_override("char_avail", 1)
354  new
355  call setline(1, ['  1', '  2 the~e', '  3 the theother'])
356  set incsearch
357endfunc
358
359func Incsearch_cleanup()
360  set noincsearch
361  call test_override("char_avail", 0)
362  bw!
363endfunc
364
365func Test_search_cmdline3()
366  if !exists('+incsearch')
367    return
368  endif
369  call Cmdline3_prep()
370  1
371  " first match
372  call feedkeys("/the\<c-l>\<cr>", 'tx')
373  call assert_equal('  2 the~e', getline('.'))
374
375  call Incsearch_cleanup()
376endfunc
377
378func Test_search_cmdline3s()
379  if !exists('+incsearch')
380    return
381  endif
382  call Cmdline3_prep()
383  1
384  call feedkeys(":%s/the\<c-l>/xxx\<cr>", 'tx')
385  call assert_equal('  2 xxxe', getline('.'))
386  undo
387  call feedkeys(":%subs/the\<c-l>/xxx\<cr>", 'tx')
388  call assert_equal('  2 xxxe', getline('.'))
389  undo
390  call feedkeys(":%substitute/the\<c-l>/xxx\<cr>", 'tx')
391  call assert_equal('  2 xxxe', getline('.'))
392  undo
393  call feedkeys(":%smagic/the.e/xxx\<cr>", 'tx')
394  call assert_equal('  2 xxx', getline('.'))
395  undo
396  call assert_fails(":%snomagic/the.e/xxx\<cr>", 'E486')
397  "
398  call feedkeys(":%snomagic/the\\.e/xxx\<cr>", 'tx')
399  call assert_equal('  2 xxx', getline('.'))
400
401  call Incsearch_cleanup()
402endfunc
403
404func Test_search_cmdline3g()
405  if !exists('+incsearch')
406    return
407  endif
408  call Cmdline3_prep()
409  1
410  call feedkeys(":g/the\<c-l>/d\<cr>", 'tx')
411  call assert_equal('  3 the theother', getline(2))
412  undo
413  call feedkeys(":global/the\<c-l>/d\<cr>", 'tx')
414  call assert_equal('  3 the theother', getline(2))
415  undo
416  call feedkeys(":g!/the\<c-l>/d\<cr>", 'tx')
417  call assert_equal(1, line('$'))
418  call assert_equal('  2 the~e', getline(1))
419  undo
420  call feedkeys(":global!/the\<c-l>/d\<cr>", 'tx')
421  call assert_equal(1, line('$'))
422  call assert_equal('  2 the~e', getline(1))
423
424  call Incsearch_cleanup()
425endfunc
426
427func Test_search_cmdline3v()
428  if !exists('+incsearch')
429    return
430  endif
431  call Cmdline3_prep()
432  1
433  call feedkeys(":v/the\<c-l>/d\<cr>", 'tx')
434  call assert_equal(1, line('$'))
435  call assert_equal('  2 the~e', getline(1))
436  undo
437  call feedkeys(":vglobal/the\<c-l>/d\<cr>", 'tx')
438  call assert_equal(1, line('$'))
439  call assert_equal('  2 the~e', getline(1))
440
441  call Incsearch_cleanup()
442endfunc
443
444func Test_search_cmdline4()
445  if !exists('+incsearch')
446    return
447  endif
448  " need to disable char_avail,
449  " so that expansion of commandline works
450  call test_override("char_avail", 1)
451  new
452  call setline(1, ['  1 the first', '  2 the second', '  3 the third'])
453  set incsearch
454  $
455  call feedkeys("?the\<c-g>\<cr>", 'tx')
456  call assert_equal('  3 the third', getline('.'))
457  $
458  call feedkeys("?the\<c-g>\<c-g>\<cr>", 'tx')
459  call assert_equal('  1 the first', getline('.'))
460  $
461  call feedkeys("?the\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
462  call assert_equal('  2 the second', getline('.'))
463  $
464  call feedkeys("?the\<c-t>\<cr>", 'tx')
465  call assert_equal('  1 the first', getline('.'))
466  $
467  call feedkeys("?the\<c-t>\<c-t>\<cr>", 'tx')
468  call assert_equal('  3 the third', getline('.'))
469  $
470  call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx')
471  call assert_equal('  2 the second', getline('.'))
472  " clean up
473  set noincsearch
474  call test_override("char_avail", 0)
475  bw!
476endfunc
477
478func Test_search_cmdline5()
479  if !exists('+incsearch')
480    return
481  endif
482  " Do not call test_override("char_avail", 1) so that <C-g> and <C-t> work
483  " regardless char_avail.
484  new
485  call setline(1, ['  1 the first', '  2 the second', '  3 the third', ''])
486  set incsearch
487  1
488  call feedkeys("/the\<c-g>\<c-g>\<cr>", 'tx')
489  call assert_equal('  3 the third', getline('.'))
490  $
491  call feedkeys("?the\<c-t>\<c-t>\<c-t>\<cr>", 'tx')
492  call assert_equal('  1 the first', getline('.'))
493  " clean up
494  set noincsearch
495  bw!
496endfunc
497
498func Test_search_cmdline6()
499  " Test that consecutive matches
500  " are caught by <c-g>/<c-t>
501  if !exists('+incsearch')
502    return
503  endif
504  " need to disable char_avail,
505  " so that expansion of commandline works
506  call test_override("char_avail", 1)
507  new
508  call setline(1, [' bbvimb', ''])
509  set incsearch
510  " first match
511  norm! gg0
512  call feedkeys("/b\<cr>", 'tx')
513  call assert_equal([0,1,2,0], getpos('.'))
514  " second match
515  norm! gg0
516  call feedkeys("/b\<c-g>\<cr>", 'tx')
517  call assert_equal([0,1,3,0], getpos('.'))
518  " third match
519  norm! gg0
520  call feedkeys("/b\<c-g>\<c-g>\<cr>", 'tx')
521  call assert_equal([0,1,7,0], getpos('.'))
522  " first match again
523  norm! gg0
524  call feedkeys("/b\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
525  call assert_equal([0,1,2,0], getpos('.'))
526  set nowrapscan
527  " last match
528  norm! gg0
529  call feedkeys("/b\<c-g>\<c-g>\<c-g>\<cr>", 'tx')
530  call assert_equal([0,1,7,0], getpos('.'))
531  " clean up
532  set wrapscan&vim
533  set noincsearch
534  call test_override("char_avail", 0)
535  bw!
536endfunc
537
538func Test_search_cmdline7()
539  " Test that an pressing <c-g> in an empty command line
540  " does not move the cursor
541  if !exists('+incsearch')
542    return
543  endif
544  " need to disable char_avail,
545  " so that expansion of commandline works
546  call test_override("char_avail", 1)
547  new
548  let @/ = 'b'
549  call setline(1, [' bbvimb', ''])
550  set incsearch
551  " first match
552  norm! gg0
553  " moves to next match of previous search pattern, just like /<cr>
554  call feedkeys("/\<c-g>\<cr>", 'tx')
555  call assert_equal([0,1,2,0], getpos('.'))
556  " moves to next match of previous search pattern, just like /<cr>
557  call feedkeys("/\<cr>", 'tx')
558  call assert_equal([0,1,3,0], getpos('.'))
559  " moves to next match of previous search pattern, just like /<cr>
560  call feedkeys("/\<c-t>\<cr>", 'tx')
561  call assert_equal([0,1,7,0], getpos('.'))
562
563  " using an offset uses the last search pattern
564  call cursor(1, 1)
565  call setline(1, ['1 bbvimb', ' 2 bbvimb'])
566  let @/ = 'b'
567  call feedkeys("//e\<c-g>\<cr>", 'tx')
568  call assert_equal('1 bbvimb', getline('.'))
569  call assert_equal(4, col('.'))
570
571  set noincsearch
572  call test_override("char_avail", 0)
573  bw!
574endfunc
575
576func Test_search_cmdline8()
577  " Highlighting is cleared in all windows
578  " since hls applies to all windows
579  CheckOption incsearch
580  CheckFeature terminal
581  CheckNotGui
582  if has("win32")
583    throw "Skipped: Bug with sending <ESC> to terminal window not fixed yet"
584  endif
585
586  let h = winheight(0)
587  if h < 3
588    return
589  endif
590  " Prepare buffer text
591  let lines = ['abb vim vim vi', 'vimvivim']
592  call writefile(lines, 'Xsearch.txt')
593  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', 'Xsearch.txt'], {'term_rows': 3})
594
595  call WaitForAssert({-> assert_equal(lines, [term_getline(buf, 1), term_getline(buf, 2)])})
596
597  call term_sendkeys(buf, ":set incsearch hlsearch\<cr>")
598  call term_sendkeys(buf, ":14vsp\<cr>")
599  call term_sendkeys(buf, "/vim\<cr>")
600  call term_sendkeys(buf, "/b\<esc>")
601  call term_sendkeys(buf, "gg0")
602  call term_wait(buf, 500)
603  let screen_line = term_scrape(buf, 1)
604  let [a0,a1,a2,a3] = [screen_line[3].attr, screen_line[4].attr,
605        \ screen_line[18].attr, screen_line[19].attr]
606  call assert_notequal(a0, a1)
607  call assert_notequal(a0, a3)
608  call assert_notequal(a1, a2)
609  call assert_equal(a0, a2)
610  call assert_equal(a1, a3)
611  " clean up
612  call delete('Xsearch.txt')
613
614  bwipe!
615endfunc
616
617" Tests for regexp with various magic settings
618func Test_search_regexp()
619  enew!
620
621  put ='1 a aa abb abbccc'
622  exe 'normal! /a*b\{2}c\+/e' . "\<CR>"
623  call assert_equal([0, 2, 17, 0], getpos('.'))
624
625  put ='2 d dd dee deefff'
626  exe 'normal! /\Md\*e\{2}f\+/e' . "\<CR>"
627  call assert_equal([0, 3, 17, 0], getpos('.'))
628
629  set nomagic
630  put ='3 g gg ghh ghhiii'
631  exe 'normal! /g\*h\{2}i\+/e' . "\<CR>"
632  call assert_equal([0, 4, 17, 0], getpos('.'))
633
634  put ='4 j jj jkk jkklll'
635  exe 'normal! /\mj*k\{2}l\+/e' . "\<CR>"
636  call assert_equal([0, 5, 17, 0], getpos('.'))
637
638  put ='5 m mm mnn mnnooo'
639  exe 'normal! /\vm*n{2}o+/e' . "\<CR>"
640  call assert_equal([0, 6, 17, 0], getpos('.'))
641
642  put ='6 x ^aa$ x'
643  exe 'normal! /\V^aa$' . "\<CR>"
644  call assert_equal([0, 7, 5, 0], getpos('.'))
645
646  set magic
647  put ='7 (a)(b) abbaa'
648  exe 'normal! /\v(a)(b)\2\1\1/e' . "\<CR>"
649  call assert_equal([0, 8, 14, 0], getpos('.'))
650
651  put ='8 axx [ab]xx'
652  exe 'normal! /\V[ab]\(\[xy]\)\1' . "\<CR>"
653  call assert_equal([0, 9, 7, 0], getpos('.'))
654
655  set undolevels=100
656  put ='9 foobar'
657  put =''
658  exe "normal! a\<C-G>u\<Esc>"
659  normal G
660  exe 'normal! dv?bar?' . "\<CR>"
661  call assert_equal('9 foo', getline('.'))
662  call assert_equal([0, 10, 5, 0], getpos('.'))
663  call assert_equal(10, line('$'))
664  normal u
665  call assert_equal('9 foobar', getline('.'))
666  call assert_equal([0, 10, 6, 0], getpos('.'))
667  call assert_equal(11, line('$'))
668
669  set undolevels&
670  enew!
671endfunc
672
673func Test_search_cmdline_incsearch_highlight()
674  if !exists('+incsearch')
675    return
676  endif
677  set incsearch hlsearch
678  " need to disable char_avail,
679  " so that expansion of commandline works
680  call test_override("char_avail", 1)
681  new
682  call setline(1, ['aaa  1 the first', '  2 the second', '  3 the third'])
683
684  1
685  call feedkeys("/second\<cr>", 'tx')
686  call assert_equal('second', @/)
687  call assert_equal('  2 the second', getline('.'))
688
689  " Canceling search won't change @/
690  1
691  let @/ = 'last pattern'
692  call feedkeys("/third\<C-c>", 'tx')
693  call assert_equal('last pattern', @/)
694  call feedkeys("/third\<Esc>", 'tx')
695  call assert_equal('last pattern', @/)
696  call feedkeys("/3\<bs>\<bs>", 'tx')
697  call assert_equal('last pattern', @/)
698  call feedkeys("/third\<c-g>\<c-t>\<Esc>", 'tx')
699  call assert_equal('last pattern', @/)
700
701  " clean up
702  set noincsearch nohlsearch
703  bw!
704endfunc
705
706func Test_search_cmdline_incsearch_highlight_attr()
707  CheckOption incsearch
708  CheckFeature terminal
709  CheckNotGui
710
711  let h = winheight(0)
712  if h < 3
713    return
714  endif
715
716  " Prepare buffer text
717  let lines = ['abb vim vim vi', 'vimvivim']
718  call writefile(lines, 'Xsearch.txt')
719  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile', 'Xsearch.txt'], {'term_rows': 3})
720
721  call WaitForAssert({-> assert_equal(lines, [term_getline(buf, 1), term_getline(buf, 2)])})
722  " wait for vim to complete initialization
723  call term_wait(buf)
724
725  " Get attr of normal(a0), incsearch(a1), hlsearch(a2) highlight
726  call term_sendkeys(buf, ":set incsearch hlsearch\<cr>")
727  call term_sendkeys(buf, '/b')
728  call term_wait(buf, 200)
729  let screen_line1 = term_scrape(buf, 1)
730  call assert_true(len(screen_line1) > 2)
731  " a0: attr_normal
732  let a0 = screen_line1[0].attr
733  " a1: attr_incsearch
734  let a1 = screen_line1[1].attr
735  " a2: attr_hlsearch
736  let a2 = screen_line1[2].attr
737  call assert_notequal(a0, a1)
738  call assert_notequal(a0, a2)
739  call assert_notequal(a1, a2)
740  call term_sendkeys(buf, "\<cr>gg0")
741
742  " Test incremental highlight search
743  call term_sendkeys(buf, "/vim")
744  call term_wait(buf, 200)
745  " Buffer:
746  " abb vim vim vi
747  " vimvivim
748  " Search: /vim
749  let attr_line1 = [a0,a0,a0,a0,a1,a1,a1,a0,a2,a2,a2,a0,a0,a0]
750  let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2]
751  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
752  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
753
754  " Test <C-g>
755  call term_sendkeys(buf, "\<C-g>\<C-g>")
756  call term_wait(buf, 200)
757  let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a2,a2,a2,a0,a0,a0]
758  let attr_line2 = [a1,a1,a1,a0,a0,a2,a2,a2]
759  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
760  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
761
762  " Test <C-t>
763  call term_sendkeys(buf, "\<C-t>")
764  call term_wait(buf, 200)
765  let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a1,a1,a1,a0,a0,a0]
766  let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2]
767  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
768  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
769
770  " Type Enter and a1(incsearch highlight) should become a2(hlsearch highlight)
771  call term_sendkeys(buf, "\<cr>")
772  call term_wait(buf, 200)
773  let attr_line1 = [a0,a0,a0,a0,a2,a2,a2,a0,a2,a2,a2,a0,a0,a0]
774  let attr_line2 = [a2,a2,a2,a0,a0,a2,a2,a2]
775  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
776  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
777
778  " Test nohlsearch. a2(hlsearch highlight) should become a0(normal highlight)
779  call term_sendkeys(buf, ":1\<cr>")
780  call term_sendkeys(buf, ":set nohlsearch\<cr>")
781  call term_sendkeys(buf, "/vim")
782  call term_wait(buf, 200)
783  let attr_line1 = [a0,a0,a0,a0,a1,a1,a1,a0,a0,a0,a0,a0,a0,a0]
784  let attr_line2 = [a0,a0,a0,a0,a0,a0,a0,a0]
785  call assert_equal(attr_line1, map(term_scrape(buf, 1)[:len(attr_line1)-1], 'v:val.attr'))
786  call assert_equal(attr_line2, map(term_scrape(buf, 2)[:len(attr_line2)-1], 'v:val.attr'))
787  call delete('Xsearch.txt')
788
789  call delete('Xsearch.txt')
790  bwipe!
791endfunc
792
793func Test_incsearch_cmdline_modifier()
794  if !exists('+incsearch')
795    return
796  endif
797  call test_override("char_avail", 1)
798  new
799  call setline(1, ['foo'])
800  set incsearch
801  " Test that error E14 does not occur in parsing command modifier.
802  call feedkeys("V:tab", 'tx')
803
804  call Incsearch_cleanup()
805endfunc
806
807func Test_incsearch_scrolling()
808  if !CanRunVimInTerminal()
809    throw 'Skipped: cannot make screendumps'
810  endif
811  call assert_equal(0, &scrolloff)
812  call writefile([
813	\ 'let dots = repeat(".", 120)',
814	\ 'set incsearch cmdheight=2 scrolloff=0',
815	\ 'call setline(1, [dots, dots, dots, "", "target", dots, dots])',
816	\ 'normal gg',
817	\ 'redraw',
818	\ ], 'Xscript')
819  let buf = RunVimInTerminal('-S Xscript', {'rows': 9, 'cols': 70})
820  " Need to send one key at a time to force a redraw
821  call term_sendkeys(buf, '/')
822  sleep 100m
823  call term_sendkeys(buf, 't')
824  sleep 100m
825  call term_sendkeys(buf, 'a')
826  sleep 100m
827  call term_sendkeys(buf, 'r')
828  sleep 100m
829  call term_sendkeys(buf, 'g')
830  call VerifyScreenDump(buf, 'Test_incsearch_scrolling_01', {})
831
832  call term_sendkeys(buf, "\<Esc>")
833  call StopVimInTerminal(buf)
834  call delete('Xscript')
835endfunc
836
837func Test_incsearch_search_dump()
838  if !exists('+incsearch')
839    return
840  endif
841  if !CanRunVimInTerminal()
842    throw 'Skipped: cannot make screendumps'
843  endif
844  call writefile([
845	\ 'set incsearch hlsearch scrolloff=0',
846	\ 'for n in range(1, 8)',
847	\ '  call setline(n, "foo " . n)',
848	\ 'endfor',
849	\ '3',
850	\ ], 'Xis_search_script')
851  let buf = RunVimInTerminal('-S Xis_search_script', {'rows': 9, 'cols': 70})
852  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
853  " the 'ambiwidth' check.
854  sleep 100m
855
856  " Need to send one key at a time to force a redraw.
857  call term_sendkeys(buf, '/fo')
858  call VerifyScreenDump(buf, 'Test_incsearch_search_01', {})
859  call term_sendkeys(buf, "\<Esc>")
860  sleep 100m
861
862  call term_sendkeys(buf, '/\v')
863  call VerifyScreenDump(buf, 'Test_incsearch_search_02', {})
864  call term_sendkeys(buf, "\<Esc>")
865
866  call StopVimInTerminal(buf)
867  call delete('Xis_search_script')
868endfunc
869
870func Test_incsearch_substitute()
871  if !exists('+incsearch')
872    return
873  endif
874  call test_override("char_avail", 1)
875  new
876  set incsearch
877  for n in range(1, 10)
878    call setline(n, 'foo ' . n)
879  endfor
880  4
881  call feedkeys(":.,.+2s/foo\<BS>o\<BS>o/xxx\<cr>", 'tx')
882  call assert_equal('foo 3', getline(3))
883  call assert_equal('xxx 4', getline(4))
884  call assert_equal('xxx 5', getline(5))
885  call assert_equal('xxx 6', getline(6))
886  call assert_equal('foo 7', getline(7))
887
888  call Incsearch_cleanup()
889endfunc
890
891" Similar to Test_incsearch_substitute() but with a screendump halfway.
892func Test_incsearch_substitute_dump()
893  if !exists('+incsearch')
894    return
895  endif
896  if !CanRunVimInTerminal()
897    throw 'Skipped: cannot make screendumps'
898  endif
899  call writefile([
900	\ 'set incsearch hlsearch scrolloff=0',
901	\ 'for n in range(1, 10)',
902	\ '  call setline(n, "foo " . n)',
903	\ 'endfor',
904	\ 'call setline(11, "bar 11")',
905	\ '3',
906	\ ], 'Xis_subst_script')
907  let buf = RunVimInTerminal('-S Xis_subst_script', {'rows': 9, 'cols': 70})
908  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
909  " the 'ambiwidth' check.
910  sleep 100m
911
912  " Need to send one key at a time to force a redraw.
913  " Select three lines at the cursor with typed pattern.
914  call term_sendkeys(buf, ':.,.+2s/')
915  sleep 100m
916  call term_sendkeys(buf, 'f')
917  sleep 100m
918  call term_sendkeys(buf, 'o')
919  sleep 100m
920  call term_sendkeys(buf, 'o')
921  call VerifyScreenDump(buf, 'Test_incsearch_substitute_01', {})
922  call term_sendkeys(buf, "\<Esc>")
923
924  " Select three lines at the cursor using previous pattern.
925  call term_sendkeys(buf, "/foo\<CR>")
926  sleep 100m
927  call term_sendkeys(buf, ':.,.+2s//')
928  call VerifyScreenDump(buf, 'Test_incsearch_substitute_02', {})
929
930  " Deleting last slash should remove the match.
931  call term_sendkeys(buf, "\<BS>")
932  call VerifyScreenDump(buf, 'Test_incsearch_substitute_03', {})
933  call term_sendkeys(buf, "\<Esc>")
934
935  " Reverse range is accepted
936  call term_sendkeys(buf, ':5,2s/foo')
937  call VerifyScreenDump(buf, 'Test_incsearch_substitute_04', {})
938  call term_sendkeys(buf, "\<Esc>")
939
940  " White space after the command is skipped
941  call term_sendkeys(buf, ':2,3sub  /fo')
942  call VerifyScreenDump(buf, 'Test_incsearch_substitute_05', {})
943  call term_sendkeys(buf, "\<Esc>")
944
945  " Command modifiers are skipped
946  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.')
947  call VerifyScreenDump(buf, 'Test_incsearch_substitute_06', {})
948  call term_sendkeys(buf, "\<Esc>")
949
950  " Cursorline highlighting at match
951  call term_sendkeys(buf, ":set cursorline\<CR>")
952  call term_sendkeys(buf, 'G9G')
953  call term_sendkeys(buf, ':9,11s/bar')
954  call VerifyScreenDump(buf, 'Test_incsearch_substitute_07', {})
955  call term_sendkeys(buf, "\<Esc>")
956
957  " Cursorline highlighting at cursor when no match
958  call term_sendkeys(buf, ':9,10s/bar')
959  call VerifyScreenDump(buf, 'Test_incsearch_substitute_08', {})
960  call term_sendkeys(buf, "\<Esc>")
961
962  " Only \v handled as empty pattern, does not move cursor
963  call term_sendkeys(buf, '3G4G')
964  call term_sendkeys(buf, ":nohlsearch\<CR>")
965  call term_sendkeys(buf, ':6,7s/\v')
966  call VerifyScreenDump(buf, 'Test_incsearch_substitute_09', {})
967  call term_sendkeys(buf, "\<Esc>")
968
969  call term_sendkeys(buf, ":set nocursorline\<CR>")
970
971  " All matches are highlighted for 'hlsearch' after the incsearch canceled
972  call term_sendkeys(buf, "1G*")
973  call term_sendkeys(buf, ":2,5s/foo")
974  sleep 100m
975  call term_sendkeys(buf, "\<Esc>")
976  call VerifyScreenDump(buf, 'Test_incsearch_substitute_10', {})
977
978  call term_sendkeys(buf, ":split\<CR>")
979  call term_sendkeys(buf, ":let @/ = 'xyz'\<CR>")
980  call term_sendkeys(buf, ":%s/.")
981  call VerifyScreenDump(buf, 'Test_incsearch_substitute_11', {})
982  call term_sendkeys(buf, "\<BS>")
983  call VerifyScreenDump(buf, 'Test_incsearch_substitute_12', {})
984  call term_sendkeys(buf, "\<Esc>")
985  call VerifyScreenDump(buf, 'Test_incsearch_substitute_13', {})
986
987  call StopVimInTerminal(buf)
988  call delete('Xis_subst_script')
989endfunc
990
991func Test_incsearch_with_change()
992  if !has('timers') || !exists('+incsearch') || !CanRunVimInTerminal()
993    throw 'Skipped: cannot make screendumps and/or timers feature and/or incsearch option missing'
994  endif
995
996  call writefile([
997	\ 'set incsearch hlsearch scrolloff=0',
998	\ 'call setline(1, ["one", "two ------ X", "three"])',
999	\ 'call timer_start(200, { _ -> setline(2, "x")})',
1000	\ ], 'Xis_change_script')
1001  let buf = RunVimInTerminal('-S Xis_change_script', {'rows': 9, 'cols': 70})
1002  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1003  " the 'ambiwidth' check.
1004  sleep 300m
1005
1006  " Highlight X, it will be deleted by the timer callback.
1007  call term_sendkeys(buf, ':%s/X')
1008  call VerifyScreenDump(buf, 'Test_incsearch_change_01', {})
1009  call term_sendkeys(buf, "\<Esc>")
1010
1011  call StopVimInTerminal(buf)
1012  call delete('Xis_change_script')
1013endfunc
1014
1015" Similar to Test_incsearch_substitute_dump() for :sort
1016func Test_incsearch_sort_dump()
1017  if !exists('+incsearch')
1018    return
1019  endif
1020  if !CanRunVimInTerminal()
1021    throw 'Skipped: cannot make screendumps'
1022  endif
1023  call writefile([
1024	\ 'set incsearch hlsearch scrolloff=0',
1025	\ 'call setline(1, ["another one 2", "that one 3", "the one 1"])',
1026	\ ], 'Xis_sort_script')
1027  let buf = RunVimInTerminal('-S Xis_sort_script', {'rows': 9, 'cols': 70})
1028  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1029  " the 'ambiwidth' check.
1030  sleep 100m
1031
1032  " Need to send one key at a time to force a redraw.
1033  call term_sendkeys(buf, ':sort ni u /on')
1034  call VerifyScreenDump(buf, 'Test_incsearch_sort_01', {})
1035  call term_sendkeys(buf, "\<Esc>")
1036
1037  call StopVimInTerminal(buf)
1038  call delete('Xis_sort_script')
1039endfunc
1040
1041" Similar to Test_incsearch_substitute_dump() for :vimgrep famiry
1042func Test_incsearch_vimgrep_dump()
1043  if !exists('+incsearch')
1044    return
1045  endif
1046  if !CanRunVimInTerminal()
1047    throw 'Skipped: cannot make screendumps'
1048  endif
1049  call writefile([
1050	\ 'set incsearch hlsearch scrolloff=0',
1051	\ 'call setline(1, ["another one 2", "that one 3", "the one 1"])',
1052	\ ], 'Xis_vimgrep_script')
1053  let buf = RunVimInTerminal('-S Xis_vimgrep_script', {'rows': 9, 'cols': 70})
1054  " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by
1055  " the 'ambiwidth' check.
1056  sleep 100m
1057
1058  " Need to send one key at a time to force a redraw.
1059  call term_sendkeys(buf, ':vimgrep on')
1060  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_01', {})
1061  call term_sendkeys(buf, "\<Esc>")
1062
1063  call term_sendkeys(buf, ':vimg /on/ *.txt')
1064  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_02', {})
1065  call term_sendkeys(buf, "\<Esc>")
1066
1067  call term_sendkeys(buf, ':vimgrepadd "\<on')
1068  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_03', {})
1069  call term_sendkeys(buf, "\<Esc>")
1070
1071  call term_sendkeys(buf, ':lv "tha')
1072  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_04', {})
1073  call term_sendkeys(buf, "\<Esc>")
1074
1075  call term_sendkeys(buf, ':lvimgrepa "the" **/*.txt')
1076  call VerifyScreenDump(buf, 'Test_incsearch_vimgrep_05', {})
1077  call term_sendkeys(buf, "\<Esc>")
1078
1079  call StopVimInTerminal(buf)
1080  call delete('Xis_vimgrep_script')
1081endfunc
1082
1083func Test_keep_last_search_pattern()
1084  if !exists('+incsearch')
1085    return
1086  endif
1087  new
1088  call setline(1, ['foo', 'foo', 'foo'])
1089  set incsearch
1090  call test_override("char_avail", 1)
1091  let @/ = 'bar'
1092  call feedkeys(":/foo/s//\<Esc>", 'ntx')
1093  call assert_equal('bar', @/)
1094
1095  " no error message if pattern not found
1096  call feedkeys(":/xyz/s//\<Esc>", 'ntx')
1097  call assert_equal('bar', @/)
1098
1099  bwipe!
1100  call test_override("ALL", 0)
1101  set noincsearch
1102endfunc
1103
1104func Test_word_under_cursor_after_match()
1105  if !exists('+incsearch')
1106    return
1107  endif
1108  new
1109  call setline(1, 'foo bar')
1110  set incsearch
1111  call test_override("char_avail", 1)
1112  try
1113    call feedkeys("/foo\<C-R>\<C-W>\<CR>", 'ntx')
1114  catch /E486:/
1115  endtry
1116  call assert_equal('foobar', @/)
1117
1118  bwipe!
1119  call test_override("ALL", 0)
1120  set noincsearch
1121endfunc
1122
1123func Test_subst_word_under_cursor()
1124  if !exists('+incsearch')
1125    return
1126  endif
1127  new
1128  call setline(1, ['int SomeLongName;', 'for (xxx = 1; xxx < len; ++xxx)'])
1129  set incsearch
1130  call test_override("char_avail", 1)
1131  call feedkeys("/LongName\<CR>", 'ntx')
1132  call feedkeys(":%s/xxx/\<C-R>\<C-W>/g\<CR>", 'ntx')
1133  call assert_equal('for (SomeLongName = 1; SomeLongName < len; ++SomeLongName)', getline(2))
1134
1135  bwipe!
1136  call test_override("ALL", 0)
1137  set noincsearch
1138endfunc
1139
1140func Test_search_undefined_behaviour()
1141  if !has("terminal")
1142    return
1143  endif
1144  let h = winheight(0)
1145  if h < 3
1146    return
1147  endif
1148  " did cause an undefined left shift
1149  let g:buf = term_start([GetVimProg(), '--clean', '-e', '-s', '-c', 'call search(getline("."))', 'samples/test000'], {'term_rows': 3})
1150  call assert_equal([''], getline(1, '$'))
1151  call term_sendkeys(g:buf, ":qa!\<cr>")
1152  bwipe!
1153endfunc
1154
1155func Test_search_undefined_behaviour2()
1156  call search("\%UC0000000")
1157endfunc
1158
1159" Test for search('multi-byte char', 'bce')
1160func Test_search_multibyte()
1161  let save_enc = &encoding
1162  set encoding=utf8
1163  enew!
1164  call append('$', 'A')
1165  call cursor(2, 1)
1166  call assert_equal(2, search('A', 'bce', line('.')))
1167  enew!
1168  let &encoding = save_enc
1169endfunc
1170
1171" This was causing E874.  Also causes an invalid read?
1172func Test_look_behind()
1173  new
1174  call setline(1, '0\|\&\n\@<=')
1175  call search(getline("."))
1176  bwipe!
1177endfunc
1178
1179func Test_search_sentence()
1180  new
1181  " this used to cause a crash
1182  call assert_fails("/\\%')", 'E486')
1183  call assert_fails("/", 'E486')
1184  /\%'(
1185  /
1186endfunc
1187
1188" Test that there is no crash when there is a last search pattern but no last
1189" substitute pattern.
1190func Test_no_last_substitute_pat()
1191  " Use viminfo to set the last search pattern to a string and make the last
1192  " substitute pattern the most recent used and make it empty (NULL).
1193  call writefile(['~MSle0/bar', '~MSle0~&'], 'Xviminfo')
1194  rviminfo! Xviminfo
1195  call assert_fails('normal n', 'E35:')
1196
1197  call delete('Xviminfo')
1198endfunc
1199
1200func Test_search_Ctrl_L_combining()
1201  " Make sure, that Ctrl-L works correctly with combining characters.
1202  " It uses an artificial example of an 'a' with 4 combining chars:
1203    " 'a' U+0061 Dec:97 LATIN SMALL LETTER A &#x61; /\%u61\Z "\u0061"
1204    " ' ̀' U+0300 Dec:768 COMBINING GRAVE ACCENT &#x300; /\%u300\Z "\u0300"
1205    " ' ́' U+0301 Dec:769 COMBINING ACUTE ACCENT &#x301; /\%u301\Z "\u0301"
1206    " ' ̇' U+0307 Dec:775 COMBINING DOT ABOVE &#x307; /\%u307\Z "\u0307"
1207    " ' ̣' U+0323 Dec:803 COMBINING DOT BELOW &#x323; /\%u323 "\u0323"
1208  " Those should also appear on the commandline
1209  if !exists('+incsearch')
1210    return
1211  endif
1212  call Cmdline3_prep()
1213  1
1214  let bufcontent = ['', 'Miạ̀́̇m']
1215  call append('$', bufcontent)
1216  call feedkeys("/Mi\<c-l>\<c-l>\<cr>", 'tx')
1217  call assert_equal(5, line('.'))
1218  call assert_equal(bufcontent[1], @/)
1219  call Incsearch_cleanup()
1220endfunc
1221
1222func Test_large_hex_chars1()
1223  " This used to cause a crash, the character becomes an NFA state.
1224  try
1225    /\%Ufffffc23
1226  catch
1227    call assert_match('E678:', v:exception)
1228  endtry
1229  try
1230    set re=1
1231    /\%Ufffffc23
1232  catch
1233    call assert_match('E678:', v:exception)
1234  endtry
1235  set re&
1236endfunc
1237
1238func Test_large_hex_chars2()
1239  " This used to cause a crash, the character becomes an NFA state.
1240  try
1241    /[\Ufffffc1f]
1242  catch
1243    call assert_match('E486:', v:exception)
1244  endtry
1245  try
1246    set re=1
1247    /[\Ufffffc1f]
1248  catch
1249    call assert_match('E486:', v:exception)
1250  endtry
1251  set re&
1252endfunc
1253
1254func Test_one_error_msg()
1255  " This  was also giving an internal error
1256  call assert_fails('call search(" \\((\\v[[=P=]]){185}+             ")', 'E871:')
1257endfunc
1258
1259func Test_incsearch_add_char_under_cursor()
1260  if !exists('+incsearch')
1261    return
1262  endif
1263  set incsearch
1264  new
1265  call setline(1, ['find match', 'anything'])
1266  1
1267  call test_override('char_avail', 1)
1268  call feedkeys("fc/m\<C-L>\<C-L>\<C-L>\<C-L>\<C-L>\<CR>", 'tx')
1269  call assert_equal('match', @/)
1270  call test_override('char_avail', 0)
1271
1272  set incsearch&
1273  bwipe!
1274endfunc
1275
1276" Test for the search() function with match at the cursor position
1277func Test_search_match_at_curpos()
1278  new
1279  call append(0, ['foobar', '', 'one two', ''])
1280
1281  normal gg
1282
1283  eval 'foobar'->search('c')
1284  call assert_equal([1, 1], [line('.'), col('.')])
1285
1286  normal j
1287  call search('^$', 'c')
1288  call assert_equal([2, 1], [line('.'), col('.')])
1289
1290  call search('^$', 'bc')
1291  call assert_equal([2, 1], [line('.'), col('.')])
1292
1293  exe "normal /two\<CR>"
1294  call search('.', 'c')
1295  call assert_equal([3, 5], [line('.'), col('.')])
1296
1297  close!
1298endfunc
1299
1300func Test_search_display_pattern()
1301  new
1302  call setline(1, ['foo', 'bar', 'foobar'])
1303
1304  call cursor(1, 1)
1305  let @/ = 'foo'
1306  let pat = @/->escape('()*?'. '\s\+')
1307  let g:a = execute(':unsilent :norm! n')
1308  call assert_match(pat, g:a)
1309
1310  " right-left
1311  if exists("+rightleft")
1312    set rl
1313    call cursor(1, 1)
1314    let @/ = 'foo'
1315    let pat = 'oof/\s\+'
1316    let g:a = execute(':unsilent :norm! n')
1317    call assert_match(pat, g:a)
1318    set norl
1319  endif
1320endfunc
1321
1322func Test_searchdecl()
1323  let lines =<< trim END
1324     int global;
1325
1326     func()
1327     {
1328       int global;
1329       if (cond) {
1330	 int local;
1331       }
1332       int local;
1333       // comment
1334     }
1335  END
1336  new
1337  call setline(1, lines)
1338  10
1339  call assert_equal(0, searchdecl('local', 0, 0))
1340  call assert_equal(7, getcurpos()[1])
1341
1342  10
1343  call assert_equal(0, 'local'->searchdecl(0, 1))
1344  call assert_equal(9, getcurpos()[1])
1345
1346  10
1347  call assert_equal(0, searchdecl('global'))
1348  call assert_equal(5, getcurpos()[1])
1349
1350  10
1351  call assert_equal(0, searchdecl('global', 1))
1352  call assert_equal(1, getcurpos()[1])
1353
1354  bwipe!
1355endfunc
1356