Skip to content

Commit d93a7fc

Browse files
committed
patch 8.2.2295: incsearch does not detect empty pattern properly
Problem: Incsearch does not detect empty pattern properly. Solution: Return magic state when skipping over a pattern. (Christian Brabandt, closes #7612, closes #6420)
1 parent 82c38fe commit d93a7fc

15 files changed

Lines changed: 125 additions & 40 deletions

src/ex_cmds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3672,7 +3672,7 @@ ex_substitute(exarg_T *eap)
36723672
delimiter = *cmd++; // remember delimiter character
36733673
pat = cmd; // remember start of search pat
36743674
cmd = skip_regexp_ex(cmd, delimiter, magic_isset(),
3675-
&eap->arg, NULL);
3675+
&eap->arg, NULL, NULL);
36763676
if (cmd[0] == delimiter) // end delimiter found
36773677
*cmd++ = NUL; // replace it with a NUL
36783678
}
@@ -4856,7 +4856,7 @@ ex_global(exarg_T *eap)
48564856
if (delim)
48574857
++cmd; // skip delimiter if there is one
48584858
pat = cmd; // remember start of pattern
4859-
cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL);
4859+
cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL, NULL);
48604860
if (cmd[0] == delim) // end delimiter found
48614861
*cmd++ = NUL; // replace it with a NUL
48624862
}

src/ex_docmd.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7529,9 +7529,10 @@ ex_may_print(exarg_T *eap)
75297529
static void
75307530
ex_submagic(exarg_T *eap)
75317531
{
7532-
magic_T saved = magic_overruled;
7532+
optmagic_T saved = magic_overruled;
75337533

7534-
magic_overruled = eap->cmdidx == CMD_smagic ? MAGIC_ON : MAGIC_OFF;
7534+
magic_overruled = eap->cmdidx == CMD_smagic
7535+
? OPTION_MAGIC_ON : OPTION_MAGIC_OFF;
75357536
ex_substitute(eap);
75367537
magic_overruled = saved;
75377538
}

src/ex_getln.c

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ static void restore_cmdline(cmdline_info_T *ccp);
5252
static int cmdline_paste(int regname, int literally, int remcr);
5353
static void redrawcmdprompt(void);
5454
static int ccheck_abbr(int);
55+
#ifdef FEAT_SEARCH_EXTRA
56+
static int empty_pattern_magic(char_u *pat, size_t len, magic_T magic_val);
57+
#endif
5558

5659
#ifdef FEAT_CMDWIN
5760
static int open_cmdwin(void);
@@ -89,15 +92,34 @@ abandon_cmdline(void)
8992
* as a trailing \|, which can happen while typing a pattern.
9093
*/
9194
static int
92-
empty_pattern(char_u *p)
95+
empty_pattern(char_u *p, int delim)
9396
{
94-
size_t n = STRLEN(p);
97+
size_t n = STRLEN(p);
98+
magic_T magic_val = MAGIC_ON;
99+
100+
if (n > 0)
101+
(void) skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val);
102+
else
103+
return TRUE;
95104

105+
return empty_pattern_magic(p, n, magic_val);
106+
}
107+
108+
static int
109+
empty_pattern_magic(char_u *p, size_t len, magic_T magic_val)
110+
{
96111
// remove trailing \v and the like
97-
while (n >= 2 && p[n - 2] == '\\'
98-
&& vim_strchr((char_u *)"mMvVcCZ", p[n - 1]) != NULL)
99-
n -= 2;
100-
return n == 0 || (n >= 2 && p[n - 2] == '\\' && p[n - 1] == '|');
112+
while (len >= 2 && p[len - 2] == '\\'
113+
&& vim_strchr((char_u *)"mMvVcCZ", p[len - 1]) != NULL)
114+
len -= 2;
115+
116+
// true, if the pattern is empty, or the pattern ends with \| and magic is
117+
// set (or it ends with '|' and very magic is set)
118+
return len == 0 || (len > 1
119+
&& ((p[len - 2] == '\\'
120+
&& p[len - 1] == '|' && magic_val == MAGIC_ON)
121+
|| (p[len - 2] != '\\'
122+
&& p[len - 1] == '|' && magic_val == MAGIC_ALL)));
101123
}
102124

103125
// Struct to store the viewstate during 'incsearch' highlighting.
@@ -149,7 +171,7 @@ typedef struct {
149171
pos_T match_end;
150172
int did_incsearch;
151173
int incsearch_postponed;
152-
magic_T magic_overruled_save;
174+
optmagic_T magic_overruled_save;
153175
} incsearch_state_T;
154176

155177
static void
@@ -207,6 +229,7 @@ do_incsearch_highlighting(
207229
pos_T save_cursor;
208230
int use_last_pat;
209231
int retval = FALSE;
232+
magic_T magic = 0;
210233

211234
*skiplen = 0;
212235
*patlen = ccline.cmdlen;
@@ -252,9 +275,9 @@ do_incsearch_highlighting(
252275
|| STRNCMP(cmd, "vglobal", p - cmd) == 0)
253276
{
254277
if (*cmd == 's' && cmd[1] == 'm')
255-
magic_overruled = MAGIC_ON;
278+
magic_overruled = OPTION_MAGIC_ON;
256279
else if (*cmd == 's' && cmd[1] == 'n')
257-
magic_overruled = MAGIC_OFF;
280+
magic_overruled = OPTION_MAGIC_OFF;
258281
}
259282
else if (STRNCMP(cmd, "sort", MAX(p - cmd, 3)) == 0)
260283
{
@@ -288,7 +311,7 @@ do_incsearch_highlighting(
288311
p = skipwhite(p);
289312
delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++;
290313
*search_delim = delim;
291-
end = skip_regexp(p, delim, magic_isset());
314+
end = skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic);
292315

293316
use_last_pat = end == p && *end == delim;
294317

@@ -302,7 +325,7 @@ do_incsearch_highlighting(
302325
int empty;
303326

304327
*end = NUL;
305-
empty = empty_pattern(p);
328+
empty = empty_pattern_magic(p, STRLEN(p), magic);
306329
*end = c;
307330
if (empty)
308331
goto theend;
@@ -535,7 +558,8 @@ may_do_incsearch_highlighting(
535558
{
536559
next_char = ccline.cmdbuff[skiplen + patlen];
537560
ccline.cmdbuff[skiplen + patlen] = NUL;
538-
if (empty_pattern(ccline.cmdbuff) && !no_hlsearch)
561+
if (empty_pattern(ccline.cmdbuff + skiplen, search_delim)
562+
&& !no_hlsearch)
539563
{
540564
redraw_all_later(SOME_VALID);
541565
set_no_hlsearch(TRUE);

src/globals.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,7 +1945,6 @@ EXTERN int channel_need_redraw INIT(= FALSE);
19451945
#define FOR_ALL_LIST_ITEMS(l, li) \
19461946
for ((li) = (l)->lv_first; (li) != NULL; (li) = (li)->li_next)
19471947

1948-
// While executing a regexp and set to MAGIC_ON or MAGIC_OFF this overrules
1949-
// p_magic. Otherwise set to MAGIC_NOT_SET.
1950-
1951-
EXTERN magic_T magic_overruled INIT(= MAGIC_NOT_SET);
1948+
// While executing a regexp and set to OPTION_MAGIC_ON or OPTION_MAGIC_OFF this
1949+
// overrules p_magic. Otherwise set to OPTION_MAGIC_NOT_SET.
1950+
EXTERN optmagic_T magic_overruled INIT(= OPTION_MAGIC_NOT_SET);

src/option.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7009,9 +7009,9 @@ magic_isset(void)
70097009
{
70107010
switch (magic_overruled)
70117011
{
7012-
case MAGIC_ON: return TRUE;
7013-
case MAGIC_OFF: return FALSE;
7014-
case MAGIC_NOT_SET: break;
7012+
case OPTION_MAGIC_ON: return TRUE;
7013+
case OPTION_MAGIC_OFF: return FALSE;
7014+
case OPTION_MAGIC_NOT_SET: break;
70157015
}
70167016
#ifdef FEAT_EVAL
70177017
if (in_vim9script())

src/proto/regexp.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
int re_multiline(regprog_T *prog);
33
char_u *skip_regexp(char_u *startp, int delim, int magic);
44
char_u *skip_regexp_err(char_u *startp, int delim, int magic);
5-
char_u *skip_regexp_ex(char_u *startp, int dirc, int magic, char_u **newp, int *dropped);
5+
char_u *skip_regexp_ex(char_u *startp, int dirc, int magic, char_u **newp, int *dropped, magic_T *magic_val);
66
reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
77
void unref_extmatch(reg_extmatch_T *em);
88
char_u *regtilde(char_u *source, int magic);

src/regexp.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,7 @@ static unsigned regflags; // RF_ flags for prog
304304
static int had_eol; // TRUE when EOL found by vim_regcomp()
305305
#endif
306306

307-
static int reg_magic; // magicness of the pattern:
308-
#define MAGIC_NONE 1 // "\V" very unmagic
309-
#define MAGIC_OFF 2 // "\M" or 'magic' off
310-
#define MAGIC_ON 3 // "\m" or 'magic'
311-
#define MAGIC_ALL 4 // "\v" very magic
307+
static magic_T reg_magic; // magicness of the pattern
312308

313309
static int reg_string; // matching with a string instead of a buffer
314310
// line
@@ -548,7 +544,7 @@ skip_regexp(
548544
int delim,
549545
int magic)
550546
{
551-
return skip_regexp_ex(startp, delim, magic, NULL, NULL);
547+
return skip_regexp_ex(startp, delim, magic, NULL, NULL, NULL);
552548
}
553549

554550
/*
@@ -577,16 +573,18 @@ skip_regexp_err(
577573
* expression and change "\?" to "?". If "*newp" is not NULL the expression
578574
* is changed in-place.
579575
* If a "\?" is changed to "?" then "dropped" is incremented, unless NULL.
576+
* If "magic_val" is not NULL, returns the effective magicness of the pattern
580577
*/
581578
char_u *
582579
skip_regexp_ex(
583580
char_u *startp,
584581
int dirc,
585582
int magic,
586583
char_u **newp,
587-
int *dropped)
584+
int *dropped,
585+
magic_T *magic_val)
588586
{
589-
int mymagic;
587+
magic_T mymagic;
590588
char_u *p = startp;
591589

592590
if (magic)
@@ -632,6 +630,8 @@ skip_regexp_ex(
632630
mymagic = MAGIC_NONE;
633631
}
634632
}
633+
if (magic_val != NULL)
634+
*magic_val = mymagic;
635635
return p;
636636
}
637637

src/search.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,7 @@ do_search(
13421342
*/
13431343
ps = strcopy;
13441344
p = skip_regexp_ex(pat, search_delim, magic_isset(),
1345-
&strcopy, NULL);
1345+
&strcopy, NULL, NULL);
13461346
if (strcopy != ps)
13471347
{
13481348
// made a copy of "pat" to change "\?" to "?"

src/structs.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4321,8 +4321,20 @@ typedef struct
43214321
// with iconv() to be able to allocate a buffer.
43224322
#define ICONV_MULT 8
43234323

4324+
// Used for "magic_overruled".
43244325
typedef enum {
4325-
MAGIC_NOT_SET, // p_magic not overruled
4326-
MAGIC_ON, // magic on inside regexp
4327-
MAGIC_OFF // magic off inside regexp
4326+
OPTION_MAGIC_NOT_SET, // p_magic not overruled
4327+
OPTION_MAGIC_ON, // magic on inside regexp
4328+
OPTION_MAGIC_OFF // magic off inside regexp
4329+
} optmagic_T;
4330+
4331+
// Magicness of a pattern, used by regexp code.
4332+
// The order and values matter:
4333+
// magic <= MAGIC_OFF includes MAGIC_NONE
4334+
// magic >= MAGIC_ON includes MAGIC_ALL
4335+
typedef enum {
4336+
MAGIC_NONE = 1, // "\V" very unmagic
4337+
MAGIC_OFF = 2, // "\M" or 'magic' off
4338+
MAGIC_ON = 3, // "\m" or 'magic'
4339+
MAGIC_ALL = 4 // "\v" very magic
43284340
} magic_T;

src/tag.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,7 +3312,7 @@ jumpto_tag(
33123312
int keep_help) // keep help flag (FALSE for cscope)
33133313
{
33143314
int save_secure;
3315-
int save_magic_overruled;
3315+
optmagic_T save_magic_overruled;
33163316
int save_p_ws, save_p_scs, save_p_ic;
33173317
linenr_T save_lnum;
33183318
char_u *str;
@@ -3505,7 +3505,7 @@ jumpto_tag(
35053505
++sandbox;
35063506
#endif
35073507
save_magic_overruled = magic_overruled;
3508-
magic_overruled = MAGIC_OFF; // always execute with 'nomagic'
3508+
magic_overruled = OPTION_MAGIC_OFF; // always execute with 'nomagic'
35093509
#ifdef FEAT_SEARCH_EXTRA
35103510
// Save value of no_hlsearch, jumping to a tag is not a real search
35113511
save_no_hlsearch = no_hlsearch;

0 commit comments

Comments
 (0)