]> granicus.if.org Git - vim/commitdiff
patch 8.1.0277: 'incsearch' highlighting wrong in a few cases v8.1.0277
authorBram Moolenaar <Bram@vim.org>
Sun, 12 Aug 2018 15:39:14 +0000 (17:39 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 12 Aug 2018 15:39:14 +0000 (17:39 +0200)
Problem:    'incsearch' highlighting wrong in a few cases.
Solution:   Fix using last search pattern.  Restore highlighting when changing
            command. (issue #3321)

src/ex_getln.c
src/testdir/dumps/Test_incsearch_substitute_02.dump [new file with mode: 0644]
src/testdir/dumps/Test_incsearch_substitute_03.dump [new file with mode: 0644]
src/testdir/test_search.vim
src/version.c

index 07032bb542d7c444a991f7e8d90fdf4137659ed5..a1cea9baf2ea50be84e75faf7bd947d0632443d6 100644 (file)
@@ -300,7 +300,7 @@ do_incsearch_highlighting(int firstc, incsearch_state_T *is_state,
                {
                    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, incsearch_state_T *is_state,
     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 *c, incsearch_state_T *is_state)
     }
     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)
diff --git a/src/testdir/dumps/Test_incsearch_substitute_02.dump b/src/testdir/dumps/Test_incsearch_substitute_02.dump
new file mode 100644 (file)
index 0000000..fd1f912
--- /dev/null
@@ -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
diff --git a/src/testdir/dumps/Test_incsearch_substitute_03.dump b/src/testdir/dumps/Test_incsearch_substitute_03.dump
new file mode 100644 (file)
index 0000000..5d7afa0
--- /dev/null
@@ -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
index 20ffa0fbffc05ab1d22a096151f54343fddcd9d3..9b701269d5fe56ee175fdef4521dc10c79f66d75 100644 (file)
@@ -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)
index 98b233588f2d158a1025c03b348f98b97bcca065..a3f81f072e6b38aaed37ac9d72fa8d8ed6723bdb 100644 (file)
@@ -794,6 +794,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    277,
 /**/
     276,
 /**/