aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-07-28 15:41:58 +0800
committerGitHub <noreply@github.com>2023-07-28 15:41:58 +0800
commitc1c2a1b5dd1d73e5e97b94e6626aaac25a3db9bc (patch)
tree5a3463065356600dc618ca01d3b30c0abfd3bfa0
parentdf2f5e39127e283a7ac74a21cb0323c437c3294f (diff)
downloadrneovim-c1c2a1b5dd1d73e5e97b94e6626aaac25a3db9bc.tar.gz
rneovim-c1c2a1b5dd1d73e5e97b94e6626aaac25a3db9bc.tar.bz2
rneovim-c1c2a1b5dd1d73e5e97b94e6626aaac25a3db9bc.zip
fix(inccommand): don't save information of a buffer twice (#24501)
Problem: 'inccommand' doesn't restore 'undolevels' properly for a buffer shown in multiple windows. Solution: Don't save information of a buffer twice.
-rw-r--r--src/nvim/ex_getln.c29
-rw-r--r--test/functional/ui/inccommand_spec.lua5
2 files changed, 21 insertions, 13 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 5f1f5d5adc..ece6257c4a 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2333,6 +2333,8 @@ static void cmdpreview_restore_undo(const CpUndoInfo *cp_undoinfo, buf_T *buf)
static void cmdpreview_prepare(CpInfo *cpinfo)
FUNC_ATTR_NONNULL_ALL
{
+ Set(ptr_t) saved_bufs = SET_INIT;
+
kv_init(cpinfo->buf_info);
kv_init(cpinfo->win_info);
@@ -2344,19 +2346,19 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
continue;
}
- CpBufInfo cp_bufinfo;
- cp_bufinfo.buf = buf;
-
- cp_bufinfo.save_b_p_ul = buf->b_p_ul;
- cp_bufinfo.save_b_changed = buf->b_changed;
- cp_bufinfo.save_changedtick = buf_get_changedtick(buf);
-
- cmdpreview_save_undo(&cp_bufinfo.undo_info, buf);
- u_clearall(buf);
-
- kv_push(cpinfo->buf_info, cp_bufinfo);
+ if (!set_has(ptr_t, &saved_bufs, buf)) {
+ CpBufInfo cp_bufinfo;
+ cp_bufinfo.buf = buf;
+ cp_bufinfo.save_b_p_ul = buf->b_p_ul;
+ cp_bufinfo.save_b_changed = buf->b_changed;
+ cp_bufinfo.save_changedtick = buf_get_changedtick(buf);
+ cmdpreview_save_undo(&cp_bufinfo.undo_info, buf);
+ kv_push(cpinfo->buf_info, cp_bufinfo);
+ set_put(ptr_t, &saved_bufs, buf);
- buf->b_p_ul = LONG_MAX; // Make sure we can undo all changes
+ u_clearall(buf);
+ buf->b_p_ul = LONG_MAX; // Make sure we can undo all changes
+ }
CpWinInfo cp_wininfo;
cp_wininfo.win = win;
@@ -2375,6 +2377,8 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
win->w_p_cuc = false; // Disable 'cursorcolumn' so it doesn't mess up the highlights
}
+ set_destroy(ptr_t, &saved_bufs);
+
cpinfo->save_hls = p_hls;
cpinfo->save_cmdmod = cmdmod;
win_size_save(&cpinfo->save_view);
@@ -2431,6 +2435,7 @@ static void cmdpreview_restore_state(CpInfo *cpinfo)
// Clear preview highlights.
extmark_clear(buf, (uint32_t)cmdpreview_ns, 0, 0, MAXLNUM, MAXCOL);
}
+
for (size_t i = 0; i < cpinfo->win_info.size; i++) {
CpWinInfo cp_wininfo = cpinfo->win_info.items[i];
win_T *win = cp_wininfo.win;
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index dc4aeb9c83..00dfa3fd49 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -174,9 +174,12 @@ describe(":substitute, 'inccommand' preserves", function()
it("'undolevels' (inccommand="..case..")", function()
feed_command("set undolevels=139")
feed_command("setlocal undolevels=34")
+ feed_command("split") -- Show the buffer in multiple windows
feed_command("set inccommand=" .. case)
insert("as")
- feed(":%s/as/glork/<enter>")
+ feed(":%s/as/glork/")
+ poke_eventloop()
+ feed("<enter>")
eq(meths.get_option_value('undolevels', {scope='global'}), 139)
eq(meths.get_option_value('undolevels', {buf=0}), 34)
end)