refactor(ex_cmds): use function arguments for magic behavior

Now this was a cargo cult anti-pattern to write home about.
Doing painful save-and-restore bookkeeping around a separate
`magic_overruled` decoy global is just as messy as doing painful
save-and-restore logic around `p_magic` itself. only that now you need
to wrap every access to the effective value in a function call.

This replaces this with a marvellous new Clean Code technique™:
passing in the intended behavior as a function parameter to functions
where either the option or an explicit value might be used.
This commit is contained in:
bfredl
2026-08-06 14:18:57 +02:00
parent 5287a04be4
commit 344ea602f6
19 changed files with 79 additions and 126 deletions

View File

@@ -362,7 +362,7 @@ static void arglist_del_files(garray_T *alist_ga)
if (p == NULL) {
break;
}
regmatch.regprog = vim_regcomp(p, magic_isset() ? RE_MAGIC : 0);
regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
if (regmatch.regprog == NULL) {
xfree(p);
break;

View File

@@ -2451,7 +2451,7 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted,
}
regmatch_T regmatch;
regmatch.regprog = vim_regcomp(p, magic_isset() ? RE_MAGIC : 0);
regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0);
FOR_ALL_BUFFERS_BACKWARDS(buf) {
if (regmatch.regprog == NULL) {

View File

@@ -1724,7 +1724,7 @@ static const char *set_context_in_match_cmd(expand_T *xp, const char *arg)
arg = skipwhite(skiptowhite(arg));
if (*arg != NUL) {
xp->xp_context = EXPAND_NOTHING;
arg = skip_regexp((char *)arg + 1, (uint8_t)(*arg), magic_isset());
arg = skip_regexp((char *)arg + 1, (uint8_t)(*arg), p_magic);
}
}
return find_nextcmd(arg);
@@ -1760,7 +1760,7 @@ static const char *find_cmd_after_substitute_cmd(const char *arg)
if (delim) {
// Skip "from" part.
arg++;
arg = skip_regexp((char *)arg, delim, magic_isset());
arg = skip_regexp((char *)arg, delim, p_magic);
if (arg[0] != NUL && arg[0] == delim) {
// Skip "to" part.
@@ -1993,7 +1993,8 @@ static void set_context_with_pattern(expand_T *xp)
emsg_off++;
int skiplen = 0;
int dummy, patlen;
int retval = parse_pattern_and_range(&pre_incsearch_pos, &dummy, &skiplen, &patlen);
bool magic = p_magic;
int retval = parse_pattern_and_range(&pre_incsearch_pos, &dummy, &skiplen, &patlen, &magic);
emsg_off--;
// Check if cursor is within search pattern
@@ -3184,7 +3185,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
}
if (!fuzzy) {
regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
if (regmatch.regprog == NULL) {
xfree(tofree);
return FAIL;
@@ -4357,7 +4358,7 @@ static int expand_pattern_in_buf(char *pat, Direction dir, char ***matches, int
msg_silent++;
int found_new_match = searchit(NULL, curbuf, &cur_match_pos,
&end_match_pos, dir, pat, (size_t)pat_len, 1L,
search_flags, RE_LAST, NULL);
search_flags, RE_LAST, p_magic, NULL);
msg_silent--;
emsg_off--;

View File

@@ -5558,7 +5558,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
// Repeat until {skip} returns false.
while (true) {
subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, (char *)pat, patlen, 1,
options, RE_SEARCH, &sia);
options, RE_SEARCH, p_magic, &sia);
// finding the first match again means there is no match where {skip}
// evaluates to zero.
if (firstpos.lnum != 0 && equalpos(pos, firstpos)) {
@@ -6069,7 +6069,7 @@ int do_searchpair(const char *spat, const char *mpat, const char *epat, int dir,
};
int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, patlen, 1,
options, RE_SEARCH, &sia);
options, RE_SEARCH, true, &sia);
if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) {
// didn't find it or found the first match again: FAIL
break;

View File

@@ -3367,7 +3367,7 @@ static bool sub_joining_lines(exarg_T *eap, String pat, const char *sub, const c
if (save) {
if (!keeppatterns) {
save_re_pat(RE_SUBST, pat.data, pat.size, magic_isset());
save_re_pat(RE_SUBST, pat.data, pat.size, p_magic);
}
// put pattern in history
add_to_history(HIST_SEARCH, pat.data, pat.size, true, NUL);
@@ -3613,7 +3613,7 @@ static int do_sub(exarg_T *eap, proftime_T tm, const int cmdpreview_ns,
which_pat = RE_LAST; // use last used regexp
delimiter = (uint8_t)(*cmd++); // remember delimiter character
pat.data = cmd; // remember start of search pat
cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), &eap->arg, NULL, NULL);
cmd = skip_regexp_ex(cmd, delimiter, p_magic, &eap->arg, NULL, NULL);
pat.size = (size_t)(cmd - pat.data);
if (cmd[0] == delimiter) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
@@ -3700,8 +3700,10 @@ static int do_sub(exarg_T *eap, proftime_T tm, const int cmdpreview_ns,
return 0;
}
bool magic = ((eap->cmdidx == CMD_smagic)
? true : ((eap->cmdidx == CMD_snomagic) ? false : p_magic));
if (search_regcomp(pat.data, pat.size, NULL, RE_SUBST, which_pat,
(cmdpreview_ns > 0 ? 0 : SEARCH_HIS), &regmatch) == FAIL) {
(cmdpreview_ns > 0 ? 0 : SEARCH_HIS), magic, &regmatch) == FAIL) {
if (subflags.do_error) {
emsg(_(e_invcmd));
}
@@ -3730,7 +3732,7 @@ static int do_sub(exarg_T *eap, proftime_T tm, const int cmdpreview_ns,
xfree(sub);
sub = p;
} else {
char *p = regtilde(sub, magic_isset(), cmdpreview_ns > 0);
char *p = regtilde(sub, p_magic, cmdpreview_ns > 0);
if (p != sub) {
xfree(sub);
sub = p;
@@ -4118,7 +4120,7 @@ static int do_sub(exarg_T *eap, proftime_T tm, const int cmdpreview_ns,
sub_firstlnum - regmatch.startpos[0].lnum,
sub, sub_firstline.data, 0,
REGSUB_BACKSLASH
| (magic_isset() ? REGSUB_MAGIC : 0));
| (p_magic ? REGSUB_MAGIC : 0));
textlock--;
// If getting the substitute string caused an error, don't do
@@ -4171,7 +4173,7 @@ static int do_sub(exarg_T *eap, proftime_T tm, const int cmdpreview_ns,
sub_firstlnum - regmatch.startpos[0].lnum,
sub, new_end, (int)sublen,
REGSUB_COPY | REGSUB_BACKSLASH
| (magic_isset() ? REGSUB_MAGIC : 0));
| (p_magic ? REGSUB_MAGIC : 0));
if (n > 0) {
new_start.size += n - 1; // remove 1 for the NUL
}
@@ -4656,7 +4658,7 @@ void ex_global(exarg_T *eap)
delim = *cmd; // get the delimiter
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);
cmd = skip_regexp_ex(cmd, delim, p_magic, &eap->arg, NULL, NULL);
if (cmd[0] == delim) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
@@ -4665,7 +4667,7 @@ void ex_global(exarg_T *eap)
char *used_pat;
if (search_regcomp(pat, patlen, &used_pat, RE_BOTH, which_pat,
SEARCH_HIS, &regmatch) == FAIL) {
SEARCH_HIS, p_magic, &regmatch) == FAIL) {
emsg(_(e_invcmd));
return;
}

View File

@@ -2558,8 +2558,8 @@ M.cmds = {
command = 'smagic',
flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, PREVIEW),
addr_type = 'ADDR_LINES',
func = 'ex_submagic',
preview_func = 'ex_submagic_preview',
func = 'ex_substitute',
preview_func = 'ex_substitute_preview',
},
{
command = 'smap',
@@ -2589,8 +2589,8 @@ M.cmds = {
command = 'snomagic',
flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, BUFLOCK_OK, LOCK_OK, PREVIEW),
addr_type = 'ADDR_LINES',
func = 'ex_submagic',
preview_func = 'ex_submagic_preview',
func = 'ex_substitute',
preview_func = 'ex_substitute_preview',
},
{
command = 'snoremap',

View File

@@ -3525,7 +3525,7 @@ linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool skip,
goto error;
}
if (skip) { // skip "/pat/"
cmd = skip_regexp(cmd, c, magic_isset());
cmd = skip_regexp(cmd, c, p_magic);
if (*cmd == c) {
cmd++;
}
@@ -3550,7 +3550,7 @@ linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool skip,
curwin->w_cursor.col = (c == '/' && curwin->w_cursor.lnum > 0) ? MAXCOL : 0;
Search.cmdlen = 0;
flags = silent ? SEARCH_KEEP : SEARCH_HIS | SEARCH_MSG;
if (!do_search(NULL, c, c, cmd, strlen(cmd), 1, flags, NULL)) {
if (!do_search(NULL, c, c, cmd, strlen(cmd), 1, flags, p_magic, NULL)) {
curwin->w_cursor = pos;
cmd = NULL;
goto error;
@@ -3587,7 +3587,7 @@ linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool skip,
pos.coladd = 0;
if (searchit(curwin, curbuf, &pos, NULL,
*cmd == '?' ? BACKWARD : FORWARD,
"", 0, 1, SEARCH_MSG, i, NULL) != FAIL) {
"", 0, 1, SEARCH_MSG, i, p_magic, NULL) != FAIL) {
lnum = pos.lnum;
} else {
cmd = NULL;
@@ -6666,28 +6666,6 @@ void ex_may_print(exarg_T *eap)
}
}
/// ":smagic" and ":snomagic".
static void ex_submagic(exarg_T *eap)
{
const optmagic_T saved = magic_overruled;
magic_overruled = eap->cmdidx == CMD_smagic ? OPTION_MAGIC_ON : OPTION_MAGIC_OFF;
ex_substitute(eap);
magic_overruled = saved;
}
/// ":smagic" and ":snomagic" preview callback.
static int ex_submagic_preview(exarg_T *eap, int cmdpreview_ns, handle_T cmdpreview_bufnr)
{
const optmagic_T saved = magic_overruled;
magic_overruled = eap->cmdidx == CMD_smagic ? OPTION_MAGIC_ON : OPTION_MAGIC_OFF;
int retv = ex_substitute_preview(eap, cmdpreview_ns, cmdpreview_bufnr);
magic_overruled = saved;
return retv;
}
/// ":join".
static void ex_join(exarg_T *eap)
{
@@ -7363,7 +7341,7 @@ static void ex_findpat(exarg_T *eap)
if (*eap->arg == '/') { // Match regexp, not just whole words
whole = false;
eap->arg++;
char *p = skip_regexp(eap->arg, '/', magic_isset());
char *p = skip_regexp(eap->arg, '/', p_magic);
if (*p) {
*p++ = NUL;
p = skipwhite(p);

View File

@@ -119,7 +119,6 @@ typedef struct {
pos_T match_end;
bool did_incsearch;
bool incsearch_postponed;
optmagic_T magic_overruled_save;
} incsearch_state_T;
typedef struct {
@@ -250,7 +249,6 @@ static void init_incsearch_state(incsearch_state_T *s)
s->match_start = curwin->w_cursor;
s->did_incsearch = false;
s->incsearch_postponed = false;
s->magic_overruled_save = magic_overruled;
clearpos(&s->match_end);
s->save_cursor = curwin->w_cursor; // may be restored later
s->search_start = curwin->w_cursor;
@@ -273,8 +271,9 @@ static void set_search_match(pos_T *t)
/// Parses the :[range]s/foo like commands and returns details needed for
/// incsearch and wildmenu completion.
/// Returns true if pattern is valid.
/// Sets skiplen, patlen, Search.first_line, and Search.last_line.
bool parse_pattern_and_range(pos_T *incsearch_start, int *search_delim, int *skiplen, int *patlen)
/// Sets skiplen, patlen, Search.first_line, and Search.last_line and magic if overruled.
bool parse_pattern_and_range(pos_T *incsearch_start, int *search_delim, int *skiplen, int *patlen,
bool *is_magic)
FUNC_ATTR_NONNULL_ALL
{
char *p;
@@ -317,9 +316,9 @@ bool parse_pattern_and_range(pos_T *incsearch_start, int *search_delim, int *ski
|| strncmp(cmd, "snomagic", (size_t)MAX(p - cmd, 3)) == 0
|| strncmp(cmd, "vglobal", (size_t)(p - cmd)) == 0) {
if (*cmd == 's' && cmd[1] == 'm') {
magic_overruled = OPTION_MAGIC_ON;
*is_magic = true;
} else if (*cmd == 's' && cmd[1] == 'n') {
magic_overruled = OPTION_MAGIC_OFF;
*is_magic = false;
}
} else if (strncmp(cmd, "sort", (size_t)MAX(p - cmd, 3)) == 0
|| strncmp(cmd, "uniq", (size_t)MAX(p - cmd, 3)) == 0) {
@@ -356,7 +355,7 @@ bool parse_pattern_and_range(pos_T *incsearch_start, int *search_delim, int *ski
int delim = (delim_optional && vim_isIDc((uint8_t)(*p))) ? ' ' : *p++;
*search_delim = delim;
char *end = skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic);
char *end = skip_regexp_ex(p, delim, *is_magic, NULL, NULL, &magic);
bool use_last_pat = end == p && *end == delim;
if (end == p && !use_last_pat) {
@@ -401,7 +400,7 @@ bool parse_pattern_and_range(pos_T *incsearch_start, int *search_delim, int *ski
/// Sets Search.first_line and Search.last_line to the address range.
/// May change the last search pattern.
static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *is_state,
int *skiplen, int *patlen)
int *skiplen, int *patlen, bool *magic)
{
bool retval = false;
@@ -427,7 +426,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
emsg_off++;
retval = parse_pattern_and_range(&is_state->search_start, search_delim,
skiplen, patlen);
skiplen, patlen, magic);
emsg_off--;
return retval;
@@ -438,12 +437,13 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
{
int skiplen, patlen;
int search_delim;
bool magic = p_magic;
// 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, &search_delim, s, &skiplen, &patlen)) {
if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen, &patlen, &magic)) {
restore_last_search_pattern();
finish_incsearch_highlighting(false, s, true);
return;
@@ -497,7 +497,7 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
emsg_off++; // So it doesn't beep if bad expr
found = do_search(NULL, firstc == ':' ? '/' : firstc, search_delim,
ccline.cmdbuff + skiplen, (size_t)patlen, count,
search_flags, &sia);
search_flags, magic, &sia);
emsg_off--;
ccline.cmdbuff[skiplen + patlen] = next_char;
if (curwin->w_cursor.lnum < Search.first_line
@@ -590,6 +590,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
{
int skiplen, patlen;
int search_delim;
bool magic = p_magic;
// Parsing range may already set the last search pattern.
// NOTE: must call restore_last_search_pattern() before returning!
@@ -597,7 +598,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
// Add a character from under the cursor for 'incsearch'
if (!do_incsearch_highlighting(firstc, &search_delim, s, &skiplen,
&patlen)) {
&patlen, &magic)) {
restore_last_search_pattern();
return FAIL;
}
@@ -615,7 +616,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
*c = mb_tolower(*c);
}
if (*c == search_delim
|| vim_strchr((magic_isset() ? "\\~^$.*[" : "\\^$"), *c) != NULL) {
|| vim_strchr((p_magic ? "\\~^$.*[" : "\\^$"), *c) != NULL) {
// put a backslash before special characters
stuffcharReadbuff(*c);
*c = '\\';
@@ -661,8 +662,6 @@ static void finish_incsearch_highlighting(bool gotesc, incsearch_state_T *s,
Search.first_line = 0;
Search.last_line = MAXLNUM;
magic_overruled = s->magic_overruled_save;
validate_cursor(curwin); // needed for TAB
status_redraw_all();
redraw_all_later(UPD_SOME_VALID);
@@ -1556,13 +1555,14 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s
FUNC_ATTR_NONNULL_ALL
{
int skiplen, patlen, search_delim;
bool magic = p_magic;
// 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, &search_delim, s, &skiplen,
&patlen)) {
&patlen, &magic)) {
restore_last_search_pattern();
return OK;
}
@@ -1607,7 +1607,7 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s
int found = searchit(curwin, curbuf, &t, NULL,
next_match ? FORWARD : BACKWARD,
searchstr, searchstrlen, count, search_flags,
RE_SEARCH, NULL);
RE_SEARCH, magic, NULL);
emsg_off--;
if (dircp != NULL) {
*dircp = (char)search_delim;
@@ -2412,7 +2412,7 @@ static bool empty_pattern(char *p, size_t len, int delim)
magic_T magic_val = MAGIC_ON;
if (len > 0) {
skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val);
skip_regexp_ex(p, delim, p_magic, NULL, NULL, &magic_val);
} else {
return true;
}

View File

@@ -711,10 +711,6 @@ EXTERN bool headless_mode INIT( = false);
/// Only filled for Win32.
EXTERN char windowsVersion[20] INIT( = { 0 });
/// 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);
/// Skip win_fix_scroll() call for 'splitkeep' when closing tab page.
EXTERN bool skip_win_fix_scroll INIT( = false);
/// Skip update_topline() call while executing win_fix_scroll().

View File

@@ -1964,7 +1964,7 @@ static void ins_compl_dictionaries(char *dict_start, char *pat, int flags, bool
xfree(pat_esc);
xfree(ptr);
} else {
regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
if (regmatch.regprog == NULL) {
goto theend;
}
@@ -4401,7 +4401,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
NULL, compl_direction, compl_pattern.data,
compl_pattern.size,
1, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
1, SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, p_magic, NULL);
}
msg_silent--;
if (!compl_started || st->set_match_pos) {
@@ -6440,7 +6440,7 @@ static unsigned quote_meta(char *dest, char *src, int len)
}
FALLTHROUGH;
case '~':
if (!magic_isset()) { // quote these only if magic is set
if (!p_magic) { // quote these only if magic is set
break;
}
FALLTHROUGH;

View File

@@ -2368,7 +2368,7 @@ bool find_decl(char *ptr, size_t len, bool locally, bool thisblock, int flags_ar
clearpos(&found_pos);
while (true) {
t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD,
pat, patlen, 1, searchflags, RE_LAST, NULL);
pat, patlen, 1, searchflags, RE_LAST, false, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum) {
t = false; // match after start is failure too
}
@@ -3483,9 +3483,9 @@ static void nv_ident(cmdarg_T *cap)
} else {
char *aux_ptr;
if (cmdchar == '*') {
aux_ptr = (magic_isset() ? "/.*~[^$\\" : "/^$\\");
aux_ptr = (p_magic ? "/.*~[^$\\" : "/^$\\");
} else if (cmdchar == '#') {
aux_ptr = (magic_isset() ? "/?.*~[^$\\" : "/?^$\\");
aux_ptr = (p_magic ? "/?.*~[^$\\" : "/?^$\\");
} else if (tag_cmd) {
if (strcmp(curbuf->b_p_ft, "help") == 0) {
// ":help" handles unescaped argument
@@ -3991,7 +3991,7 @@ static int normal_search(cmdarg_T *cap, int dir, char *pat, size_t patlen, int o
CLEAR_FIELD(sia);
int i = do_search(cap->oap, dir, dir, pat, patlen, cap->count1,
opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, &sia);
opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, p_magic, &sia);
if (wrapped != NULL) {
*wrapped = sia.sa_wrapped;
}

View File

@@ -6779,20 +6779,6 @@ int fill_culopt_flags(char *val, win_T *wp)
return OK;
}
/// Get the value of 'magic' taking "magic_overruled" into account.
bool magic_isset(void)
{
switch (magic_overruled) {
case OPTION_MAGIC_ON:
return true;
case OPTION_MAGIC_OFF:
return false;
case OPTION_MAGIC_NOT_SET:
break;
}
return p_magic;
}
/// Set the callback function value for an option that accepts a function name,
/// lambda, et al. (e.g. 'operatorfunc', 'tagfunc', etc.)
/// @return OK if the option is successfully set to a function, otherwise FAIL

View File

@@ -3090,7 +3090,7 @@ static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char qf_viscol, char
// 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, strlen(qf_pattern), 1, SEARCH_KEEP, NULL)) {
if (!do_search(NULL, '/', '/', qf_pattern, strlen(qf_pattern), 1, SEARCH_KEEP, p_magic, NULL)) {
curwin->w_cursor = save_cursor;
}
}

View File

@@ -41,13 +41,6 @@ typedef struct {
colnr_T rmm_maxcol; ///< when not zero: maximum column
} regmmatch_T;
/// 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

View File

@@ -146,10 +146,9 @@ typedef struct {
///
/// @return FAIL if failed, OK otherwise.
int search_regcomp(char *pat, size_t patlen, char **used_pat, int pat_save, int pat_use,
int options, regmmatch_T *regmatch)
int options, bool magic, regmmatch_T *regmatch)
{
rc_did_emsg = false;
int magic = magic_isset();
// If no pattern given, use a previously defined pattern.
if (pat == NULL || *pat == NUL) {
@@ -409,7 +408,7 @@ bool pat_has_uppercase(char *pat)
magic_T magic_val = MAGIC_ON;
// get the magicness of the pattern
skip_regexp_ex(pat, NUL, magic_isset(), NULL, NULL, &magic_val);
skip_regexp_ex(pat, NUL, p_magic, NULL, NULL, &magic_val);
while (*p != NUL) {
const int l = utfc_ptr2len(p);
@@ -546,7 +545,7 @@ void last_pat_prog(regmmatch_T *regmatch)
return;
}
emsg_off++; // So it doesn't beep if bad expr
search_regcomp("", 0, NULL, 0, last_idx, SEARCH_KEEP, regmatch);
search_regcomp("", 0, NULL, 0, last_idx, SEARCH_KEEP, p_magic, regmatch);
emsg_off--;
}
@@ -574,7 +573,8 @@ void last_pat_prog(regmmatch_T *regmatch)
/// the index of the first matching
/// subpattern plus one; one if there was none.
int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, char *pat,
size_t patlen, int count, int options, int pat_use, searchit_arg_T *extra_arg)
size_t patlen, int count, int options, int pat_use, bool magic,
searchit_arg_T *extra_arg)
{
int found;
linenr_T lnum; // no init to shut up Apollo cc
@@ -603,7 +603,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
}
if (search_regcomp(pat, patlen, NULL, RE_SEARCH, pat_use,
(options & (SEARCH_HIS + SEARCH_KEEP)), &regmatch) == FAIL) {
(options & (SEARCH_HIS + SEARCH_KEEP)), magic, &regmatch) == FAIL) {
if ((options & SEARCH_MSG) && !rc_did_emsg) {
semsg(_("E383: Invalid search string: %s"), mr_pattern);
}
@@ -1056,7 +1056,7 @@ int parse_search_pattern_offset(char **pat, size_t *patlen, int search_delim, in
// Find end of regular expression.
// If there is a matching '/' or '?', toss it.
p = skip_regexp_ex(*pat, search_delim, magic_isset(), strcopy, NULL, NULL);
p = skip_regexp_ex(*pat, search_delim, p_magic, strcopy, NULL, NULL);
if (*strcopy != ps) {
size_t len = strlen(*strcopy);
// made a copy of "pat" to change "\?" to "?"
@@ -1135,7 +1135,7 @@ int parse_search_pattern_offset(char **pat, size_t *patlen, int search_delim, in
///
/// @return 0 for failure, 1 for found, 2 for found and line offset added.
int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, size_t patlen, int count,
int options, searchit_arg_T *sia)
int options, bool magic, searchit_arg_T *sia)
{
char *searchstr;
size_t searchstrlen;
@@ -1384,7 +1384,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, size_t patlen
& (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG
+ SEARCH_START
+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF)))),
RE_LAST, sia);
RE_LAST, magic, sia);
if (dircp != NULL) {
*dircp = (char)search_delim; // restore second '/' or '?' for normal_cmd()
@@ -2506,7 +2506,7 @@ int current_search(int count, bool forward)
result = searchit(curwin, curbuf, &pos, &end_pos,
(dir ? FORWARD : BACKWARD),
spats[last_idx].pat, spats[last_idx].patlen, i ? count : 1,
SEARCH_KEEP | flags, RE_SEARCH, NULL);
SEARCH_KEEP | flags, RE_SEARCH, p_magic, NULL);
p_ws = old_p_ws;
@@ -2594,7 +2594,7 @@ static int is_zero_width(char *pattern, size_t patternlen, bool move, pos_T *cur
}
if (search_regcomp(pattern, patternlen, NULL, RE_SEARCH, RE_SEARCH,
SEARCH_KEEP, &regmatch) == FAIL) {
SEARCH_KEEP, p_magic, &regmatch) == FAIL) {
return -1;
}
@@ -2609,7 +2609,7 @@ static int is_zero_width(char *pattern, size_t patternlen, bool move, pos_T *cur
flag = SEARCH_START;
}
if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, patternlen, 1,
SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL) {
SEARCH_KEEP + flag, RE_SEARCH, p_magic, NULL) != FAIL) {
int nmatched = 0;
// Zero-width pattern should match somewhere, then we can check if
// start and end are in the same position.
@@ -2779,7 +2779,7 @@ static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchst
}
while (!got_int && searchit(curwin, curbuf, &lastpos, &endpos,
FORWARD, NULL, 0, 1, SEARCH_KEEP, RE_LAST,
NULL) != FAIL) {
p_magic, NULL) != FAIL) {
done_search = true;
// Stop after passing the time limit.
if (timeout > 0 && profile_passed_limit(start)) {
@@ -3000,7 +3000,7 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
snprintf(pat, patsize, whole ? "\\<%.*s\\>" : "%.*s", (int)len, ptr);
// ignore case according to p_ic, p_scs and pat
regmatch.rm_ic = ignorecase(pat);
regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
regmatch.regprog = vim_regcomp(pat, p_magic ? RE_MAGIC : 0);
xfree(pat);
if (regmatch.regprog == NULL) {
goto fpip_end;
@@ -3008,7 +3008,7 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
}
char *inc_opt = (*curbuf->b_p_inc == NUL) ? p_inc : curbuf->b_p_inc;
if (*inc_opt != NUL) {
incl_regmatch.regprog = vim_regcomp(inc_opt, magic_isset() ? RE_MAGIC : 0);
incl_regmatch.regprog = vim_regcomp(inc_opt, p_magic ? RE_MAGIC : 0);
if (incl_regmatch.regprog == NULL) {
goto fpip_end;
}
@@ -3016,7 +3016,7 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
}
if (type == FIND_DEFINE && (*curbuf->b_p_def != NUL || *p_def != NUL)) {
def_regmatch.regprog = vim_regcomp(*curbuf->b_p_def == NUL ? p_def : curbuf->b_p_def,
magic_isset() ? RE_MAGIC : 0);
p_magic ? RE_MAGIC : 0);
if (def_regmatch.regprog == NULL) {
goto fpip_end;
}

View File

@@ -1031,7 +1031,7 @@ static void shada_read(FileDescriptor *const sd_reader, const int flags)
// string is close to useless: you can only use it with :& or :~ and
// thats all because s//~ is not available until the first call to
// regtilde. Vim was not calling this for some reason.
regtilde(cur_entry.data.sub_string.sub, magic_isset(), false);
regtilde(cur_entry.data.sub_string.sub, p_magic, false);
// Do not free shada entry: its allocated memory was saved above.
break;
case kSDItemHistoryEntry:

View File

@@ -2661,7 +2661,7 @@ void ex_spellrepall(exarg_T *eap)
sub_nlines = 0;
curwin->w_cursor.lnum = 0;
while (!got_int) {
if (do_search(NULL, '/', '/', frompat, frompatlen, 1, SEARCH_KEEP, NULL) == 0
if (do_search(NULL, '/', '/', frompat, frompatlen, 1, SEARCH_KEEP, false, NULL) == 0
|| u_save_cursor() == FAIL) {
break;
}

View File

@@ -1017,7 +1017,7 @@ static void prepare_pats(pat_T *pats, bool has_re)
pats->headlen = 0;
} else {
for (pats->headlen = 0; pats->head[pats->headlen] != NUL; pats->headlen++) {
if (vim_strchr(magic_isset() ? ".[~*\\$" : "\\$",
if (vim_strchr(p_magic ? ".[~*\\$" : "\\$",
(uint8_t)pats->head[pats->headlen]) != NULL) {
break;
}
@@ -1029,7 +1029,7 @@ static void prepare_pats(pat_T *pats, bool has_re)
}
if (has_re) {
pats->regmatch.regprog = vim_regcomp(pats->pat, magic_isset() ? RE_MAGIC : 0);
pats->regmatch.regprog = vim_regcomp(pats->pat, p_magic ? RE_MAGIC : 0);
} else {
pats->regmatch.regprog = NULL;
}
@@ -2776,8 +2776,6 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
curwin->w_set_curswant = true;
postponed_split = 0;
const optmagic_T save_magic_overruled = magic_overruled;
magic_overruled = OPTION_MAGIC_OFF; // always execute with 'nomagic'
// Save no_hlsearch: jumping to a tag is not a real search
const bool save_no_hlsearch = Search.no_hlsearch;
@@ -2818,7 +2816,7 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
: 0;
if (do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, pbuflen - 1, 1,
search_options, NULL)) {
search_options, false, NULL)) {
retval = OK;
} else {
int found = 1;
@@ -2826,18 +2824,18 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
// try again, ignore case now
p_ic = true;
if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, pbuflen - 1, 1,
search_options, NULL)) {
search_options, false, NULL)) {
// Failed to find pattern, take a guess: "^func ("
found = 2;
test_for_static(&tagp);
char cc = *tagp.tagname_end;
*tagp.tagname_end = NUL;
pbuflen = (size_t)snprintf(pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
if (!do_search(NULL, '/', '/', pbuf, pbuflen, 1, search_options, NULL)) {
if (!do_search(NULL, '/', '/', pbuf, pbuflen, 1, search_options, false, NULL)) {
// Guess again: "^char * \<func ("
pbuflen = (size_t)snprintf(pbuf, LSIZE, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
tagp.tagname);
if (!do_search(NULL, '/', '/', pbuf, pbuflen, 1, search_options, NULL)) {
if (!do_search(NULL, '/', '/', pbuf, pbuflen, 1, search_options, false, NULL)) {
found = 0;
}
}
@@ -2886,7 +2884,6 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
sandbox--;
}
magic_overruled = save_magic_overruled;
// restore no_hlsearch when keeping the old search pattern
if (search_options) {
set_no_hlsearch(save_no_hlsearch);

View File

@@ -39,7 +39,7 @@ describe('search_regcomp', function()
local search_regcomp = function(pat, patlen, pat_save, pat_use, options)
local regmatch = ffi.new('regmmatch_T')
local fail =
search.search_regcomp(to_cstr(pat), patlen, nil, pat_save, pat_use, options, regmatch)
search.search_regcomp(to_cstr(pat), patlen, nil, pat_save, pat_use, options, true, regmatch)
return fail, regmatch
end