# HG changeset patch # User Christian Brabandt # Date 1534088704 -7200 # Node ID 58ca1161081978fcefb1e96a959371d3e5fe58ae # Parent 6fc131355f0dd1fcd2bbdaea048b53a2853b8667 patch 8.1.0277: 'incsearch' highlighting wrong in a few cases commit https://github.com/vim/vim/commit/c7f08b7ee1c1ff2080d425c2fcdb6907c26fc98e Author: Bram Moolenaar 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) diff --git a/src/ex_getln.c b/src/ex_getln.c --- 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) diff --git a/src/testdir/dumps/Test_incsearch_substitute_02.dump b/src/testdir/dumps/Test_incsearch_substitute_02.dump 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 diff --git a/src/testdir/dumps/Test_incsearch_substitute_03.dump b/src/testdir/dumps/Test_incsearch_substitute_03.dump 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 diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim --- 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, "\") + + " Select three lines at the cursor using previous pattern. + call term_sendkeys(buf, "/foo\") + 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, "\") + sleep 100m + call VerifyScreenDump(buf, 'Test_incsearch_substitute_03', {}) call term_sendkeys(buf, "\") call StopVimInTerminal(buf) diff --git a/src/version.c b/src/version.c --- 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,