Patch 8.2.2295

4 views
Skip to first unread message

Bram Moolenaar

unread,
Jan 4, 2021, 6:42:55 AM1/4/21
to vim...@googlegroups.com

Patch 8.2.2295
Problem: Incsearch does not detect empty pattern properly.
Solution: Return magic state when skipping over a pattern. (Christian
Brabandt, closes #7612, closes #6420)
Files: src/ex_cmds.c, src/ex_docmd.c, src/ex_getln.c, src/globals.h,
src/option.c, src/tag.c, src/proto/regexp.pro, src/regexp.c,
src/search.c, src/structs.h, src/vim9compile.c,
src/testdir/dumps/Test_incsearch_sub_01.dump,
src/testdir/dumps/Test_incsearch_sub_02.dump,
src/testdir/test_search.vim


*** ../vim-8.2.2294/src/ex_cmds.c 2020-12-27 19:00:20.706479331 +0100
--- src/ex_cmds.c 2021-01-04 11:31:55.813633440 +0100
***************
*** 3672,3678 ****
delimiter = *cmd++; // remember delimiter character
pat = cmd; // remember start of search pat
cmd = skip_regexp_ex(cmd, delimiter, magic_isset(),
! &eap->arg, NULL);
if (cmd[0] == delimiter) // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
--- 3672,3678 ----
delimiter = *cmd++; // remember delimiter character
pat = cmd; // remember start of search pat
cmd = skip_regexp_ex(cmd, delimiter, magic_isset(),
! &eap->arg, NULL, NULL);
if (cmd[0] == delimiter) // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
***************
*** 4856,4862 ****
if (delim)
++cmd; // skip delimiter if there is one
pat = cmd; // remember start of pattern
! cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL);
if (cmd[0] == delim) // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
--- 4856,4862 ----
if (delim)
++cmd; // skip delimiter if there is one
pat = cmd; // remember start of pattern
! cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL, NULL);
if (cmd[0] == delim) // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
*** ../vim-8.2.2294/src/ex_docmd.c 2020-12-29 11:14:58.444606193 +0100
--- src/ex_docmd.c 2021-01-04 11:40:35.783731667 +0100
***************
*** 7529,7537 ****
static void
ex_submagic(exarg_T *eap)
{
! magic_T saved = magic_overruled;

! magic_overruled = eap->cmdidx == CMD_smagic ? MAGIC_ON : MAGIC_OFF;
ex_substitute(eap);
magic_overruled = saved;
}
--- 7529,7538 ----
static void
ex_submagic(exarg_T *eap)
{
! optmagic_T saved = magic_overruled;

! magic_overruled = eap->cmdidx == CMD_smagic
! ? OPTION_MAGIC_ON : OPTION_MAGIC_OFF;
ex_substitute(eap);
magic_overruled = saved;
}
*** ../vim-8.2.2294/src/ex_getln.c 2020-12-21 19:59:04.569197722 +0100
--- src/ex_getln.c 2021-01-04 11:48:48.157971176 +0100
***************
*** 52,57 ****
--- 52,60 ----
static int cmdline_paste(int regname, int literally, int remcr);
static void redrawcmdprompt(void);
static int ccheck_abbr(int);
+ #ifdef FEAT_SEARCH_EXTRA
+ static int empty_pattern_magic(char_u *pat, size_t len, magic_T magic_val);
+ #endif

#ifdef FEAT_CMDWIN
static int open_cmdwin(void);
***************
*** 89,103 ****
* as a trailing \|, which can happen while typing a pattern.
*/
static int
! empty_pattern(char_u *p)
{
! size_t n = STRLEN(p);

// remove trailing \v and the like
! while (n >= 2 && p[n - 2] == '\\'
! && vim_strchr((char_u *)"mMvVcCZ", p[n - 1]) != NULL)
! n -= 2;
! return n == 0 || (n >= 2 && p[n - 2] == '\\' && p[n - 1] == '|');
}

// Struct to store the viewstate during 'incsearch' highlighting.
--- 92,125 ----
* as a trailing \|, which can happen while typing a pattern.
*/
static int
! empty_pattern(char_u *p, int delim)
{
! size_t n = STRLEN(p);
! magic_T magic_val = MAGIC_ON;
!
! if (n > 0)
! (void) skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val);
! else
! return TRUE;

+ return empty_pattern_magic(p, n, magic_val);
+ }
+
+ static int
+ empty_pattern_magic(char_u *p, size_t len, magic_T magic_val)
+ {
// remove trailing \v and the like
! while (len >= 2 && p[len - 2] == '\\'
! && vim_strchr((char_u *)"mMvVcCZ", p[len - 1]) != NULL)
! len -= 2;
!
! // true, if the pattern is empty, or the pattern ends with \| and magic is
! // set (or it ends with '|' and very magic is set)
! return len == 0 || (len > 1
! && ((p[len - 2] == '\\'
! && p[len - 1] == '|' && magic_val == MAGIC_ON)
! || (p[len - 2] != '\\'
! && p[len - 1] == '|' && magic_val == MAGIC_ALL)));
}

// Struct to store the viewstate during 'incsearch' highlighting.
***************
*** 149,155 ****
pos_T match_end;
int did_incsearch;
int incsearch_postponed;
! magic_T magic_overruled_save;
} incsearch_state_T;

static void
--- 171,177 ----
pos_T match_end;
int did_incsearch;
int incsearch_postponed;
! optmagic_T magic_overruled_save;
} incsearch_state_T;

static void
***************
*** 207,212 ****
--- 229,235 ----
pos_T save_cursor;
int use_last_pat;
int retval = FALSE;
+ magic_T magic = 0;

*skiplen = 0;
*patlen = ccline.cmdlen;
***************
*** 252,260 ****
|| STRNCMP(cmd, "vglobal", p - cmd) == 0)
{
if (*cmd == 's' && cmd[1] == 'm')
! magic_overruled = MAGIC_ON;
else if (*cmd == 's' && cmd[1] == 'n')
! magic_overruled = MAGIC_OFF;
}
else if (STRNCMP(cmd, "sort", MAX(p - cmd, 3)) == 0)
{
--- 275,283 ----
|| STRNCMP(cmd, "vglobal", p - cmd) == 0)
{
if (*cmd == 's' && cmd[1] == 'm')
! magic_overruled = OPTION_MAGIC_ON;
else if (*cmd == 's' && cmd[1] == 'n')
! magic_overruled = OPTION_MAGIC_OFF;
}
else if (STRNCMP(cmd, "sort", MAX(p - cmd, 3)) == 0)
{
***************
*** 288,294 ****
p = skipwhite(p);
delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++;
*search_delim = delim;
! end = skip_regexp(p, delim, magic_isset());

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

--- 311,317 ----
p = skipwhite(p);
delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++;
*search_delim = delim;
! end = skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic);

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

***************
*** 302,308 ****
int empty;

*end = NUL;
! empty = empty_pattern(p);
*end = c;
if (empty)
goto theend;
--- 325,331 ----
int empty;

*end = NUL;
! empty = empty_pattern_magic(p, STRLEN(p), magic);
*end = c;
if (empty)
goto theend;
***************
*** 535,541 ****
{
next_char = ccline.cmdbuff[skiplen + patlen];
ccline.cmdbuff[skiplen + patlen] = NUL;
! if (empty_pattern(ccline.cmdbuff) && !no_hlsearch)
{
redraw_all_later(SOME_VALID);
set_no_hlsearch(TRUE);
--- 558,565 ----
{
next_char = ccline.cmdbuff[skiplen + patlen];
ccline.cmdbuff[skiplen + patlen] = NUL;
! if (empty_pattern(ccline.cmdbuff + skiplen, search_delim)
! && !no_hlsearch)
{
redraw_all_later(SOME_VALID);
set_no_hlsearch(TRUE);
*** ../vim-8.2.2294/src/globals.h 2020-12-28 18:25:56.796886014 +0100
--- src/globals.h 2021-01-04 11:50:48.369544048 +0100
***************
*** 1945,1951 ****
#define FOR_ALL_LIST_ITEMS(l, li) \
for ((li) = (l)->lv_first; (li) != NULL; (li) = (li)->li_next)

! // While executing a regexp and set to MAGIC_ON or MAGIC_OFF this overrules
! // p_magic. Otherwise set to MAGIC_NOT_SET.
!
! EXTERN magic_T magic_overruled INIT(= MAGIC_NOT_SET);
--- 1945,1950 ----
#define FOR_ALL_LIST_ITEMS(l, li) \
for ((li) = (l)->lv_first; (li) != NULL; (li) = (li)->li_next)

! // While executing a regexp and set to OPTION_MAGIC_ON or OPTION_MAGIC_OFF this
! // overrules p_magic. Otherwise set to OPTION_MAGIC_NOT_SET.
! EXTERN optmagic_T magic_overruled INIT(= OPTION_MAGIC_NOT_SET);
*** ../vim-8.2.2294/src/option.c 2021-01-02 16:53:08.294010035 +0100
--- src/option.c 2021-01-04 11:31:55.813633440 +0100
***************
*** 7009,7017 ****
{
switch (magic_overruled)
{
! case MAGIC_ON: return TRUE;
! case MAGIC_OFF: return FALSE;
! case MAGIC_NOT_SET: break;
}
#ifdef FEAT_EVAL
if (in_vim9script())
--- 7009,7017 ----
{
switch (magic_overruled)
{
! case OPTION_MAGIC_ON: return TRUE;
! case OPTION_MAGIC_OFF: return FALSE;
! case OPTION_MAGIC_NOT_SET: break;
}
#ifdef FEAT_EVAL
if (in_vim9script())
*** ../vim-8.2.2294/src/tag.c 2020-12-21 19:59:04.569197722 +0100
--- src/tag.c 2021-01-04 11:50:22.621635476 +0100
***************
*** 3312,3318 ****
int keep_help) // keep help flag (FALSE for cscope)
{
int save_secure;
! int save_magic_overruled;
int save_p_ws, save_p_scs, save_p_ic;
linenr_T save_lnum;
char_u *str;
--- 3312,3318 ----
int keep_help) // keep help flag (FALSE for cscope)
{
int save_secure;
! optmagic_T save_magic_overruled;
int save_p_ws, save_p_scs, save_p_ic;
linenr_T save_lnum;
char_u *str;
***************
*** 3505,3511 ****
++sandbox;
#endif
save_magic_overruled = magic_overruled;
! magic_overruled = MAGIC_OFF; // always execute with 'nomagic'
#ifdef FEAT_SEARCH_EXTRA
// Save value of no_hlsearch, jumping to a tag is not a real search
save_no_hlsearch = no_hlsearch;
--- 3505,3511 ----
++sandbox;
#endif
save_magic_overruled = magic_overruled;
! magic_overruled = OPTION_MAGIC_OFF; // always execute with 'nomagic'
#ifdef FEAT_SEARCH_EXTRA
// Save value of no_hlsearch, jumping to a tag is not a real search
save_no_hlsearch = no_hlsearch;
*** ../vim-8.2.2294/src/proto/regexp.pro 2020-04-20 19:42:06.590078519 +0200
--- src/proto/regexp.pro 2021-01-04 11:45:40.958637924 +0100
***************
*** 2,8 ****
int re_multiline(regprog_T *prog);
char_u *skip_regexp(char_u *startp, int delim, int magic);
char_u *skip_regexp_err(char_u *startp, int delim, int magic);
! char_u *skip_regexp_ex(char_u *startp, int dirc, int magic, char_u **newp, int *dropped);
reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
void unref_extmatch(reg_extmatch_T *em);
char_u *regtilde(char_u *source, int magic);
--- 2,8 ----
int re_multiline(regprog_T *prog);
char_u *skip_regexp(char_u *startp, int delim, int magic);
char_u *skip_regexp_err(char_u *startp, int delim, int magic);
! char_u *skip_regexp_ex(char_u *startp, int dirc, int magic, char_u **newp, int *dropped, magic_T *magic_val);
reg_extmatch_T *ref_extmatch(reg_extmatch_T *em);
void unref_extmatch(reg_extmatch_T *em);
char_u *regtilde(char_u *source, int magic);
*** ../vim-8.2.2294/src/regexp.c 2021-01-02 17:43:44.021175836 +0100
--- src/regexp.c 2021-01-04 11:46:30.206462289 +0100
***************
*** 304,314 ****
static int had_eol; // TRUE when EOL found by vim_regcomp()
#endif

! static int reg_magic; // magicness of the pattern:
! #define MAGIC_NONE 1 // "\V" very unmagic
! #define MAGIC_OFF 2 // "\M" or 'magic' off
! #define MAGIC_ON 3 // "\m" or 'magic'
! #define MAGIC_ALL 4 // "\v" very magic

static int reg_string; // matching with a string instead of a buffer
// line
--- 304,310 ----
static int had_eol; // TRUE when EOL found by vim_regcomp()
#endif

! static magic_T reg_magic; // magicness of the pattern

static int reg_string; // matching with a string instead of a buffer
// line
***************
*** 548,554 ****
int delim,
int magic)
{
! return skip_regexp_ex(startp, delim, magic, NULL, NULL);
}

/*
--- 544,550 ----
int delim,
int magic)
{
! return skip_regexp_ex(startp, delim, magic, NULL, NULL, NULL);
}

/*
***************
*** 577,582 ****
--- 573,579 ----
* expression and change "\?" to "?". If "*newp" is not NULL the expression
* is changed in-place.
* If a "\?" is changed to "?" then "dropped" is incremented, unless NULL.
+ * If "magic_val" is not NULL, returns the effective magicness of the pattern
*/
char_u *
skip_regexp_ex(
***************
*** 584,592 ****
int dirc,
int magic,
char_u **newp,
! int *dropped)
{
! int mymagic;
char_u *p = startp;

if (magic)
--- 581,590 ----
int dirc,
int magic,
char_u **newp,
! int *dropped,
! magic_T *magic_val)
{
! magic_T mymagic;
char_u *p = startp;

if (magic)
***************
*** 632,637 ****
--- 630,637 ----
mymagic = MAGIC_NONE;
}
}
+ if (magic_val != NULL)
+ *magic_val = mymagic;
return p;
}

*** ../vim-8.2.2294/src/search.c 2021-01-02 18:31:10.887220293 +0100
--- src/search.c 2021-01-04 11:31:55.817633424 +0100
***************
*** 1342,1348 ****
*/
ps = strcopy;
p = skip_regexp_ex(pat, search_delim, magic_isset(),
! &strcopy, NULL);
if (strcopy != ps)
{
// made a copy of "pat" to change "\?" to "?"
--- 1342,1348 ----
*/
ps = strcopy;
p = skip_regexp_ex(pat, search_delim, magic_isset(),
! &strcopy, NULL, NULL);
if (strcopy != ps)
{
// made a copy of "pat" to change "\?" to "?"
*** ../vim-8.2.2294/src/structs.h 2021-01-02 15:41:00.189079039 +0100
--- src/structs.h 2021-01-04 11:45:04.562767852 +0100
***************
*** 4321,4328 ****
// with iconv() to be able to allocate a buffer.
#define ICONV_MULT 8

typedef enum {
! MAGIC_NOT_SET, // p_magic not overruled
! MAGIC_ON, // magic on inside regexp
! MAGIC_OFF // magic off inside regexp
} magic_T;
--- 4321,4340 ----
// with iconv() to be able to allocate a buffer.
#define ICONV_MULT 8

+ // Used for "magic_overruled".
typedef enum {
! OPTION_MAGIC_NOT_SET, // p_magic not overruled
! OPTION_MAGIC_ON, // magic on inside regexp
! OPTION_MAGIC_OFF // magic off inside regexp
! } optmagic_T;
!
! // Magicness of a pattern, used by regexp code.
! // The order and values matter:
! // magic <= MAGIC_OFF includes MAGIC_NONE
! // magic >= MAGIC_ON includes MAGIC_ALL
! typedef enum {
! MAGIC_NONE = 1, // "\V" very unmagic
! MAGIC_OFF = 2, // "\M" or 'magic' off
! MAGIC_ON = 3, // "\m" or 'magic'
! MAGIC_ALL = 4 // "\v" very magic
} magic_T;
*** ../vim-8.2.2294/src/vim9compile.c 2021-01-03 21:53:28.279020545 +0100
--- src/vim9compile.c 2021-01-04 11:31:55.817633424 +0100
***************
*** 7048,7054 ****
// Push v:exception, push {expr} and MATCH
generate_instr_type(cctx, ISN_PUSHEXC, &t_string);

! end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped);
if (*end != *p)
{
semsg(_(e_separator_mismatch_str), p);
--- 7048,7054 ----
// Push v:exception, push {expr} and MATCH
generate_instr_type(cctx, ISN_PUSHEXC, &t_string);

! end = skip_regexp_ex(p + 1, *p, TRUE, &tofree, &dropped, NULL);
if (*end != *p)
{
semsg(_(e_separator_mismatch_str), p);
***************
*** 7372,7378 ****
{
int delim = *eap->arg;

! p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL);
if (*p == delim)
{
eap->arg = p + 1;
--- 7372,7378 ----
{
int delim = *eap->arg;

! p = skip_regexp_ex(eap->arg + 1, delim, TRUE, NULL, NULL, NULL);
if (*p == delim)
{
eap->arg = p + 1;
*** ../vim-8.2.2294/src/testdir/dumps/Test_incsearch_sub_01.dump 2021-01-04 12:41:37.447957673 +0100
--- src/testdir/dumps/Test_incsearch_sub_01.dump 2021-01-04 11:31:55.817633424 +0100
***************
*** 0 ****
--- 1,9 ----
+ |f+0&#ffffff0|o@1| |1| @64
+ |f|o@1| |2| @64
+ |f|o@1| |3| @64
+ |f|o@1| |4| @64
+ |a|b|c|||d|e|f| @62
+ |~+0#4040ff13&| @68
+ |~| @68
+ |~| @68
+ |:+0#0000000&|%|s|/|\|v|a|b|c||> @59
*** ../vim-8.2.2294/src/testdir/dumps/Test_incsearch_sub_02.dump 2021-01-04 12:41:37.451957653 +0100
--- src/testdir/dumps/Test_incsearch_sub_02.dump 2021-01-04 11:31:55.817633424 +0100
***************
*** 0 ****
--- 1,9 ----
+ |f+0&#ffffff0|o@1| |1| @64
+ |f|o@1| |2| @64
+ |f|o@1| |3| @64
+ |f|o@1| |4| @64
+ |a|b|c|||d|e|f| @62
+ |~+0#4040ff13&| @68
+ |~| @68
+ |~| @68
+ |:+0#0000000&|1|,|5|s|/|\|v||> @60
*** ../vim-8.2.2294/src/testdir/test_search.vim 2020-11-25 17:41:16.453206458 +0100
--- src/testdir/test_search.vim 2021-01-04 11:31:55.817633424 +0100
***************
*** 1808,1811 ****
--- 1808,1840 ----
bw
endfunc

+ func Test_incsearch_substitute_dump2()
+ CheckOption incsearch
+ CheckScreendump
+
+ call writefile([
+ \ 'set incsearch hlsearch scrolloff=0',
+ \ 'for n in range(1, 4)',
+ \ ' call setline(n, "foo " . n)',
+ \ 'endfor',
+ \ 'call setline(5, "abc|def")',
+ \ '3',
+ \ ], 'Xis_subst_script2')
+ let buf = RunVimInTerminal('-S Xis_subst_script2', {'rows': 9, 'cols': 70})
+
+ call term_sendkeys(buf, ':%s/\vabc|')
+ sleep 100m
+ call VerifyScreenDump(buf, 'Test_incsearch_sub_01', {})
+ call term_sendkeys(buf, "\<Esc>")
+
+ " The following should not be highlighted
+ call term_sendkeys(buf, ':1,5s/\v|')
+ sleep 100m
+ call VerifyScreenDump(buf, 'Test_incsearch_sub_02', {})
+
+
+ call StopVimInTerminal(buf)
+ call delete('Xis_subst_script2')
+ endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.2.2294/src/version.c 2021-01-04 10:47:21.698153964 +0100
--- src/version.c 2021-01-04 11:33:53.941195043 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2295,
/**/

--
From "know your smileys":
:-F Bucktoothed vampire with one tooth missing

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages