From d4384cbbf37786f0185f6bbb2e5bf82f5573e532 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 30 Oct 2019 20:38:41 +0000 Subject: [PATCH 1/9] Remove unnecessary expr in 'icm' test --- test/functional/ui/inccommand_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index d60cd08fb0..82251a4b88 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -88,7 +88,7 @@ local function common_setup(screen, inccommand, text) }) end - command("set inccommand=" .. (inccommand and inccommand or "")) + command("set inccommand=" .. (inccommand or "")) if text then insert(text) From 3b3d21775478cc97acf391a30d844eb3a81e96f6 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 8 Mar 2019 22:49:03 +0000 Subject: [PATCH 2/9] Factor out skip_colon_white() --- src/nvim/ex_docmd.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index da0184aa45..22c4fd264d 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1201,6 +1201,19 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap) } } +static char_u *skip_colon_white(const char_u *p, bool skipleadingwhite) +{ + if (skipleadingwhite) { + p = skipwhite(p); + } + + while (*p == ':') { + p = skipwhite(p + 1); + } + + return (char_u *)p; +} + /* * Execute one Ex command. * @@ -1705,9 +1718,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, /* * Skip ':' and any white space */ - ea.cmd = skipwhite(ea.cmd); - while (*ea.cmd == ':') - ea.cmd = skipwhite(ea.cmd + 1); + ea.cmd = skip_colon_white(ea.cmd, true); /* * If we got a line, but no command, then go to the line. @@ -3580,9 +3591,8 @@ char_u *skip_range( ++cmd; } - /* Skip ":" and white space. */ - while (*cmd == ':') - cmd = skipwhite(cmd + 1); + // Skip ":" and white space. + cmd = skip_colon_white(cmd, false); return (char_u *)cmd; } From 1c7aa1131297b4b3686d66aae06090e1398da56c Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 8 Mar 2019 22:49:48 +0000 Subject: [PATCH 3/9] Allow multiple leading colons before and after modifiers for 'inccommand' --- src/nvim/ex_docmd.c | 5 ++++- test/functional/ui/inccommand_spec.lua | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 22c4fd264d..48d29caf60 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -10216,10 +10216,13 @@ bool cmd_can_preview(char_u *cmd) return false; } + // Ignore additional colons at the start... + cmd = skip_colon_white(cmd, true); + // Ignore any leading modifiers (:keeppatterns, :verbose, etc.) for (int len = modifier_len(cmd); len != 0; len = modifier_len(cmd)) { cmd += len; - cmd = skipwhite(cmd); + cmd = skip_colon_white(cmd, true); } exarg_T ea; diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 82251a4b88..c5ad093eca 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -779,6 +779,13 @@ describe(":substitute, inccommand=split", function() {15:~ }| :silent tabedit %s/tw/to^ | ]]) + feed('') + + -- leading colons + feed(':::%s/tw/to') + screen:expect{any=[[{12:to}o lines]]} + feed('') + screen:expect{any=[[two lines]]} end) it('shows split window when typing the pattern', function() From 1f6ce1f97d60f9fd1cc75dab4b604a72d390bf1e Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Tue, 29 Oct 2019 22:31:06 +0000 Subject: [PATCH 4/9] Only apply 'icm' substitutions when preview was successfully opened --- src/nvim/ex_cmds.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 2e8bd79c81..c1ef08593d 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -5563,7 +5563,12 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, linenr_T highest_num_line = 0; int col_width = 0; + // if we fail to split the window, we don't want to modify orig_buf + bool split_success = false; + if (split && win_split((int)p_cwh, WSP_BOT) != FAIL) { + split_success = true; + buf_open_scratch(preview_buf ? bufnr : 0, "[Preview]"); buf_clear(); preview_buf = curbuf; @@ -5593,7 +5598,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, for (size_t matchidx = 0; matchidx < lines.subresults.size; matchidx++) { SubResult match = lines.subresults.items[matchidx]; - if (split && preview_buf) { + if (split_success && preview_buf) { lpos_T p_start = { 0, match.start.col }; // match starts here in preview lpos_T p_end = { 0, match.end.col }; // ... and ends here From d52d7823898c7fee0121c4d6da730a0530bf8c50 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Tue, 29 Oct 2019 22:31:40 +0000 Subject: [PATCH 5/9] Prevent :topleft, etc modifying the inccommand preview window --- src/nvim/ex_cmds.c | 3 ++ test/functional/ui/inccommand_spec.lua | 48 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index c1ef08593d..a71b249a92 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -5535,6 +5535,9 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, // We keep a special-purpose buffer around, but don't assume it exists. buf_T *preview_buf = bufnr ? buflist_findnr(bufnr) : 0; + // disable :leftabove/botright modifiers + // (especially ones that conflict with our win_split() call below) + cmdmod.split = 0; cmdmod.tab = 0; // disable :tab modifier cmdmod.noswapfile = true; // disable swap for preview buffer // disable file info message diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index c5ad093eca..0d6aa7f128 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -95,7 +95,7 @@ local function common_setup(screen, inccommand, text) end end -describe(":substitute, inccommand=split", function() +describe(":substitute, inccommand=split interactivity", function() before_each(function() clear() common_setup(nil, "split", default_text) @@ -788,6 +788,52 @@ describe(":substitute, inccommand=split", function() screen:expect{any=[[two lines]]} end) + it("ignores new-window modifiers when splitting the preview window", function() + -- one modifier + feed(':topleft %s/tw/to') + screen:expect([[ + Inc substitution on | + {12:to}o lines | + Inc substitution on | + {12:to}o lines | + | + {11:[No Name] [+] }| + |2| {12:to}o lines | + |4| {12:to}o lines | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :topleft %s/tw/to^ | + ]]) + feed('') + screen:expect{any=[[two lines]]} + + -- multiple modifiers + feed(':topleft vert %s/tw/to') + screen:expect([[ + Inc substitution on | + {12:to}o lines | + Inc substitution on | + {12:to}o lines | + | + {11:[No Name] [+] }| + |2| {12:to}o lines | + |4| {12:to}o lines | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :topleft vert %s/tw/to^ | + ]]) + feed('') + screen:expect{any=[[two lines]]} + end) + it('shows split window when typing the pattern', function() feed(":%s/tw") screen:expect([[ From d04ab11f24521e60278a0daed9a7d5abeeaf6f4f Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Tue, 29 Oct 2019 22:32:25 +0000 Subject: [PATCH 6/9] Prevent prompts during inccommand previews For example, "Backwards range given, OK to swap (y/n)?" on each keypress. --- src/nvim/ex_getln.c | 2 ++ test/functional/ui/inccommand_spec.lua | 43 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index f2665ca0b5..9e2671ca5e 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1927,7 +1927,9 @@ static int command_line_changed(CommandLineState *s) // - Immediately undo the effects. State |= CMDPREVIEW; emsg_silent++; // Block error reporting as the command may be incomplete + msg_silent++; // Block messages, namely ones that prompt do_cmdline(ccline.cmdbuff, NULL, NULL, DOCMD_KEEPLINE|DOCMD_NOWAIT); + msg_silent--; // Unblock messages emsg_silent--; // Unblock error reporting // Restore the window "view". diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua index 0d6aa7f128..b841574643 100644 --- a/test/functional/ui/inccommand_spec.lua +++ b/test/functional/ui/inccommand_spec.lua @@ -2582,6 +2582,49 @@ describe(":substitute", function() :%s/some\(thing\)\@!/every/^ | ]]) end) + + it("doesn't prompt to swap cmd range", function() + screen = Screen.new(50, 8) -- wide to avoid hit-enter prompt + common_setup(screen, "split", default_text) + feed(':2,1s/tw/MO/g') + + -- substitution preview should have been made, without prompting + screen:expect([[ + {12:MO}o lines | + {11:[No Name] [+] }| + |2| {12:MO}o lines | + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + :2,1s/tw/MO/g^ | + ]]) + + -- but should be prompted on hitting enter + feed('') + screen:expect([[ + {12:MO}o lines | + {11:[No Name] [+] }| + |2| {12:MO}o lines | + {15:~ }| + {15:~ }| + {15:~ }| + {10:[Preview] }| + {13:Backwards range given, OK to swap (y/n)?}^ | + ]]) + + feed('y') + screen:expect([[ + Inc substitution on | + ^MOo lines | + | + {15:~ }| + {15:~ }| + {15:~ }| + {15:~ }| + {13:Backwards range given, OK to swap (y/n)?}y | + ]]) + end) end) it(':substitute with inccommand during :terminal activity', function() From 36b4191e41788192c7fc5cef2f7b11d3bcd13880 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 31 Oct 2019 23:20:33 +0000 Subject: [PATCH 7/9] Document skip_colon_white() --- src/nvim/ex_docmd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 48d29caf60..d3e2120721 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1201,6 +1201,10 @@ static void get_wincmd_addr_type(char_u *arg, exarg_T *eap) } } +/// Skip colons and trailing whitespace, returning a pointer to the first +/// non-colon, non-whitespace character. +// +/// @param skipleadingwhite Skip leading whitespace too static char_u *skip_colon_white(const char_u *p, bool skipleadingwhite) { if (skipleadingwhite) { From 0cee3001947340c0d74d32a17a2c93147e13cb7f Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 2 Nov 2019 09:31:48 +0000 Subject: [PATCH 8/9] Simplify split_success logic --- src/nvim/ex_cmds.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index a71b249a92..8cdf971b9e 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -5566,12 +5566,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, linenr_T highest_num_line = 0; int col_width = 0; - // if we fail to split the window, we don't want to modify orig_buf - bool split_success = false; - if (split && win_split((int)p_cwh, WSP_BOT) != FAIL) { - split_success = true; - buf_open_scratch(preview_buf ? bufnr : 0, "[Preview]"); buf_clear(); preview_buf = curbuf; @@ -5589,6 +5584,9 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, highest_num_line = kv_last(lines.subresults).end.lnum; col_width = log10(highest_num_line) + 1 + 3; } + } else { + // if we fail to split the window, we don't want to modify the preview buffer + preview_buf = NULL; } char *str = NULL; // construct the line to show in here @@ -5601,7 +5599,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, for (size_t matchidx = 0; matchidx < lines.subresults.size; matchidx++) { SubResult match = lines.subresults.items[matchidx]; - if (split_success && preview_buf) { + if (preview_buf) { lpos_T p_start = { 0, match.start.col }; // match starts here in preview lpos_T p_end = { 0, match.end.col }; // ... and ends here From 4f124702c079fba4502b077c8c832538c0f0b386 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Tue, 5 Nov 2019 18:56:54 +0000 Subject: [PATCH 9/9] Simplify + inline/align comment --- src/nvim/ex_cmds.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 8cdf971b9e..712ce711d0 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -5535,9 +5535,7 @@ static buf_T *show_sub(exarg_T *eap, pos_T old_cusr, // We keep a special-purpose buffer around, but don't assume it exists. buf_T *preview_buf = bufnr ? buflist_findnr(bufnr) : 0; - // disable :leftabove/botright modifiers - // (especially ones that conflict with our win_split() call below) - cmdmod.split = 0; + cmdmod.split = 0; // disable :leftabove/botright modifiers cmdmod.tab = 0; // disable :tab modifier cmdmod.noswapfile = true; // disable swap for preview buffer // disable file info message