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)
This commit is contained in:
Bram Moolenaar
2020-02-21 21:30:52 +01:00
parent 5b1c8fe3d5
commit c036e87bd7
12 changed files with 61 additions and 23 deletions

View File

@@ -3671,7 +3671,7 @@ get_address(
curwin->w_cursor.col = 0; curwin->w_cursor.col = 0;
searchcmdlen = 0; searchcmdlen = 0;
flags = silent ? 0 : SEARCH_HIS | SEARCH_MSG; 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; curwin->w_cursor = pos;
cmd = NULL; cmd = NULL;

View File

@@ -184,7 +184,7 @@ set_search_match(pos_T *t)
* May change the last search pattern. * May change the last search pattern.
*/ */
static int 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) int *skiplen, int *patlen)
{ {
char_u *cmd; char_u *cmd;
@@ -210,7 +210,10 @@ do_incsearch_highlighting(int firstc, incsearch_state_T *is_state,
search_last_line = MAXLNUM; search_last_line = MAXLNUM;
if (firstc == '/' || firstc == '?') if (firstc == '/' || firstc == '?')
{
*search_delim = firstc;
return TRUE; return TRUE;
}
if (firstc != ':') if (firstc != ':')
return FALSE; return FALSE;
@@ -273,6 +276,7 @@ do_incsearch_highlighting(int firstc, incsearch_state_T *is_state,
p = skipwhite(p); p = skipwhite(p);
delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++; delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++;
*search_delim = delim;
end = skip_regexp(p, delim, p_magic, NULL); end = skip_regexp(p, delim, p_magic, NULL);
use_last_pat = end == p && *end == delim; use_last_pat = end == p && *end == delim;
@@ -385,12 +389,13 @@ may_do_incsearch_highlighting(
int next_char; int next_char;
int use_last_pat; int use_last_pat;
int did_do_incsearch = is_state->did_incsearch; int did_do_incsearch = is_state->did_incsearch;
int search_delim;
// Parsing range may already set the last search pattern. // Parsing range may already set the last search pattern.
// NOTE: must call restore_last_search_pattern() before returning! // NOTE: must call restore_last_search_pattern() before returning!
save_last_search_pattern(); 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(); restore_last_search_pattern();
finish_incsearch_highlighting(FALSE, is_state, TRUE); finish_incsearch_highlighting(FALSE, is_state, TRUE);
@@ -457,7 +462,7 @@ may_do_incsearch_highlighting(
vim_memset(&sia, 0, sizeof(sia)); vim_memset(&sia, 0, sizeof(sia));
sia.sa_tm = &tm; sia.sa_tm = &tm;
#endif #endif
found = do_search(NULL, firstc == ':' ? '/' : firstc, found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
ccline.cmdbuff + skiplen, count, search_flags, ccline.cmdbuff + skiplen, count, search_flags,
#ifdef FEAT_RELTIME #ifdef FEAT_RELTIME
&sia &sia
@@ -565,12 +570,13 @@ may_adjust_incsearch_highlighting(
int search_flags = SEARCH_NOOF; int search_flags = SEARCH_NOOF;
int i; int i;
int save; int save;
int search_delim;
// Parsing range may already set the last search pattern. // Parsing range may already set the last search pattern.
// NOTE: must call restore_last_search_pattern() before returning! // NOTE: must call restore_last_search_pattern() before returning!
save_last_search_pattern(); 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(); restore_last_search_pattern();
return OK; return OK;
@@ -581,7 +587,7 @@ may_adjust_incsearch_highlighting(
return FAIL; return FAIL;
} }
if (firstc == ccline.cmdbuff[skiplen]) if (search_delim == ccline.cmdbuff[skiplen])
{ {
pat = last_search_pattern(); pat = last_search_pattern();
skiplen = 0; skiplen = 0;
@@ -668,13 +674,13 @@ may_adjust_incsearch_highlighting(
static int static int
may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state) 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. // Parsing range may already set the last search pattern.
// NOTE: must call restore_last_search_pattern() before returning! // NOTE: must call restore_last_search_pattern() before returning!
save_last_search_pattern(); 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(); restore_last_search_pattern();
return FAIL; return FAIL;
@@ -693,7 +699,7 @@ may_add_char_to_search(int firstc, int *c, incsearch_state_T *is_state)
// the character to lowercase. // the character to lowercase.
if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff + skiplen)) if (p_ic && p_scs && !pat_has_uppercase(ccline.cmdbuff + skiplen))
*c = MB_TOLOWER(*c); *c = MB_TOLOWER(*c);
if (*c == firstc || vim_strchr((char_u *)( if (*c == search_delim || vim_strchr((char_u *)(
p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL) p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL)
{ {
// put a backslash before special characters // put a backslash before special characters

View File

@@ -5374,7 +5374,7 @@ gui_do_findrepl(
i = msg_scroll; i = msg_scroll;
if (down) if (down)
{ {
(void)do_search(NULL, '/', ga.ga_data, 1L, searchflags, NULL); (void)do_search(NULL, '/', '/', ga.ga_data, 1L, searchflags, NULL);
} }
else else
{ {
@@ -5382,7 +5382,7 @@ gui_do_findrepl(
// direction // direction
p = vim_strsave_escaped(ga.ga_data, (char_u *)"?"); p = vim_strsave_escaped(ga.ga_data, (char_u *)"?");
if (p != NULL) if (p != NULL)
(void)do_search(NULL, '?', p, 1L, searchflags, NULL); (void)do_search(NULL, '?', '?', p, 1L, searchflags, NULL);
vim_free(p); vim_free(p);
} }

View File

@@ -4304,7 +4304,7 @@ normal_search(
curwin->w_set_curswant = TRUE; curwin->w_set_curswant = TRUE;
vim_memset(&sia, 0, sizeof(sia)); 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); opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia);
if (wrapped != NULL) if (wrapped != NULL)
*wrapped = sia.sa_wrapped; *wrapped = sia.sa_wrapped;

View File

@@ -24,7 +24,7 @@ void set_last_search_pat(char_u *s, int idx, int magic, int setlast);
void last_pat_prog(regmmatch_T *regmatch); 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); 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); 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 search_for_exact_line(buf_T *buf, pos_T *pos, int dir, char_u *pat);
int searchc(cmdarg_T *cap, int t_cmd); int searchc(cmdarg_T *cap, int t_cmd);
pos_T *findmatch(oparg_T *oap, int initc); pos_T *findmatch(oparg_T *oap, int initc);

View File

@@ -3197,7 +3197,7 @@ qf_jump_goto_line(
// Move the cursor to the first line in the buffer // Move the cursor to the first line in the buffer
save_cursor = curwin->w_cursor; save_cursor = curwin->w_cursor;
curwin->w_cursor.lnum = 0; 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; curwin->w_cursor = save_cursor;
} }
} }

View File

@@ -1187,6 +1187,7 @@ first_submatch(regmmatch_T *rp)
do_search( do_search(
oparg_T *oap, // can be NULL oparg_T *oap, // can be NULL
int dirc, // '/' or '?' int dirc, // '/' or '?'
int search_delim, // the delimiter for the search, e.g. '%' in s%regex%replacement%
char_u *pat, char_u *pat,
long count, long count,
int options, int options,
@@ -1285,7 +1286,7 @@ do_search(
searchstr = pat; searchstr = pat;
dircp = NULL; dircp = NULL;
// use previous pattern // 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 if (spats[RE_SEARCH].pat == NULL) // no previous pattern
{ {
@@ -1311,7 +1312,7 @@ do_search(
* If there is a matching '/' or '?', toss it. * If there is a matching '/' or '?', toss it.
*/ */
ps = strcopy; ps = strcopy;
p = skip_regexp(pat, dirc, (int)p_magic, &strcopy); p = skip_regexp(pat, search_delim, (int)p_magic, &strcopy);
if (strcopy != ps) if (strcopy != ps)
{ {
// made a copy of "pat" to change "\?" to "?" // made a copy of "pat" to change "\?" to "?"
@@ -1319,7 +1320,7 @@ do_search(
pat = strcopy; pat = strcopy;
searchstr = strcopy; searchstr = strcopy;
} }
if (*p == dirc) if (*p == search_delim)
{ {
dircp = p; // remember where we put the NUL dircp = p; // remember where we put the NUL
*p++ = NUL; *p++ = NUL;
@@ -1525,7 +1526,7 @@ do_search(
RE_LAST, sia); RE_LAST, sia);
if (dircp != NULL) if (dircp != NULL)
*dircp = dirc; // restore second '/' or '?' for normal_cmd() *dircp = search_delim; // restore second '/' or '?' for normal_cmd()
if (!shortmess(SHM_SEARCH) if (!shortmess(SHM_SEARCH)
&& ((dirc == '/' && LT_POS(pos, curwin->w_cursor)) && ((dirc == '/' && LT_POS(pos, curwin->w_cursor))
@@ -1606,6 +1607,7 @@ do_search(
break; break;
dirc = *++pat; dirc = *++pat;
search_delim = dirc;
if (dirc != '?' && dirc != '/') if (dirc != '?' && dirc != '/')
{ {
retval = 0; retval = 0;

View File

@@ -2861,7 +2861,7 @@ ex_spellrepall(exarg_T *eap UNUSED)
curwin->w_cursor.lnum = 0; curwin->w_cursor.lnum = 0;
while (!got_int) 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) || u_save_cursor() == FAIL)
break; break;

View File

@@ -3543,7 +3543,7 @@ jumpto_tag(
else else
// start search before first line // start search before first line
curwin->w_cursor.lnum = 0; 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)) search_options, NULL))
retval = OK; retval = OK;
else else
@@ -3555,7 +3555,7 @@ jumpto_tag(
* try again, ignore case now * try again, ignore case now
*/ */
p_ic = TRUE; 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)) search_options, NULL))
{ {
/* /*
@@ -3566,13 +3566,13 @@ jumpto_tag(
cc = *tagp.tagname_end; cc = *tagp.tagname_end;
*tagp.tagname_end = NUL; *tagp.tagname_end = NUL;
sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname); sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname);
if (!do_search(NULL, '/', pbuf, (long)1, if (!do_search(NULL, '/', '/', pbuf, (long)1,
search_options, NULL)) search_options, NULL))
{ {
// Guess again: "^char * \<func (" // Guess again: "^char * \<func ("
sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(", sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
tagp.tagname); tagp.tagname);
if (!do_search(NULL, '/', pbuf, (long)1, if (!do_search(NULL, '/', '/', pbuf, (long)1,
search_options, NULL)) search_options, NULL))
found = 0; found = 0;
} }

View File

@@ -0,0 +1,4 @@
|h+0&#ffffff0|e+1&&|l@1|o|/|t|h|e|r+0&&|e| @8
|~+0#4040ff13&| @18
|~| @18
|:+0#0000000&|%|s|;|e|l@1|o|/|t|h|e> @7

View File

@@ -1084,6 +1084,30 @@ func Test_incsearch_substitute_dump()
call delete('Xis_subst_script') call delete('Xis_subst_script')
endfunc 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, "<Esc>")
endfunc
func Test_incsearch_with_change() func Test_incsearch_with_change()
if !has('timers') || !exists('+incsearch') || !CanRunVimInTerminal() if !has('timers') || !exists('+incsearch') || !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps and/or timers feature and/or incsearch option missing' throw 'Skipped: cannot make screendumps and/or timers feature and/or incsearch option missing'

View File

@@ -738,6 +738,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
295,
/**/ /**/
294, 294,
/**/ /**/