# HG changeset patch # User Bram Moolenaar # Date 1582317904 -3600 # Node ID 5512aa74cb622dfd3d5c48811f91a2c4007b9404 # Parent 3e0b71dd3dc500f44a1dc401f65fc0fa2008cef2 patch 8.2.0295: highlighting for :s wrong when using different separator Commit: https://github.com/vim/vim/commit/c036e87bd7001238ab7cc5d9e30e59bbf989a5fd Author: Bram Moolenaar Date: Fri Feb 21 21:30:52 2020 +0100 patch 8.2.0295: highlighting for :s wrong when using different separator Problem: Highlighting for :s wrong when using different separator. Solution: Use separat argument for search direction and separator. (Rob Pilling, closes #5665) diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3671,7 +3671,7 @@ get_address( curwin->w_cursor.col = 0; searchcmdlen = 0; flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG; - if (!do_search(NULL, c, cmd, 1L, flags, NULL)) + if (!do_search(NULL, c, c, cmd, 1L, flags, NULL)) { curwin->w_cursor = pos; cmd = NULL; diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -184,7 +184,7 @@ set_search_match(pos_T *t) * May change the last search pattern. */ static int -do_incsearch_highlighting(int firstc, incsearch_state_T *is_state, +do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *is_state, int *skiplen, int *patlen) { char_u *cmd; @@ -210,7 +210,10 @@ do_incsearch_highlighting(int firstc, in search_last_line = MAXLNUM; if (firstc == '/' || firstc == '?') + { + *search_delim = firstc; return TRUE; + } if (firstc != ':') return FALSE; @@ -273,6 +276,7 @@ do_incsearch_highlighting(int firstc, in p = skipwhite(p); delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++; + *search_delim = delim; end = skip_regexp(p, delim, p_magic, NULL); use_last_pat = end == p && *end == delim; @@ -385,12 +389,13 @@ may_do_incsearch_highlighting( int next_char; int use_last_pat; int did_do_incsearch = is_state->did_incsearch; + int search_delim; // Parsing range may already set the last search pattern. // NOTE: must call restore_last_search_pattern() before returning! save_last_search_pattern(); - if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) + if (!do_incsearch_highlighting(firstc, &search_delim, is_state, &skiplen, &patlen)) { restore_last_search_pattern(); finish_incsearch_highlighting(FALSE, is_state, TRUE); @@ -457,7 +462,7 @@ may_do_incsearch_highlighting( vim_memset(&sia, 0, sizeof(sia)); sia.sa_tm = &tm; #endif - found = do_search(NULL, firstc == ':' ? '/' : firstc, + found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim, ccline.cmdbuff + skiplen, count, search_flags, #ifdef FEAT_RELTIME &sia @@ -565,12 +570,13 @@ may_adjust_incsearch_highlighting( int search_flags = SEARCH_NOOF; int i; int save; + int search_delim; // Parsing range may already set the last search pattern. // NOTE: must call restore_last_search_pattern() before returning! save_last_search_pattern(); - if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) + if (!do_incsearch_highlighting(firstc, &search_delim, is_state, &skiplen, &patlen)) { restore_last_search_pattern(); return OK; @@ -581,7 +587,7 @@ may_adjust_incsearch_highlighting( return FAIL; } - if (firstc == ccline.cmdbuff[skiplen]) + if (search_delim == ccline.cmdbuff[skiplen]) { pat = last_search_pattern(); skiplen = 0; @@ -668,13 +674,13 @@ may_adjust_incsearch_highlighting( static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state) { - int skiplen, patlen; + int skiplen, patlen, search_delim; // Parsing range may already set the last search pattern. // NOTE: must call restore_last_search_pattern() before returning! save_last_search_pattern(); - if (!do_incsearch_highlighting(firstc, is_state, &skiplen, &patlen)) + if (!do_incsearch_highlighting(firstc, &search_delim, is_state, &skiplen, &patlen)) { restore_last_search_pattern(); return FAIL; @@ -693,7 +699,7 @@ may_add_char_to_search(int firstc, int * // the character to lowercase. if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff + skiplen)) *c = MB_TOLOWER(*c); - if (*c == firstc || vim_strchr((char_u *)( + if (*c == search_delim || vim_strchr((char_u *)( p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL) { // put a backslash before special characters diff --git a/src/gui.c b/src/gui.c --- a/src/gui.c +++ b/src/gui.c @@ -5374,7 +5374,7 @@ gui_do_findrepl( i = msg_scroll; if (down) { - (void)do_search(NULL, '/', ga.ga_data, 1L, searchflags, NULL); + (void)do_search(NULL, '/', '/', ga.ga_data, 1L, searchflags, NULL); } else { @@ -5382,7 +5382,7 @@ gui_do_findrepl( // direction p = vim_strsave_escaped(ga.ga_data, (char_u *)"?"); if (p != NULL) - (void)do_search(NULL, '?', p, 1L, searchflags, NULL); + (void)do_search(NULL, '?', '?', p, 1L, searchflags, NULL); vim_free(p); } diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -4304,7 +4304,7 @@ normal_search( curwin->w_set_curswant = TRUE; vim_memset(&sia, 0, sizeof(sia)); - i = do_search(cap->oap, dir, pat, cap->count1, + i = do_search(cap->oap, dir, dir, pat, cap->count1, opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia); if (wrapped != NULL) *wrapped = sia.sa_wrapped; diff --git a/src/proto/search.pro b/src/proto/search.pro --- a/src/proto/search.pro +++ b/src/proto/search.pro @@ -24,7 +24,7 @@ void set_last_search_pat(char_u *s, int void last_pat_prog(regmmatch_T *regmatch); int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, int dir, char_u *pat, long count, int options, int pat_use, searchit_arg_T *extra_arg); void set_search_direction(int cdir); -int do_search(oparg_T *oap, int dirc, char_u *pat, long count, int options, searchit_arg_T *sia); +int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, int options, searchit_arg_T *sia); int search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat); int searchc(cmdarg_T *cap, int t_cmd); pos_T *findmatch(oparg_T *oap, int initc); diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -3197,7 +3197,7 @@ qf_jump_goto_line( // Move the cursor to the first line in the buffer save_cursor = curwin->w_cursor; curwin->w_cursor.lnum = 0; - if (!do_search(NULL, '/', qf_pattern, (long)1, SEARCH_KEEP, NULL)) + if (!do_search(NULL, '/', '/', qf_pattern, (long)1, SEARCH_KEEP, NULL)) curwin->w_cursor = save_cursor; } } diff --git a/src/search.c b/src/search.c --- a/src/search.c +++ b/src/search.c @@ -1187,6 +1187,7 @@ first_submatch(regmmatch_T *rp) do_search( oparg_T *oap, // can be NULL int dirc, // '/' or '?' + int search_delim, // the delimiter for the search, e.g. '%' in s%regex%replacement% char_u *pat, long count, int options, @@ -1285,7 +1286,7 @@ do_search( searchstr = pat; dircp = NULL; // use previous pattern - if (pat == NULL || *pat == NUL || *pat == dirc) + if (pat == NULL || *pat == NUL || *pat == search_delim) { if (spats[RE_SEARCH].pat == NULL) // no previous pattern { @@ -1311,7 +1312,7 @@ do_search( * If there is a matching '/' or '?', toss it. */ ps = strcopy; - p = skip_regexp(pat, dirc, (int)p_magic, &strcopy); + p = skip_regexp(pat, search_delim, (int)p_magic, &strcopy); if (strcopy != ps) { // made a copy of "pat" to change "\?" to "?" @@ -1319,7 +1320,7 @@ do_search( pat = strcopy; searchstr = strcopy; } - if (*p == dirc) + if (*p == search_delim) { dircp = p; // remember where we put the NUL *p++ = NUL; @@ -1525,7 +1526,7 @@ do_search( RE_LAST, sia); if (dircp != NULL) - *dircp = dirc; // restore second '/' or '?' for normal_cmd() + *dircp = search_delim; // restore second '/' or '?' for normal_cmd() if (!shortmess(SHM_SEARCH) && ((dirc == '/' && LT_POS(pos, curwin->w_cursor)) @@ -1606,6 +1607,7 @@ do_search( break; dirc = *++pat; + search_delim = dirc; if (dirc != '?' && dirc != '/') { retval = 0; diff --git a/src/spell.c b/src/spell.c --- a/src/spell.c +++ b/src/spell.c @@ -2861,7 +2861,7 @@ ex_spellrepall(exarg_T *eap UNUSED) curwin->w_cursor.lnum = 0; while (!got_int) { - if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0 + if (do_search(NULL, '/', '/', frompat, 1L, SEARCH_KEEP, NULL) == 0 || u_save_cursor() == FAIL) break; diff --git a/src/tag.c b/src/tag.c --- a/src/tag.c +++ b/src/tag.c @@ -3543,7 +3543,7 @@ jumpto_tag( else // start search before first line curwin->w_cursor.lnum = 0; - if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, + if (do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, (long)1, search_options, NULL)) retval = OK; else @@ -3555,7 +3555,7 @@ jumpto_tag( * try again, ignore case now */ p_ic = TRUE; - if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1, + if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, (long)1, search_options, NULL)) { /* @@ -3566,13 +3566,13 @@ jumpto_tag( cc = *tagp.tagname_end; *tagp.tagname_end = NUL; sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname); - if (!do_search(NULL, '/', pbuf, (long)1, + if (!do_search(NULL, '/', '/', pbuf, (long)1, search_options, NULL)) { // Guess again: "^char * \ @7 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 @@ -1084,6 +1084,30 @@ func Test_incsearch_substitute_dump() call delete('Xis_subst_script') endfunc +func Test_incsearch_highlighting() + if !exists('+incsearch') + return + endif + if !CanRunVimInTerminal() + throw 'Skipped: cannot make screendumps' + endif + + call writefile([ + \ 'set incsearch hlsearch', + \ 'call setline(1, "hello/there")', + \ ], 'Xis_subst_hl_script') + let buf = RunVimInTerminal('-S Xis_subst_hl_script', {'rows': 4, 'cols': 20}) + " Give Vim a chance to redraw to get rid of the spaces in line 2 caused by + " the 'ambiwidth' check. + sleep 300m + + " Using a different search delimiter should still highlight matches + " that contain a '/'. + call term_sendkeys(buf, ":%s;ello/the") + call VerifyScreenDump(buf, 'Test_incsearch_substitute_15', {}) + call term_sendkeys(buf, "") +endfunc + func Test_incsearch_with_change() if !has('timers') || !exists('+incsearch') || !CanRunVimInTerminal() throw 'Skipped: cannot make screendumps and/or timers feature and/or incsearch option missing' diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 295, +/**/ 294, /**/ 293,