changeset 14528:58ca11610819 v8.1.0277

patch 8.1.0277: 'incsearch' highlighting wrong in a few cases commit https://github.com/vim/vim/commit/c7f08b7ee1c1ff2080d425c2fcdb6907c26fc98e Author: Bram Moolenaar <Bram@vim.org> Date: Sun Aug 12 17:39:14 2018 +0200 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)
author Christian Brabandt <cb@256bit.org>
date Sun, 12 Aug 2018 17:45:04 +0200
parents 6fc131355f0d
children 957961c9ff99
files src/ex_getln.c src/testdir/dumps/Test_incsearch_substitute_02.dump src/testdir/dumps/Test_incsearch_substitute_03.dump src/testdir/test_search.vim src/version.c
diffstat 5 files changed, 89 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -300,7 +300,7 @@ do_incsearch_highlighting(int firstc, in
 		{
 		    delim = *p++;
 		    end = skip_regexp(p, delim, p_magic, NULL);
-		    if (end > p)
+		    if (end > p || *end == delim)
 		    {
 			char_u  *dummy;
 			exarg_T ea;
@@ -341,6 +341,37 @@ do_incsearch_highlighting(int firstc, in
     return FALSE;
 }
 
+    static void
+finish_incsearch_highlighting(
+	int gotesc,
+	incsearch_state_T *is_state,
+	int call_update_screen)
+{
+    if (is_state->did_incsearch)
+    {
+	is_state->did_incsearch = FALSE;
+	if (gotesc)
+	    curwin->w_cursor = is_state->save_cursor;
+	else
+	{
+	    if (!EQUAL_POS(is_state->save_cursor, is_state->search_start))
+	    {
+		// put the '" mark at the original position
+		curwin->w_cursor = is_state->save_cursor;
+		setpcmark();
+	    }
+	    curwin->w_cursor = is_state->search_start;
+	}
+	restore_viewstate(&is_state->old_viewstate);
+	highlight_match = FALSE;
+	validate_cursor();	/* needed for TAB */
+	if (call_update_screen)
+	    update_screen(SOME_VALID);
+	else
+	    redraw_all_later(SOME_VALID);
+    }
+}
+
 /*
  * Do 'incsearch' highlighting if desired.
  */
@@ -357,10 +388,14 @@ may_do_incsearch_highlighting(
 #ifdef FEAT_RELTIME
     proftime_T	tm;
 #endif
-    int		c;
+    int		next_char;
+    int		use_last_pat;
 
     if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen))
+    {
+	finish_incsearch_highlighting(FALSE, is_state, TRUE);
 	return;
+    }
 
     // If there is a character waiting, search and redraw later.
     if (char_avail())
@@ -381,8 +416,13 @@ may_do_incsearch_highlighting(
     }
     save_last_search_pattern();
 
-    // If there is no command line, don't do anything.
-    if (patlen == 0)
+    // Use the previous pattern for ":s//".
+    next_char = ccline.cmdbuff[skiplen + patlen];
+    use_last_pat = patlen == 0 && skiplen > 0
+				   && ccline.cmdbuff[skiplen - 1] == next_char;
+
+    // If there is no pattern, don't do anything.
+    if (patlen == 0 && !use_last_pat)
     {
 	i = 0;
 	set_no_hlsearch(TRUE); // turn off previous highlight
@@ -403,7 +443,6 @@ may_do_incsearch_highlighting(
 	    search_flags += SEARCH_KEEP;
 	if (search_first_line != 0)
 	    search_flags += SEARCH_START;
-	c = ccline.cmdbuff[skiplen + patlen];
 	ccline.cmdbuff[skiplen + patlen] = NUL;
 	i = do_search(NULL, firstc == ':' ? '/' : firstc,
 				 ccline.cmdbuff + skiplen, count, search_flags,
@@ -413,7 +452,7 @@ may_do_incsearch_highlighting(
 		NULL, NULL
 #endif
 		);
-	ccline.cmdbuff[skiplen + patlen] = c;
+	ccline.cmdbuff[skiplen + patlen] = next_char;
 	--emsg_off;
 
 	if (curwin->w_cursor.lnum < search_first_line
@@ -459,11 +498,14 @@ may_do_incsearch_highlighting(
 
     // Disable 'hlsearch' highlighting if the pattern matches everything.
     // Avoids a flash when typing "foo\|".
-    c = ccline.cmdbuff[skiplen + patlen];
-    ccline.cmdbuff[skiplen + patlen] = NUL;
-    if (empty_pattern(ccline.cmdbuff))
-	set_no_hlsearch(TRUE);
-    ccline.cmdbuff[skiplen + patlen] = c;
+    if (!use_last_pat)
+    {
+	next_char = ccline.cmdbuff[skiplen + patlen];
+	ccline.cmdbuff[skiplen + patlen] = NUL;
+	if (empty_pattern(ccline.cmdbuff))
+	    set_no_hlsearch(TRUE);
+	ccline.cmdbuff[skiplen + patlen] = next_char;
+    }
 
     validate_cursor();
     // May redraw the status line to show the cursor position.
@@ -628,30 +670,6 @@ may_add_char_to_search(int firstc, int *
     }
     return OK;
 }
-
-    static void
-finish_incsearch_highlighting(int gotesc, incsearch_state_T *is_state)
-{
-    if (is_state->did_incsearch)
-    {
-	if (gotesc)
-	    curwin->w_cursor = is_state->save_cursor;
-	else
-	{
-	    if (!EQUAL_POS(is_state->save_cursor, is_state->search_start))
-	    {
-		// put the '" mark at the original position
-		curwin->w_cursor = is_state->save_cursor;
-		setpcmark();
-	    }
-	    curwin->w_cursor = is_state->search_start;
-	}
-	restore_viewstate(&is_state->old_viewstate);
-	highlight_match = FALSE;
-	validate_cursor();	/* needed for TAB */
-	redraw_all_later(SOME_VALID);
-    }
-}
 #endif
 
 /*
@@ -2301,7 +2319,7 @@ returncmd:
     ccline.xpc = NULL;
 
 #ifdef FEAT_SEARCH_EXTRA
-    finish_incsearch_highlighting(gotesc, &is_state);
+    finish_incsearch_highlighting(gotesc, &is_state, FALSE);
 #endif
 
     if (ccline.cmdbuff != NULL)
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_incsearch_substitute_02.dump
@@ -0,0 +1,9 @@
+|f+0&#ffffff0|o@1| |1| @64
+|f|o@1| |2| @64
+|f|o@1| |3| @64
+|f+1&&|o@1| +0&&|4| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|5| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|6| @64
+|f|o@1| |7| @64
+|f|o@1| |8| @64
+|:|.|,|.|+|2|s|/@1> @60
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_incsearch_substitute_03.dump
@@ -0,0 +1,9 @@
+|f+0&#ffff4012|o@1| +0&#ffffff0|1| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|2| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|3| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|4| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|5| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|6| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|7| @64
+|f+0&#ffff4012|o@1| +0&#ffffff0|8| @64
+|:|.|,|.|+|2|s|/> @61
--- a/src/testdir/test_search.vim
+++ b/src/testdir/test_search.vim
@@ -839,6 +839,7 @@ func Test_incsearch_substitute_dump()
   sleep 100m
 
   " Need to send one key at a time to force a redraw.
+  " Select three lines at the cursor with typed pattern.
   call term_sendkeys(buf, ':.,.+2s/')
   sleep 100m
   call term_sendkeys(buf, 'f')
@@ -846,7 +847,21 @@ func Test_incsearch_substitute_dump()
   call term_sendkeys(buf, 'o')
   sleep 100m
   call term_sendkeys(buf, 'o')
+  sleep 100m
   call VerifyScreenDump(buf, 'Test_incsearch_substitute_01', {})
+  call term_sendkeys(buf, "\<Esc>")
+
+  " Select three lines at the cursor using previous pattern.
+  call term_sendkeys(buf, "/foo\<CR>")
+  sleep 100m
+  call term_sendkeys(buf, ':.,.+2s//')
+  sleep 100m
+  call VerifyScreenDump(buf, 'Test_incsearch_substitute_02', {})
+
+  " Deleting last slash should remove the match.
+  call term_sendkeys(buf, "\<BS>")
+  sleep 100m
+  call VerifyScreenDump(buf, 'Test_incsearch_substitute_03', {})
 
   call term_sendkeys(buf, "\<Esc>")
   call StopVimInTerminal(buf)
--- a/src/version.c
+++ b/src/version.c
@@ -795,6 +795,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    277,
+/**/
     276,
 /**/
     275,