aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-01-25 16:18:58 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-01-25 16:18:58 +0800
commitd11bbacf0ffa45096364195bda4739984d25121e (patch)
treead1eba2f9daaec6c0e91830415ce1db445f83ec9
parentecec957125ca95ef5fbc4534d62ed16cfedb0c44 (diff)
downloadrneovim-d11bbacf0ffa45096364195bda4739984d25121e.tar.gz
rneovim-d11bbacf0ffa45096364195bda4739984d25121e.tar.bz2
rneovim-d11bbacf0ffa45096364195bda4739984d25121e.zip
fix(inccommand): do not change reg_prev_sub when previewing
-rw-r--r--src/nvim/ex_cmds.c10
-rw-r--r--src/nvim/regexp.c15
-rw-r--r--test/functional/ui/inccommand_spec.lua64
3 files changed, 84 insertions, 5 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 95390b1a70..66e9738f98 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3629,8 +3629,14 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
// We do it here once to avoid it to be replaced over and over again.
// But don't do it when it starts with "\=", then it's an expression.
assert(sub != NULL);
+
+ bool sub_needs_free = false;
if (!(sub[0] == '\\' && sub[1] == '=')) {
+ char_u *source = sub;
sub = regtilde(sub, p_magic);
+ // When previewing, the new pattern allocated by regtilde() needs to be freed
+ // in this function because it will not be used or freed by regtilde() later.
+ sub_needs_free = preview && sub != source;
}
// Check for a match on each line.
@@ -4425,6 +4431,10 @@ skip:
kv_destroy(preview_lines.subresults);
+ if (sub_needs_free) {
+ xfree(sub);
+ }
+
return preview_buf;
#undef ADJUST_SUB_FIRSTLNUM
#undef PUSH_PREVIEW_LINES
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 45e580dbee..9bea54ad2c 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -6538,11 +6538,16 @@ char_u *regtilde(char_u *source, int magic)
}
}
- xfree(reg_prev_sub);
- if (newsub != source) /* newsub was allocated, just keep it */
- reg_prev_sub = newsub;
- else /* no ~ found, need to save newsub */
- reg_prev_sub = vim_strsave(newsub);
+ // Only change reg_prev_sub when not previewing.
+ if (!(State & CMDPREVIEW)) {
+ xfree(reg_prev_sub);
+ if (newsub != source) { // newsub was allocated, just keep it
+ reg_prev_sub = newsub;
+ } else { // no ~ found, need to save newsub
+ reg_prev_sub = vim_strsave(newsub);
+ }
+ }
+
return newsub;
}
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index b6e2f2311f..10700d9508 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -293,6 +293,70 @@ describe(":substitute, 'inccommand' preserves", function()
end)
end
+ for _, case in ipairs({'', 'split', 'nosplit'}) do
+ it('previous substitute string ~ (inccommand='..case..') #12109', function()
+ local screen = Screen.new(30,10)
+ common_setup(screen, case, default_text)
+
+ feed(':%s/Inc/SUB<CR>')
+ expect([[
+ SUB substitution on
+ two lines
+ ]])
+
+ feed(':%s/line/')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB substitution on
+ two SUBs
+ ]])
+
+ feed(':%s/sti/')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('B')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB subSUBBtution on
+ two SUBs
+ ]])
+
+ feed(':%s/ion/NEW<CR>')
+ expect([[
+ SUB subSUBBtutNEW on
+ two SUBs
+ ]])
+
+ feed(':%s/two/')
+ poke_eventloop()
+ feed('N')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB subSUBBtutNEW on
+ NNEW SUBs
+ ]])
+
+ feed(':%s/bS/')
+ poke_eventloop()
+ feed('~')
+ poke_eventloop()
+ feed('W')
+ poke_eventloop()
+ feed('<CR>')
+ expect([[
+ SUB suNNEWWUBBtutNEW on
+ NNEW SUBs
+ ]])
+ end)
+ end
end)
describe(":substitute, 'inccommand' preserves undo", function()