diff options
author | Famiu Haque <famiuhaque@protonmail.com> | 2022-04-18 09:02:32 +0600 |
---|---|---|
committer | Famiu Haque <famiuhaque@protonmail.com> | 2022-04-20 00:10:02 +0600 |
commit | 1e3d9c7dbc3ea186227ae27a93e683f750a32ce1 (patch) | |
tree | 90f69449f47ae0a3078dcb0c8742879793005a8c /src/nvim/ex_docmd.c | |
parent | 0124a7bfa9e27796e561cb0b3a045b9327bf7077 (diff) | |
download | rneovim-1e3d9c7dbc3ea186227ae27a93e683f750a32ce1.tar.gz rneovim-1e3d9c7dbc3ea186227ae27a93e683f750a32ce1.tar.bz2 rneovim-1e3d9c7dbc3ea186227ae27a93e683f750a32ce1.zip |
feat: add `undo!`
Allows using `undo!` to undo changes and remove them from the undo-tree. Can only be used for moving backwards in the same undo branch.
Diffstat (limited to 'src/nvim/ex_docmd.c')
-rw-r--r-- | src/nvim/ex_docmd.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index fc0bb48803..b67754ffe5 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -76,6 +76,7 @@ #include "nvim/terminal.h" #include "nvim/ui.h" #include "nvim/undo.h" +#include "nvim/undo_defs.h" #include "nvim/version.h" #include "nvim/vim.h" #include "nvim/window.h" @@ -8231,10 +8232,39 @@ static void ex_bang(exarg_T *eap) /// ":undo". static void ex_undo(exarg_T *eap) { - if (eap->addr_count == 1) { // :undo 123 - undo_time(eap->line2, false, false, true); - } else { - u_undo(1); + if (eap->addr_count != 1) { + if (eap->forceit) { + u_undo_and_forget(1); // :undo! + } else { + u_undo(1); // :undo + } + return; + } + + long step = eap->line2; + + if (eap->forceit) { // undo! 123 + // change number for "undo!" must be lesser than current change number + if (step >= curbuf->b_u_seq_cur) { + emsg(_(e_undobang_cannot_redo_or_move_branch)); + return; + } + // ensure that target change number is in same branch + // while also counting the amount of undoes it'd take to reach target + u_header_T *uhp; + int count = 0; + + for (uhp = curbuf->b_u_curhead ? curbuf->b_u_curhead : curbuf->b_u_newhead; + uhp != NULL && uhp->uh_seq > step; + uhp = uhp->uh_next.ptr, ++count) { + } + if (step != 0 && (uhp == NULL || uhp->uh_seq < step)) { + emsg(_(e_undobang_cannot_redo_or_move_branch)); + return; + } + u_undo_and_forget(count); + } else { // :undo 123 + undo_time(step, false, false, true); } } |