vim-patch:8.1.0282: 'incsearch' does not work with command modifiers

Problem:    'incsearch' does not work with command modifiers.
Solution:   Skip command modifiers.
33c4dbb74b
This commit is contained in:
Aufar Gilbran 2020-08-19 00:06:17 +08:00
parent ba59ee9a15
commit b24dabf266
3 changed files with 93 additions and 55 deletions

View File

@ -1269,17 +1269,17 @@ static char_u * do_one_cmd(char_u **cmdlinep,
goto doend; goto doend;
} }
/* // 1. Skip comment lines and leading white space and colons.
* Repeat until no more command modifiers are found. // 2. Handle command modifiers.
* The "ea" structure holds the arguments that can be used.
*/ // The "ea" structure holds the arguments that can be used.
ea.cmd = *cmdlinep; ea.cmd = *cmdlinep;
ea.cmdlinep = cmdlinep; ea.cmdlinep = cmdlinep;
ea.getline = fgetline; ea.getline = fgetline;
ea.cookie = cookie; ea.cookie = cookie;
ea.cstack = cstack; ea.cstack = cstack;
if (parse_command_modifiers(&ea, &errormsg) == FAIL) { if (parse_command_modifiers(&ea, &errormsg, false) == FAIL) {
goto doend; goto doend;
} }
@ -1994,16 +1994,7 @@ doend:
if (ea.verbose_save >= 0) { if (ea.verbose_save >= 0) {
p_verbose = ea.verbose_save; p_verbose = ea.verbose_save;
} }
if (cmdmod.save_ei != NULL) { free_cmdmod();
/* Restore 'eventignore' to the value before ":noautocmd". */
set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei,
OPT_FREE, SID_NONE);
free_string_option(cmdmod.save_ei);
}
if (cmdmod.filter_regmatch.regprog != NULL) {
vim_regfree(cmdmod.filter_regmatch.regprog);
}
cmdmod = save_cmdmod; cmdmod = save_cmdmod;
reg_executing = save_reg_executing; reg_executing = save_reg_executing;
@ -2045,11 +2036,14 @@ doend:
// - store flags in "cmdmod". // - store flags in "cmdmod".
// - Set ex_pressedreturn for an empty command line. // - Set ex_pressedreturn for an empty command line.
// - set msg_silent for ":silent" // - set msg_silent for ":silent"
// - set 'eventignore' to "all" for ":noautocmd"
// - set p_verbose for ":verbose" // - set p_verbose for ":verbose"
// - Increment "sandbox" for ":sandbox" // - Increment "sandbox" for ":sandbox"
// When "skip_only" is true the global variables are not changed, except for
// "cmdmod".
// Return FAIL when the command is not to be executed. // Return FAIL when the command is not to be executed.
// May set "errormsg" to an error message. // May set "errormsg" to an error message.
int parse_command_modifiers(exarg_T *eap, char_u **errormsg) int parse_command_modifiers(exarg_T *eap, char_u **errormsg, bool skip_only)
{ {
char_u *p; char_u *p;
@ -2057,10 +2051,8 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
eap->verbose_save = -1; eap->verbose_save = -1;
eap->save_msg_silent = -1; eap->save_msg_silent = -1;
// Repeat until no more command modifiers are found.
for (;; ) { for (;; ) {
/*
* 1. Skip comment lines and leading white space and colons.
*/
while (*eap->cmd == ' ' while (*eap->cmd == ' '
|| *eap->cmd == '\t' || *eap->cmd == '\t'
|| *eap->cmd == ':') { || *eap->cmd == ':') {
@ -2073,7 +2065,9 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
|| getline_equal(eap->getline, eap->cookie, getexline)) || getline_equal(eap->getline, eap->cookie, getexline))
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
eap->cmd = (char_u *)"+"; eap->cmd = (char_u *)"+";
ex_pressedreturn = true; if (!skip_only) {
ex_pressedreturn = true;
}
} }
// ignore comment and empty lines // ignore comment and empty lines
@ -2081,13 +2075,12 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
return FAIL; return FAIL;
} }
if (*eap->cmd == NUL) { if (*eap->cmd == NUL) {
ex_pressedreturn = true; if (!skip_only) {
ex_pressedreturn = true;
}
return FAIL; return FAIL;
} }
/*
* 2. Handle command modifiers.
*/
p = skip_range(eap->cmd, NULL); p = skip_range(eap->cmd, NULL);
switch (*p) { switch (*p) {
// When adding an entry, also modify cmd_exists(). // When adding an entry, also modify cmd_exists().
@ -2146,13 +2139,20 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
break; break;
} }
} }
p = skip_vimgrep_pat(p, &reg_pat, NULL); if (skip_only) {
p = skip_vimgrep_pat(p, NULL, NULL);
} else {
// NOTE: This puts a NUL after the pattern.
p = skip_vimgrep_pat(p, &reg_pat, NULL);
}
if (p == NULL || *p == NUL) { if (p == NULL || *p == NUL) {
break; break;
} }
cmdmod.filter_regmatch.regprog = vim_regcomp(reg_pat, RE_MAGIC); if (!skip_only) {
if (cmdmod.filter_regmatch.regprog == NULL) { cmdmod.filter_regmatch.regprog = vim_regcomp(reg_pat, RE_MAGIC);
break; if (cmdmod.filter_regmatch.regprog == NULL) {
break;
}
} }
eap->cmd = p; eap->cmd = p;
continue; continue;
@ -2179,7 +2179,7 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
case 'n': case 'n':
if (checkforcmd(&eap->cmd, "noautocmd", 3)) { if (checkforcmd(&eap->cmd, "noautocmd", 3)) {
if (cmdmod.save_ei == NULL) { if (cmdmod.save_ei == NULL && !skip_only) {
// Set 'eventignore' to "all". Restore the // Set 'eventignore' to "all". Restore the
// existing option value later. // existing option value later.
cmdmod.save_ei = vim_strsave(p_ei); cmdmod.save_ei = vim_strsave(p_ei);
@ -2200,24 +2200,30 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
continue; continue;
case 's': if (checkforcmd(&eap->cmd, "sandbox", 3)) { case 's': if (checkforcmd(&eap->cmd, "sandbox", 3)) {
if (!eap->did_sandbox) { if (!skip_only) {
sandbox++; if (!eap->did_sandbox) {
sandbox++;
}
eap->did_sandbox = true;
} }
eap->did_sandbox = true;
continue; continue;
} }
if (!checkforcmd(&eap->cmd, "silent", 3)) { if (!checkforcmd(&eap->cmd, "silent", 3)) {
break; break;
} }
if (eap->save_msg_silent == -1) { if (!skip_only) {
eap->save_msg_silent = msg_silent; if (eap->save_msg_silent == -1) {
eap->save_msg_silent = msg_silent;
}
msg_silent++;
} }
msg_silent++;
if (*eap->cmd == '!' && !ascii_iswhite(eap->cmd[-1])) { if (*eap->cmd == '!' && !ascii_iswhite(eap->cmd[-1])) {
// ":silent!", but not "silent !cmd" // ":silent!", but not "silent !cmd"
eap->cmd = skipwhite(eap->cmd + 1); eap->cmd = skipwhite(eap->cmd + 1);
emsg_silent++; if (!skip_only) {
eap->did_esilent++; emsg_silent++;
eap->did_esilent++;
}
} }
continue; continue;
@ -2245,10 +2251,12 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3)) case 'u': if (!checkforcmd(&eap->cmd, "unsilent", 3))
break; break;
if (eap->save_msg_silent == -1) { if (!skip_only) {
eap->save_msg_silent = msg_silent; if (eap->save_msg_silent == -1) {
eap->save_msg_silent = msg_silent;
}
msg_silent = 0;
} }
msg_silent = 0;
continue; continue;
case 'v': if (checkforcmd(&eap->cmd, "vertical", 4)) { case 'v': if (checkforcmd(&eap->cmd, "vertical", 4)) {
@ -2257,13 +2265,15 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
} }
if (!checkforcmd(&p, "verbose", 4)) if (!checkforcmd(&p, "verbose", 4))
break; break;
if (eap->verbose_save < 0) { if (!skip_only) {
eap->verbose_save = p_verbose; if (eap->verbose_save < 0) {
} eap->verbose_save = p_verbose;
if (ascii_isdigit(*eap->cmd)) { }
p_verbose = atoi((char *)eap->cmd); if (ascii_isdigit(*eap->cmd)) {
} else { p_verbose = atoi((char *)eap->cmd);
p_verbose = 1; } else {
p_verbose = 1;
}
} }
eap->cmd = p; eap->cmd = p;
continue; continue;
@ -2274,6 +2284,22 @@ int parse_command_modifiers(exarg_T *eap, char_u **errormsg)
return OK; return OK;
} }
// Free contents of "cmdmod".
static void free_cmdmod(void)
{
if (cmdmod.save_ei != NULL) {
/* Restore 'eventignore' to the value before ":noautocmd". */
set_string_option_direct((char_u *)"ei", -1, cmdmod.save_ei,
OPT_FREE, SID_NONE);
free_string_option(cmdmod.save_ei);
}
if (cmdmod.filter_regmatch.regprog != NULL) {
vim_regfree(cmdmod.filter_regmatch.regprog);
}
}
// Parse the address range, if any, in "eap". // Parse the address range, if any, in "eap".
// Return FAIL and set "errormsg" or return OK. // Return FAIL and set "errormsg" or return OK.
int parse_cmd_address(exarg_T *eap, char_u **errormsg) int parse_cmd_address(exarg_T *eap, char_u **errormsg)

View File

@ -287,11 +287,24 @@ static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
return true; return true;
} }
if (firstc == ':') { if (firstc == ':') {
char_u *cmd = skip_range(ccline.cmdbuff, NULL); char_u *cmd;
cmdmod_T save_cmdmod = cmdmod;
char_u *p; char_u *p;
int delim; int delim;
char_u *end; char_u *end;
char_u *dummy;
exarg_T ea;
memset(&ea, 0, sizeof(ea));
ea.line1 = 1;
ea.line2 = 1;
ea.cmd = ccline.cmdbuff;
ea.addr_type = ADDR_LINES;
parse_command_modifiers(&ea, &dummy, TRUE);
cmdmod = save_cmdmod;
cmd = skip_range(ea.cmd, NULL);
if (*cmd == 's' || *cmd == 'g' || *cmd == 'v') { if (*cmd == 's' || *cmd == 'g' || *cmd == 'v') {
// Skip over "substitute" to find the pattern separator. // Skip over "substitute" to find the pattern separator.
for (p = cmd; ASCII_ISALPHA(*p); p++) {} for (p = cmd; ASCII_ISALPHA(*p); p++) {}
@ -310,8 +323,6 @@ static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
delim = *p++; delim = *p++;
end = skip_regexp(p, delim, p_magic, NULL); end = skip_regexp(p, delim, p_magic, NULL);
if (end > p || *end == delim) { if (end > p || *end == delim) {
char_u *dummy;
exarg_T ea;
pos_T save_cursor = curwin->w_cursor; pos_T save_cursor = curwin->w_cursor;
// found a non-empty pattern // found a non-empty pattern
@ -319,11 +330,6 @@ static bool do_incsearch_highlighting(int firstc, incsearch_state_T *s,
*patlen = (int)(end - p); *patlen = (int)(end - p);
// parse the address range // parse the address range
memset(&ea, 0, sizeof(ea));
ea.line1 = 1;
ea.line2 = 1;
ea.cmd = ccline.cmdbuff;
ea.addr_type = ADDR_LINES;
curwin->w_cursor = s->search_start; curwin->w_cursor = s->search_start;
parse_cmd_address(&ea, &dummy); parse_cmd_address(&ea, &dummy);
if (ea.addr_count > 0) { if (ea.addr_count > 0) {

View File

@ -659,6 +659,12 @@ func Test_incsearch_substitute_dump()
call VerifyScreenDump(buf, 'Test_incsearch_substitute_05', {}) call VerifyScreenDump(buf, 'Test_incsearch_substitute_05', {})
call term_sendkeys(buf, "\<Esc>") call term_sendkeys(buf, "\<Esc>")
" Command modifiers are skipped
call term_sendkeys(buf, ':above below browse botr confirm keepmar keepalt keeppat keepjum filter xxx hide lockm leftabove noau noswap rightbel sandbox silent silent! $tab top unsil vert verbose 4,5s/fo.')
sleep 100m
call VerifyScreenDump(buf, 'Test_incsearch_substitute_06', {})
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
call delete('Xis_subst_script') call delete('Xis_subst_script')
endfunc endfunc