From ac66f5af06ac1f306b0ddb366ba81093508546c4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 26 Sep 2022 07:15:07 +0800 Subject: [PATCH] fix!: make :undo! notify buffer update callbacks (#20344) When :undo! was introduced to Nvim the implementation of 'inccommand' preview callback hasn't been fully decided yet, so not notifying buffer update callbacks made sense for 'inccommand' preview callback in case it needs to undo the changes itself. Now it turns out that the undo-and-forget is done automatically for 'inccommand', so it doesn't make sense for :undo! to avoid notifying buffer update callbacks anymore. --- src/nvim/ex_docmd.c | 4 ++-- src/nvim/ex_getln.c | 2 +- src/nvim/undo.c | 8 ++++---- test/functional/lua/buffer_updates_spec.lua | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 085948f7b1..7ece195374 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5867,7 +5867,7 @@ static void ex_undo(exarg_T *eap) { if (eap->addr_count != 1) { if (eap->forceit) { - u_undo_and_forget(1); // :undo! + u_undo_and_forget(1, true); // :undo! } else { u_undo(1); // :undo } @@ -5894,7 +5894,7 @@ static void ex_undo(exarg_T *eap) emsg(_(e_undobang_cannot_redo_or_move_branch)); return; } - u_undo_and_forget(count); + u_undo_and_forget(count, true); } else { // :undo 123 undo_time(step, false, false, true); } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 0ccc12c9b4..bc31f5a6cf 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2194,7 +2194,7 @@ static void cmdpreview_restore_state(CpInfo *cpinfo) aco_save_T aco; aucmd_prepbuf(&aco, buf); // Undo invisibly. This also moves the cursor! - if (!u_undo_and_forget(count)) { + if (!u_undo_and_forget(count, false)) { abort(); } aucmd_restbuf(&aco); diff --git a/src/nvim/undo.c b/src/nvim/undo.c index d67863f84f..1a9066d7f1 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1771,16 +1771,16 @@ void u_redo(int count) /// Undo and remove the branch from the undo tree. /// Also moves the cursor (as a "normal" undo would). -bool u_undo_and_forget(int count) +/// +/// @param do_buf_event If `true`, send the changedtick with the buffer updates +bool u_undo_and_forget(int count, bool do_buf_event) { if (curbuf->b_u_synced == false) { u_sync(true); count = 1; } undo_undoes = true; - u_doit(count, true, - // Don't send nvim_buf_lines_event for u_undo_and_forget(). - false); + u_doit(count, true, do_buf_event); if (curbuf->b_u_curhead == NULL) { // nothing was undone. diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index 10de45274c..c6c0964ddb 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -118,6 +118,24 @@ describe('lua buffer event callbacks: on_lines', function() } tick = tick + 1 + tick = tick + 1 + command('redo') + check_events { + { "test1", "lines", 1, tick, 3, 5, 4, 32 }; + { "test2", "lines", 1, tick, 3, 5, 4, 32 }; + { "test2", "changedtick", 1, tick+1 }; + } + tick = tick + 1 + + tick = tick + 1 + command('undo!') + check_events { + { "test1", "lines", 1, tick, 3, 4, 5, 13 }; + { "test2", "lines", 1, tick, 3, 4, 5, 13 }; + { "test2", "changedtick", 1, tick+1 }; + } + tick = tick + 1 + -- simulate next callback returning true exec_lua("test_unreg = 'test1'")