mirror of
https://github.com/neovim/neovim.git
synced 2025-09-17 08:48:16 +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;
|
||||
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;
|
||||
goto error;
|
||||
|
@@ -275,8 +275,9 @@ static void init_incsearch_state(incsearch_state_T *s)
|
||||
|
||||
// Return true when 'incsearch' highlighting is to be done.
|
||||
// Sets search_first_line and search_last_line to the address range.
|
||||
static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
|
||||
int *skiplen, int *patlen)
|
||||
static bool do_incsearch_highlighting(int firstc, int *search_delim,
|
||||
incsearch_state_T *s, int *skiplen,
|
||||
int *patlen)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char_u *cmd;
|
||||
@@ -303,6 +304,7 @@ static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
|
||||
search_last_line = MAXLNUM;
|
||||
|
||||
if (firstc == '/' || firstc == '?') {
|
||||
*search_delim = firstc;
|
||||
return true;
|
||||
}
|
||||
if (firstc != ':') {
|
||||
@@ -371,6 +373,7 @@ static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
|
||||
|
||||
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;
|
||||
@@ -431,12 +434,14 @@ static void may_do_incsearch_highlighting(int firstc, long count,
|
||||
int skiplen, patlen;
|
||||
char_u next_char;
|
||||
char_u use_last_pat;
|
||||
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, s, &skiplen, &patlen)) {
|
||||
if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen,
|
||||
&patlen)) {
|
||||
restore_last_search_pattern();
|
||||
finish_incsearch_highlighting(false, s, true);
|
||||
return;
|
||||
@@ -490,7 +495,7 @@ static void may_do_incsearch_highlighting(int firstc, long count,
|
||||
ccline.cmdbuff[skiplen + patlen] = NUL;
|
||||
memset(&sia, 0, sizeof(sia));
|
||||
sia.sa_tm = &tm;
|
||||
found = do_search(NULL, firstc == ':' ? '/' : firstc,
|
||||
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
|
||||
ccline.cmdbuff + skiplen, count,
|
||||
search_flags, &sia);
|
||||
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
|
||||
{
|
||||
int skiplen, patlen;
|
||||
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();
|
||||
|
||||
// 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();
|
||||
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)) {
|
||||
*c = mb_tolower(*c);
|
||||
}
|
||||
if (*c == firstc
|
||||
if (*c == search_delim
|
||||
|| vim_strchr((char_u *)(p_magic ? "\\~^$.*[" : "\\^$"), *c)
|
||||
!= NULL) {
|
||||
// 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)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
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, s, &skiplen, &patlen)) {
|
||||
if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen,
|
||||
&patlen)) {
|
||||
restore_last_search_pattern();
|
||||
return OK;
|
||||
}
|
||||
@@ -1489,7 +1497,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count,
|
||||
char_u save;
|
||||
|
||||
|
||||
if (firstc == ccline.cmdbuff[skiplen]) {
|
||||
if (search_delim == ccline.cmdbuff[skiplen]) {
|
||||
pat = last_search_pattern();
|
||||
skiplen = 0;
|
||||
patlen = (int)STRLEN(pat);
|
||||
|
@@ -5459,7 +5459,7 @@ static int normal_search(
|
||||
curwin->w_set_curswant = true;
|
||||
|
||||
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;
|
||||
|
@@ -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
|
||||
pos_T 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;
|
||||
}
|
||||
}
|
||||
|
@@ -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.
|
||||
*/
|
||||
int do_search(
|
||||
oparg_T *oap, /* can be NULL */
|
||||
int dirc, /* '/' or '?' */
|
||||
oparg_T *oap, // can be NULL
|
||||
int dirc, // '/' or '?'
|
||||
int search_delim, // delimiter for search, e.g. '%' in s%regex%replacement
|
||||
char_u *pat,
|
||||
long count,
|
||||
int options,
|
||||
@@ -1101,8 +1102,8 @@ int do_search(
|
||||
|
||||
searchstr = pat;
|
||||
dircp = NULL;
|
||||
/* use previous pattern */
|
||||
if (pat == NULL || *pat == NUL || *pat == dirc) {
|
||||
// use previous pattern
|
||||
if (pat == NULL || *pat == NUL || *pat == search_delim) {
|
||||
if (spats[RE_SEARCH].pat == NULL) { // no previous pattern
|
||||
searchstr = spats[RE_SUBST].pat;
|
||||
if (searchstr == NULL) {
|
||||
@@ -1122,15 +1123,15 @@ int do_search(
|
||||
* If there is a matching '/' or '?', toss it.
|
||||
*/
|
||||
ps = strcopy;
|
||||
p = skip_regexp(pat, dirc, p_magic, &strcopy);
|
||||
p = skip_regexp(pat, search_delim, p_magic, &strcopy);
|
||||
if (strcopy != ps) {
|
||||
/* made a copy of "pat" to change "\?" to "?" */
|
||||
searchcmdlen += (int)(STRLEN(pat) - STRLEN(strcopy));
|
||||
pat = strcopy;
|
||||
searchstr = strcopy;
|
||||
}
|
||||
if (*p == dirc) {
|
||||
dircp = p; /* remember where we put the NUL */
|
||||
if (*p == search_delim) {
|
||||
dircp = p; // remember where we put the NUL
|
||||
*p++ = NUL;
|
||||
}
|
||||
spats[0].off.line = FALSE;
|
||||
@@ -1320,7 +1321,7 @@ int 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)
|
||||
@@ -1400,6 +1401,7 @@ int do_search(
|
||||
}
|
||||
|
||||
dirc = *++pat;
|
||||
search_delim = dirc;
|
||||
if (dirc != '?' && dirc != '/') {
|
||||
retval = 0;
|
||||
EMSG(_("E386: Expected '?' or '/' after ';'"));
|
||||
|
@@ -3035,7 +3035,7 @@ void ex_spellrepall(exarg_T *eap)
|
||||
sub_nlines = 0;
|
||||
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;
|
||||
}
|
||||
|
@@ -2811,7 +2811,7 @@ static int jumpto_tag(
|
||||
// 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 {
|
||||
@@ -2821,8 +2821,8 @@ static int jumpto_tag(
|
||||
/*
|
||||
* try again, ignore case now
|
||||
*/
|
||||
p_ic = TRUE;
|
||||
if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
|
||||
p_ic = true;
|
||||
if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, (long)1,
|
||||
search_options, NULL)) {
|
||||
// Failed to find pattern, take a guess: "^func ("
|
||||
found = 2;
|
||||
@@ -2830,11 +2830,12 @@ static int jumpto_tag(
|
||||
cc = *tagp.tagname_end;
|
||||
*tagp.tagname_end = NUL;
|
||||
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 ("
|
||||
snprintf((char *)pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
|
||||
tagp.tagname);
|
||||
if (!do_search(NULL, '/', pbuf, (long)1, search_options, NULL)) {
|
||||
if (!do_search(NULL, '/', '/', pbuf, (long)1,
|
||||
search_options, NULL)) {
|
||||
found = 0;
|
||||
}
|
||||
}
|
||||
|
@@ -723,6 +723,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
|
||||
|
||||
" Similar to Test_incsearch_substitute_dump() for :sort
|
||||
func Test_incsearch_sort_dump()
|
||||
if !exists('+incsearch')
|
||||
|
@@ -507,7 +507,21 @@ describe('search highlighting', function()
|
||||
{1:~ }|
|
||||
: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)
|
||||
|
||||
|
Reference in New Issue
Block a user