changeset 19475:5512aa74cb62 v8.2.0295

patch 8.2.0295: highlighting for :s wrong when using different separator Commit: https://github.com/vim/vim/commit/c036e87bd7001238ab7cc5d9e30e59bbf989a5fd Author: Bram Moolenaar <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Fri, 21 Feb 2020 21:45:04 +0100
parents 3e0b71dd3dc5
children 381e5000c519
files src/ex_docmd.c src/ex_getln.c src/gui.c src/normal.c src/proto/search.pro src/quickfix.c src/search.c src/spell.c src/tag.c src/testdir/dumps/Test_incsearch_substitute_15.dump src/testdir/test_search.vim src/version.c
diffstat 12 files changed, 61 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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
--- 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);
 	}
 
--- 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;
--- 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);
--- 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;
     }
 }
--- 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;
--- 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;
 
--- 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 * \<func  ("
 			sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
 								tagp.tagname);
-			if (!do_search(NULL, '/', pbuf, (long)1,
+			if (!do_search(NULL, '/', '/', pbuf, (long)1,
 							 search_options, NULL))
 			    found = 0;
 		    }
new file mode 100644
--- /dev/null
+++ b/src/testdir/dumps/Test_incsearch_substitute_15.dump
@@ -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
--- 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, "<Esc>")
+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'
--- 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,