aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_docmd.c
diff options
context:
space:
mode:
authorFamiu Haque <famiuhaque@protonmail.com>2022-04-18 09:02:32 +0600
committerFamiu Haque <famiuhaque@protonmail.com>2022-04-20 00:10:02 +0600
commit1e3d9c7dbc3ea186227ae27a93e683f750a32ce1 (patch)
tree90f69449f47ae0a3078dcb0c8742879793005a8c /src/nvim/ex_docmd.c
parent0124a7bfa9e27796e561cb0b3a045b9327bf7077 (diff)
downloadrneovim-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.c38
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);
}
}