mirror of
https://github.com/neovim/neovim.git
synced 2025-09-17 16:58:17 +00:00
vim-patch:8.2.0295: highlighting for :s wrong when using different separator (#14286)
Problem: Highlighting for :s wrong when using different separator.
Solution: Use separat argument for search direction and separator. (Rob
Pilling, closes vim/vim#5665)
c036e87bd7
This commit is contained in:
@@ -3928,7 +3928,7 @@ static linenr_T get_address(exarg_T *eap,
|
|||||||
}
|
}
|
||||||
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;
|
||||||
goto error;
|
goto error;
|
||||||
|
@@ -275,8 +275,9 @@ static void init_incsearch_state(incsearch_state_T *s)
|
|||||||
|
|
||||||
// Return true when 'incsearch' highlighting is to be done.
|
// Return true when 'incsearch' highlighting is to be done.
|
||||||
// Sets search_first_line and search_last_line to the address range.
|
// Sets search_first_line and search_last_line to the address range.
|
||||||
static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
|
static bool do_incsearch_highlighting(int firstc, int *search_delim,
|
||||||
int *skiplen, int *patlen)
|
incsearch_state_T *s, int *skiplen,
|
||||||
|
int *patlen)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
char_u *cmd;
|
char_u *cmd;
|
||||||
@@ -303,6 +304,7 @@ static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
|
|||||||
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 != ':') {
|
||||||
@@ -371,6 +373,7 @@ static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
|
|||||||
|
|
||||||
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;
|
||||||
@@ -431,12 +434,14 @@ static void may_do_incsearch_highlighting(int firstc, long count,
|
|||||||
int skiplen, patlen;
|
int skiplen, patlen;
|
||||||
char_u next_char;
|
char_u next_char;
|
||||||
char_u use_last_pat;
|
char_u use_last_pat;
|
||||||
|
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, s, &skiplen, &patlen)) {
|
if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen,
|
||||||
|
&patlen)) {
|
||||||
restore_last_search_pattern();
|
restore_last_search_pattern();
|
||||||
finish_incsearch_highlighting(false, s, true);
|
finish_incsearch_highlighting(false, s, true);
|
||||||
return;
|
return;
|
||||||
@@ -490,7 +495,7 @@ static void may_do_incsearch_highlighting(int firstc, long count,
|
|||||||
ccline.cmdbuff[skiplen + patlen] = NUL;
|
ccline.cmdbuff[skiplen + patlen] = NUL;
|
||||||
memset(&sia, 0, sizeof(sia));
|
memset(&sia, 0, sizeof(sia));
|
||||||
sia.sa_tm = &tm;
|
sia.sa_tm = &tm;
|
||||||
found = do_search(NULL, firstc == ':' ? '/' : firstc,
|
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
|
||||||
ccline.cmdbuff + skiplen, count,
|
ccline.cmdbuff + skiplen, count,
|
||||||
search_flags, &sia);
|
search_flags, &sia);
|
||||||
ccline.cmdbuff[skiplen + patlen] = next_char;
|
ccline.cmdbuff[skiplen + patlen] = next_char;
|
||||||
@@ -581,13 +586,15 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
|
|||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int skiplen, patlen;
|
int skiplen, patlen;
|
||||||
|
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();
|
||||||
|
|
||||||
// Add a character from under the cursor for 'incsearch'
|
// Add a character from under the cursor for 'incsearch'
|
||||||
if (!do_incsearch_highlighting(firstc, s, &skiplen, &patlen)) {
|
if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen,
|
||||||
|
&patlen)) {
|
||||||
restore_last_search_pattern();
|
restore_last_search_pattern();
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
@@ -604,7 +611,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
|
|||||||
&& !pat_has_uppercase(ccline.cmdbuff + skiplen)) {
|
&& !pat_has_uppercase(ccline.cmdbuff + skiplen)) {
|
||||||
*c = mb_tolower(*c);
|
*c = mb_tolower(*c);
|
||||||
}
|
}
|
||||||
if (*c == firstc
|
if (*c == search_delim
|
||||||
|| vim_strchr((char_u *)(p_magic ? "\\~^$.*[" : "\\^$"), *c)
|
|| vim_strchr((char_u *)(p_magic ? "\\~^$.*[" : "\\^$"), *c)
|
||||||
!= NULL) {
|
!= NULL) {
|
||||||
// put a backslash before special characters
|
// put a backslash before special characters
|
||||||
@@ -1465,13 +1472,14 @@ static int may_do_command_line_next_incsearch(int firstc, long count,
|
|||||||
bool next_match)
|
bool next_match)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
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, s, &skiplen, &patlen)) {
|
if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen,
|
||||||
|
&patlen)) {
|
||||||
restore_last_search_pattern();
|
restore_last_search_pattern();
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -1489,7 +1497,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count,
|
|||||||
char_u save;
|
char_u save;
|
||||||
|
|
||||||
|
|
||||||
if (firstc == ccline.cmdbuff[skiplen]) {
|
if (search_delim == ccline.cmdbuff[skiplen]) {
|
||||||
pat = last_search_pattern();
|
pat = last_search_pattern();
|
||||||
skiplen = 0;
|
skiplen = 0;
|
||||||
patlen = (int)STRLEN(pat);
|
patlen = (int)STRLEN(pat);
|
||||||
|
@@ -5459,7 +5459,7 @@ static int normal_search(
|
|||||||
curwin->w_set_curswant = true;
|
curwin->w_set_curswant = true;
|
||||||
|
|
||||||
memset(&sia, 0, sizeof(sia));
|
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;
|
||||||
|
@@ -2798,7 +2798,7 @@ static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char_u qf_viscol,
|
|||||||
// Move the cursor to the first line in the buffer
|
// Move the cursor to the first line in the buffer
|
||||||
pos_T save_cursor = curwin->w_cursor;
|
pos_T 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1021,8 +1021,9 @@ static int first_submatch(regmmatch_T *rp)
|
|||||||
* Return 0 for failure, 1 for found, 2 for found and line offset added.
|
* Return 0 for failure, 1 for found, 2 for found and line offset added.
|
||||||
*/
|
*/
|
||||||
int do_search(
|
int do_search(
|
||||||
oparg_T *oap, /* can be NULL */
|
oparg_T *oap, // can be NULL
|
||||||
int dirc, /* '/' or '?' */
|
int dirc, // '/' or '?'
|
||||||
|
int search_delim, // delimiter for search, e.g. '%' in s%regex%replacement
|
||||||
char_u *pat,
|
char_u *pat,
|
||||||
long count,
|
long count,
|
||||||
int options,
|
int options,
|
||||||
@@ -1101,8 +1102,8 @@ int 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
|
||||||
searchstr = spats[RE_SUBST].pat;
|
searchstr = spats[RE_SUBST].pat;
|
||||||
if (searchstr == NULL) {
|
if (searchstr == NULL) {
|
||||||
@@ -1122,15 +1123,15 @@ int 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, p_magic, &strcopy);
|
p = skip_regexp(pat, search_delim, 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 "?" */
|
||||||
searchcmdlen += (int)(STRLEN(pat) - STRLEN(strcopy));
|
searchcmdlen += (int)(STRLEN(pat) - STRLEN(strcopy));
|
||||||
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;
|
||||||
}
|
}
|
||||||
spats[0].off.line = FALSE;
|
spats[0].off.line = FALSE;
|
||||||
@@ -1320,7 +1321,7 @@ int 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)
|
||||||
@@ -1400,6 +1401,7 @@ int do_search(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dirc = *++pat;
|
dirc = *++pat;
|
||||||
|
search_delim = dirc;
|
||||||
if (dirc != '?' && dirc != '/') {
|
if (dirc != '?' && dirc != '/') {
|
||||||
retval = 0;
|
retval = 0;
|
||||||
EMSG(_("E386: Expected '?' or '/' after ';'"));
|
EMSG(_("E386: Expected '?' or '/' after ';'"));
|
||||||
|
@@ -3035,7 +3035,7 @@ void ex_spellrepall(exarg_T *eap)
|
|||||||
sub_nlines = 0;
|
sub_nlines = 0;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@@ -2811,7 +2811,7 @@ static int jumpto_tag(
|
|||||||
// 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 {
|
||||||
@@ -2821,8 +2821,8 @@ static int 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)) {
|
||||||
// Failed to find pattern, take a guess: "^func ("
|
// Failed to find pattern, take a guess: "^func ("
|
||||||
found = 2;
|
found = 2;
|
||||||
@@ -2830,11 +2830,12 @@ static int jumpto_tag(
|
|||||||
cc = *tagp.tagname_end;
|
cc = *tagp.tagname_end;
|
||||||
*tagp.tagname_end = NUL;
|
*tagp.tagname_end = NUL;
|
||||||
snprintf((char *)pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
|
snprintf((char *)pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
|
||||||
if (!do_search(NULL, '/', pbuf, (long)1, search_options, NULL)) {
|
if (!do_search(NULL, '/', '/', pbuf, (long)1, search_options, NULL)) {
|
||||||
// Guess again: "^char * \<func ("
|
// Guess again: "^char * \<func ("
|
||||||
snprintf((char *)pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
|
snprintf((char *)pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
|
||||||
tagp.tagname);
|
tagp.tagname);
|
||||||
if (!do_search(NULL, '/', pbuf, (long)1, search_options, NULL)) {
|
if (!do_search(NULL, '/', '/', pbuf, (long)1,
|
||||||
|
search_options, NULL)) {
|
||||||
found = 0;
|
found = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -723,6 +723,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
|
||||||
|
|
||||||
" Similar to Test_incsearch_substitute_dump() for :sort
|
" Similar to Test_incsearch_substitute_dump() for :sort
|
||||||
func Test_incsearch_sort_dump()
|
func Test_incsearch_sort_dump()
|
||||||
if !exists('+incsearch')
|
if !exists('+incsearch')
|
||||||
|
@@ -507,7 +507,21 @@ describe('search highlighting', function()
|
|||||||
{1:~ }|
|
{1:~ }|
|
||||||
:syntax keyword MyGroup special |
|
:syntax keyword MyGroup special |
|
||||||
]])
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('highlights entire pattern on :%g@a/b', function()
|
||||||
|
command('set inccommand=nosplit')
|
||||||
|
feed('ia/b/c<Esc>')
|
||||||
|
feed(':%g@a/b')
|
||||||
|
screen:expect([[
|
||||||
|
{3:a/b}/c |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
:%g@a/b^ |
|
||||||
|
]])
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user