Skip to content

Commit c7f08b7

Browse files
committed
patch 8.1.0277: 'incsearch' highlighting wrong in a few cases
Problem: 'incsearch' highlighting wrong in a few cases. Solution: Fix using last search pattern. Restore highlighting when changing command. (issue #3321)
1 parent 164251f commit c7f08b7

5 files changed

Lines changed: 89 additions & 36 deletions

File tree

src/ex_getln.c

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ do_incsearch_highlighting(int firstc, incsearch_state_T *is_state,
300300
{
301301
delim = *p++;
302302
end = skip_regexp(p, delim, p_magic, NULL);
303-
if (end > p)
303+
if (end > p || *end == delim)
304304
{
305305
char_u *dummy;
306306
exarg_T ea;
@@ -341,6 +341,37 @@ do_incsearch_highlighting(int firstc, incsearch_state_T *is_state,
341341
return FALSE;
342342
}
343343

344+
static void
345+
finish_incsearch_highlighting(
346+
int gotesc,
347+
incsearch_state_T *is_state,
348+
int call_update_screen)
349+
{
350+
if (is_state->did_incsearch)
351+
{
352+
is_state->did_incsearch = FALSE;
353+
if (gotesc)
354+
curwin->w_cursor = is_state->save_cursor;
355+
else
356+
{
357+
if (!EQUAL_POS(is_state->save_cursor, is_state->search_start))
358+
{
359+
// put the '" mark at the original position
360+
curwin->w_cursor = is_state->save_cursor;
361+
setpcmark();
362+
}
363+
curwin->w_cursor = is_state->search_start;
364+
}
365+
restore_viewstate(&is_state->old_viewstate);
366+
highlight_match = FALSE;
367+
validate_cursor(); /* needed for TAB */
368+
if (call_update_screen)
369+
update_screen(SOME_VALID);
370+
else
371+
redraw_all_later(SOME_VALID);
372+
}
373+
}
374+
344375
/*
345376
* Do 'incsearch' highlighting if desired.
346377
*/
@@ -357,10 +388,14 @@ may_do_incsearch_highlighting(
357388
#ifdef FEAT_RELTIME
358389
proftime_T tm;
359390
#endif
360-
int c;
391+
int next_char;
392+
int use_last_pat;
361393

362394
if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen))
395+
{
396+
finish_incsearch_highlighting(FALSE, is_state, TRUE);
363397
return;
398+
}
364399

365400
// If there is a character waiting, search and redraw later.
366401
if (char_avail())
@@ -381,8 +416,13 @@ may_do_incsearch_highlighting(
381416
}
382417
save_last_search_pattern();
383418

384-
// If there is no command line, don't do anything.
385-
if (patlen == 0)
419+
// Use the previous pattern for ":s//".
420+
next_char = ccline.cmdbuff[skiplen + patlen];
421+
use_last_pat = patlen == 0 && skiplen > 0
422+
&& ccline.cmdbuff[skiplen - 1] == next_char;
423+
424+
// If there is no pattern, don't do anything.
425+
if (patlen == 0 && !use_last_pat)
386426
{
387427
i = 0;
388428
set_no_hlsearch(TRUE); // turn off previous highlight
@@ -403,7 +443,6 @@ may_do_incsearch_highlighting(
403443
search_flags += SEARCH_KEEP;
404444
if (search_first_line != 0)
405445
search_flags += SEARCH_START;
406-
c = ccline.cmdbuff[skiplen + patlen];
407446
ccline.cmdbuff[skiplen + patlen] = NUL;
408447
i = do_search(NULL, firstc == ':' ? '/' : firstc,
409448
ccline.cmdbuff + skiplen, count, search_flags,
@@ -413,7 +452,7 @@ may_do_incsearch_highlighting(
413452
NULL, NULL
414453
#endif
415454
);
416-
ccline.cmdbuff[skiplen + patlen] = c;
455+
ccline.cmdbuff[skiplen + patlen] = next_char;
417456
--emsg_off;
418457

419458
if (curwin->w_cursor.lnum < search_first_line
@@ -459,11 +498,14 @@ may_do_incsearch_highlighting(
459498

460499
// Disable 'hlsearch' highlighting if the pattern matches everything.
461500
// Avoids a flash when typing "foo\|".
462-
c = ccline.cmdbuff[skiplen + patlen];
463-
ccline.cmdbuff[skiplen + patlen] = NUL;
464-
if (empty_pattern(ccline.cmdbuff))
465-
set_no_hlsearch(TRUE);
466-
ccline.cmdbuff[skiplen + patlen] = c;
501+
if (!use_last_pat)
502+
{
503+
next_char = ccline.cmdbuff[skiplen + patlen];
504+
ccline.cmdbuff[skiplen + patlen] = NUL;
505+
if (empty_pattern(ccline.cmdbuff))
506+
set_no_hlsearch(TRUE);
507+
ccline.cmdbuff[skiplen + patlen] = next_char;
508+
}
467509

468510
validate_cursor();
469511
// May redraw the status line to show the cursor position.
@@ -628,30 +670,6 @@ may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state)
628670
}
629671
return OK;
630672
}
631-
632-
static void
633-
finish_incsearch_highlighting(int gotesc, incsearch_state_T *is_state)
634-
{
635-
if (is_state->did_incsearch)
636-
{
637-
if (gotesc)
638-
curwin->w_cursor = is_state->save_cursor;
639-
else
640-
{
641-
if (!EQUAL_POS(is_state->save_cursor, is_state->search_start))
642-
{
643-
// put the '" mark at the original position
644-
curwin->w_cursor = is_state->save_cursor;
645-
setpcmark();
646-
}
647-
curwin->w_cursor = is_state->search_start;
648-
}
649-
restore_viewstate(&is_state->old_viewstate);
650-
highlight_match = FALSE;
651-
validate_cursor(); /* needed for TAB */
652-
redraw_all_later(SOME_VALID);
653-
}
654-
}
655673
#endif
656674

657675
/*
@@ -2301,7 +2319,7 @@ getcmdline(
23012319
ccline.xpc = NULL;
23022320

23032321
#ifdef FEAT_SEARCH_EXTRA
2304-
finish_incsearch_highlighting(gotesc, &is_state);
2322+
finish_incsearch_highlighting(gotesc, &is_state, FALSE);
23052323
#endif
23062324

23072325
if (ccline.cmdbuff != NULL)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
|f+0&#ffffff0|o@1| |1| @64
2+
|f|o@1| |2| @64
3+
|f|o@1| |3| @64
4+
|f+1&&|o@1| +0&&|4| @64
5+
|f+0&#ffff4012|o@1| +0&#ffffff0|5| @64
6+
|f+0&#ffff4012|o@1| +0&#ffffff0|6| @64
7+
|f|o@1| |7| @64
8+
|f|o@1| |8| @64
9+
|:|.|,|.|+|2|s|/@1> @60
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
|f+0&#ffff4012|o@1| +0&#ffffff0|1| @64
2+
|f+0&#ffff4012|o@1| +0&#ffffff0|2| @64
3+
|f+0&#ffff4012|o@1| +0&#ffffff0|3| @64
4+
|f+0&#ffff4012|o@1| +0&#ffffff0|4| @64
5+
|f+0&#ffff4012|o@1| +0&#ffffff0|5| @64
6+
|f+0&#ffff4012|o@1| +0&#ffffff0|6| @64
7+
|f+0&#ffff4012|o@1| +0&#ffffff0|7| @64
8+
|f+0&#ffff4012|o@1| +0&#ffffff0|8| @64
9+
|:|.|,|.|+|2|s|/> @61

src/testdir/test_search.vim

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,14 +839,29 @@ func Test_incsearch_substitute_dump()
839839
sleep 100m
840840

841841
" Need to send one key at a time to force a redraw.
842+
" Select three lines at the cursor with typed pattern.
842843
call term_sendkeys(buf, ':.,.+2s/')
843844
sleep 100m
844845
call term_sendkeys(buf, 'f')
845846
sleep 100m
846847
call term_sendkeys(buf, 'o')
847848
sleep 100m
848849
call term_sendkeys(buf, 'o')
850+
sleep 100m
849851
call VerifyScreenDump(buf, 'Test_incsearch_substitute_01', {})
852+
call term_sendkeys(buf, "\<Esc>")
853+
854+
" Select three lines at the cursor using previous pattern.
855+
call term_sendkeys(buf, "/foo\<CR>")
856+
sleep 100m
857+
call term_sendkeys(buf, ':.,.+2s//')
858+
sleep 100m
859+
call VerifyScreenDump(buf, 'Test_incsearch_substitute_02', {})
860+
861+
" Deleting last slash should remove the match.
862+
call term_sendkeys(buf, "\<BS>")
863+
sleep 100m
864+
call VerifyScreenDump(buf, 'Test_incsearch_substitute_03', {})
850865

851866
call term_sendkeys(buf, "\<Esc>")
852867
call StopVimInTerminal(buf)

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,8 @@ static char *(features[]) =
794794

795795
static int included_patches[] =
796796
{ /* Add new patch number below this line */
797+
/**/
798+
277,
797799
/**/
798800
276,
799801
/**/

0 commit comments

Comments
 (0)