changeset 14538:213f1a519378 v8.1.0282

patch 8.1.0282: 'incsearch' does not work with command modifiers commit https://github.com/vim/vim/commit/33c4dbb74bdf41aadd193a704f597d4df20f0e47 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Aug 14 16:06:16 2018 +0200 patch 8.1.0282: 'incsearch' does not work with command modifiers Problem: 'incsearch' does not work with command modifiers. Solution: Skip command modifiers.
author Christian Brabandt <cb@256bit.org>
date Tue, 14 Aug 2018 16:15:04 +0200
parents 2e7cca4372f3
children c99b59e01467
files src/ex_docmd.c src/ex_getln.c src/proto/ex_docmd.pro src/testdir/test_search.vim src/version.c
diffstat 5 files changed, 106 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -68,6 +68,7 @@ static char_u	*do_one_cmd(char_u **, int
 static char_u	*do_one_cmd(char_u **, int, char_u *(*fgetline)(int, void *, int), void *cookie);
 static int	if_level = 0;		/* depth in :if */
 #endif
+static void	free_cmdmod(void);
 static void	append_command(char_u *cmd);
 static char_u	*find_command(exarg_T *eap, int *full);
 
@@ -1741,10 +1742,11 @@ do_one_cmd(
     if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!')
 	goto doend;
 
-    /*
-     * Repeat until no more command modifiers are found.
-     * The "ea" structure holds the arguments that can be used.
-     */
+/*
+ * 1. Skip comment lines and leading white space and colons.
+ * 2. Handle command modifiers.
+ */
+    // The "ea" structure holds the arguments that can be used.
     ea.cmd = *cmdlinep;
     ea.cmdlinep = cmdlinep;
     ea.getline = fgetline;
@@ -1752,7 +1754,7 @@ do_one_cmd(
 #ifdef FEAT_EVAL
     ea.cstack = cstack;
 #endif
-    if (parse_command_modifiers(&ea, &errormsg) == FAIL)
+    if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL)
 	goto doend;
 
     after_modifier = ea.cmd;
@@ -2553,17 +2555,7 @@ doend:
     if (ea.verbose_save >= 0)
 	p_verbose = ea.verbose_save;
 
-    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);
-
+    free_cmdmod();
     cmdmod = save_cmdmod;
 
     if (ea.save_msg_silent != -1)
@@ -2609,13 +2601,16 @@ doend:
  * - store flags in "cmdmod".
  * - Set ex_pressedreturn for an empty command line.
  * - set msg_silent for ":silent"
+ * - set 'eventignore' to "all" for ":noautocmd"
  * - set p_verbose for ":verbose"
  * - 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.
  * May set "errormsg" to an error message.
  */
     int
-parse_command_modifiers(exarg_T *eap, char_u **errormsg)
+parse_command_modifiers(exarg_T *eap, char_u **errormsg, int skip_only)
 {
     char_u *p;
 
@@ -2623,11 +2618,9 @@ parse_command_modifiers(exarg_T *eap, ch
     eap->verbose_save = -1;
     eap->save_msg_silent = -1;
 
+    // Repeat until no more command modifiers are found.
     for (;;)
     {
-/*
- * 1. Skip comment lines and leading white space and colons.
- */
 	while (*eap->cmd == ' ' || *eap->cmd == '\t' || *eap->cmd == ':')
 	    ++eap->cmd;
 
@@ -2638,7 +2631,8 @@ parse_command_modifiers(exarg_T *eap, ch
 			&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
 	{
 	    eap->cmd = (char_u *)"+";
-	    ex_pressedreturn = TRUE;
+	    if (!skip_only)
+		ex_pressedreturn = TRUE;
 	}
 
 	/* ignore comment and empty lines */
@@ -2646,13 +2640,11 @@ parse_command_modifiers(exarg_T *eap, ch
 	    return FAIL;
 	if (*eap->cmd == NUL)
 	{
-	    ex_pressedreturn = TRUE;
+	    if (!skip_only)
+		ex_pressedreturn = TRUE;
 	    return FAIL;
 	}
 
-/*
- * 2. Handle command modifiers.
- */
 	p = skip_range(eap->cmd, NULL);
 	switch (*p)
 	{
@@ -2720,13 +2712,20 @@ parse_command_modifiers(exarg_T *eap, ch
 				if (*p == NUL || ends_excmd(*p))
 				    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)
 				break;
-			    cmdmod.filter_regmatch.regprog =
+			    if (!skip_only)
+			    {
+				cmdmod.filter_regmatch.regprog =
 						vim_regcomp(reg_pat, RE_MAGIC);
-			    if (cmdmod.filter_regmatch.regprog == NULL)
-				break;
+				if (cmdmod.filter_regmatch.regprog == NULL)
+				    break;
+			    }
 			    eap->cmd = p;
 			    continue;
 			}
@@ -2752,7 +2751,7 @@ parse_command_modifiers(exarg_T *eap, ch
 
 	    case 'n':	if (checkforcmd(&eap->cmd, "noautocmd", 3))
 			{
-			    if (cmdmod.save_ei == NULL)
+			    if (cmdmod.save_ei == NULL && !skip_only)
 			    {
 				/* Set 'eventignore' to "all". Restore the
 				 * existing option value later. */
@@ -2775,23 +2774,32 @@ parse_command_modifiers(exarg_T *eap, ch
 	    case 's':	if (checkforcmd(&eap->cmd, "sandbox", 3))
 			{
 #ifdef HAVE_SANDBOX
-			    if (!eap->did_sandbox)
-				++sandbox;
-			    eap->did_sandbox = TRUE;
+			    if (!skip_only)
+			    {
+				if (!eap->did_sandbox)
+				    ++sandbox;
+				eap->did_sandbox = TRUE;
+			    }
 #endif
 			    continue;
 			}
 			if (!checkforcmd(&eap->cmd, "silent", 3))
 			    break;
-			if (eap->save_msg_silent == -1)
-			    eap->save_msg_silent = msg_silent;
-			++msg_silent;
+			if (!skip_only)
+			{
+			    if (eap->save_msg_silent == -1)
+				eap->save_msg_silent = msg_silent;
+			    ++msg_silent;
+			}
 			if (*eap->cmd == '!' && !VIM_ISWHITE(eap->cmd[-1]))
 			{
 			    /* ":silent!", but not "silent !cmd" */
 			    eap->cmd = skipwhite(eap->cmd + 1);
-			    ++emsg_silent;
-			    ++eap->did_esilent;
+			    if (!skip_only)
+			    {
+				++emsg_silent;
+				++eap->did_esilent;
+			    }
 			}
 			continue;
 
@@ -2820,9 +2828,12 @@ parse_command_modifiers(exarg_T *eap, ch
 
 	    case 'u':	if (!checkforcmd(&eap->cmd, "unsilent", 3))
 			    break;
-			if (eap->save_msg_silent == -1)
-			    eap->save_msg_silent = msg_silent;
-			msg_silent = 0;
+			if (!skip_only)
+			{
+			    if (eap->save_msg_silent == -1)
+				eap->save_msg_silent = msg_silent;
+			    msg_silent = 0;
+			}
 			continue;
 
 	    case 'v':	if (checkforcmd(&eap->cmd, "vertical", 4))
@@ -2832,12 +2843,15 @@ parse_command_modifiers(exarg_T *eap, ch
 			}
 			if (!checkforcmd(&p, "verbose", 4))
 			    break;
-			if (eap->verbose_save < 0)
-			    eap->verbose_save = p_verbose;
-			if (vim_isdigit(*eap->cmd))
-			    p_verbose = atoi((char *)eap->cmd);
-			else
-			    p_verbose = 1;
+			if (!skip_only)
+			{
+			    if (eap->verbose_save < 0)
+				eap->verbose_save = p_verbose;
+			    if (vim_isdigit(*eap->cmd))
+				p_verbose = atoi((char *)eap->cmd);
+			    else
+				p_verbose = 1;
+			}
 			eap->cmd = p;
 			continue;
 	}
@@ -2848,6 +2862,24 @@ parse_command_modifiers(exarg_T *eap, ch
 }
 
 /*
+ * 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".
  * Return FAIL and set "errormsg" or return OK.
  */
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -283,11 +283,24 @@ do_incsearch_highlighting(int firstc, in
 	    return TRUE;
 	if (firstc == ':')
 	{
-	    char_u *cmd = skip_range(ccline.cmdbuff, NULL);
-	    char_u *p;
-	    int	    delim;
-	    char_u *end;
-
+	    char_u	*cmd;
+	    cmdmod_T	save_cmdmod = cmdmod;
+	    char_u	*p;
+	    int		delim;
+	    char_u	*end;
+	    char_u	*dummy;
+	    exarg_T	ea;
+
+	    vim_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')
 	    {
 		// Skip over "substitute" to find the pattern separator.
@@ -310,8 +323,6 @@ do_incsearch_highlighting(int firstc, in
 		    end = skip_regexp(p, delim, p_magic, NULL);
 		    if (end > p || *end == delim)
 		    {
-			char_u  *dummy;
-			exarg_T ea;
 			pos_T	save_cursor = curwin->w_cursor;
 
 			// found a non-empty pattern
@@ -319,11 +330,6 @@ do_incsearch_highlighting(int firstc, in
 			*patlen = (int)(end - p);
 
 			// parse the address range
-			vim_memset(&ea, 0, sizeof(ea));
-			ea.line1 = 1;
-			ea.line2 = 1;
-			ea.cmd = ccline.cmdbuff;
-			ea.addr_type = ADDR_LINES;
 			curwin->w_cursor = is_state->search_start;
 			parse_cmd_address(&ea, &dummy);
 			if (ea.addr_count > 0)
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -4,7 +4,7 @@ int do_cmdline_cmd(char_u *cmd);
 int do_cmdline(char_u *cmdline, char_u *(*fgetline)(int, void *, int), void *cookie, int flags);
 int getline_equal(char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int));
 void *getline_cookie(char_u *(*fgetline)(int, void *, int), void *cookie);
-int parse_command_modifiers(exarg_T *eap, char_u **errormsg);
+int parse_command_modifiers(exarg_T *eap, char_u **errormsg, int skip_only);
 int parse_cmd_address(exarg_T *eap, char_u **errormsg);
 int checkforcmd(char_u **pp, char *cmd, int len);
 int modifier_len(char_u *cmd);
--- a/src/testdir/test_search.vim
+++ b/src/testdir/test_search.vim
@@ -884,6 +884,12 @@ func Test_incsearch_substitute_dump()
   call VerifyScreenDump(buf, 'Test_incsearch_substitute_05', {})
   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 delete('Xis_subst_script')
 endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -795,6 +795,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    282,
+/**/
     281,
 /**/
     280,