Hi Bram,
here are 3 patches that improve the undo-persistence.
Patch [1] sets the current save number to the last save number after
loading a file (see how 'save_cur' in the undotree() function is set to
zero after loading a file while it should probably be the same as
'save_last'; compare this to how 'save_cur' changes after going back one
step in the undotree and return to the original state [e.g. after g-g+
'save_cur' is the same as 'save_last'])
Patch [2] Lets changenr() return the current save_nr, if the optional
argument save_nr is given and is one.
Currently, it is not possible to know after which save nr the buffer is,
after moving around in the undo tree and :later <nr>f and :earlier <nr>f
jump around only relative to the current save marks. So to decide what
<nr> should be, one needs to know, after which save_nr the current
buffer is.
Patch [3] :earlier <nr>f and :later <nr>f only move relative to the
current save number of the buffer. I think it would be nice to jump
right to the actual save number, as it is output with :undolist.
This patch implements :undo <nr>f to let you jump right after the
specified save number. (Please verify, that the traversing the undo-tree
structure works as it is supposed to be. I am not sure this is correct,
though it seems to work)
[1]: /home/chrisbra/undo_save_nr_cur.patch
[2]: /home/chrisbra/changenr.patch
[3]: /home/chrisbra/undo_savenr.patch
regards,
Christian
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff --git a/src/undo.c b/src/undo.c
--- a/src/undo.c
+++ b/src/undo.c
@@ -1861,6 +1861,7 @@
curbuf->b_u_seq_cur = seq_cur;
curbuf->b_u_time_cur = seq_time;
curbuf->b_u_save_nr_last = last_save_nr;
+ curbuf->b_u_save_nr_cur = last_save_nr;
curbuf->b_u_synced = TRUE;
vim_free(uhp_table);
diff --git a/runtime/doc/undo.txt b/runtime/doc/undo.txt
--- a/runtime/doc/undo.txt
+++ b/runtime/doc/undo.txt
@@ -27,6 +27,9 @@
:u[ndo] {N} Jump to after change number {N}. See |undo-branches|
for the meaning of {N}. {not in Vi}
+:u[ndo] {N}f Jump to after save number {N}. See |undo-branches|
+ for the meaning of {N}. {not in Vi}
+
*CTRL-R*
CTRL-R Redo [count] changes which were undone. {Vi: redraw
screen}
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -994,7 +994,7 @@
EX(CMD_tunmenu, "tunmenu", ex_menu,
EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN),
EX(CMD_undo, "undo", ex_undo,
- RANGE|NOTADR|COUNT|ZEROR|TRLBAR|CMDWIN),
+ RANGE|NOTADR|COUNT|ZEROR|TRLBAR|CMDWIN|WORD1),
EX(CMD_undojoin, "undojoin", ex_undojoin,
TRLBAR|CMDWIN),
EX(CMD_undolist, "undolist", ex_undolist,
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -8493,9 +8493,34 @@
*/
static void
ex_undo(eap)
- exarg_T *eap UNUSED;
-{
- if (eap->addr_count == 1) /* :undo 123 */
+ exarg_T *eap;
+{
+ long count = 0;
+ int file = FALSE;
+ char_u *p = eap->arg;
+
+ if (*p == NUL)
+ count = 1;
+ else if (*p == 'f')
+ {
+ ++p;
+ file = TRUE;
+ }
+
+ if (*p != NUL)
+ EMSG2(_(e_invarg2), eap->arg);
+ else if (file)
+ {
+ if (eap->line2 <= 0)
+ count = 1;
+ else if (eap->line2 > curbuf->b_u_save_nr_last)
+ count = curbuf->b_u_save_nr_last;
+ else
+ count = eap->line2;
+ count = u_getChangenr(curbuf->b_u_oldhead, count);
+ undo_time(count, FALSE, FALSE, TRUE);
+ }
+ else if (eap->addr_count == 1) /* :undo 123 */
undo_time(eap->line2, FALSE, FALSE, TRUE);
else
u_undo(1);
diff --git a/src/undo.c b/src/undo.c
--- a/src/undo.c
+++ b/src/undo.c
@@ -3311,6 +3312,43 @@
#endif
(curbuf->b_changed || file_ff_differs(curbuf));
}
+ long
+u_getChangenr(uh, savenr)
+ u_header_T *uh;
+ long savenr;
+{
+ u_header_T *uhp = uh;
+ int val=0;
+ int mark;
+ mark = ++lastmark;
+ while (uhp != NULL)
+ {
+ /* Serialize current UHP if we haven't seen it */
+ if (uhp->uh_walk != mark)
+ {
+ uhp->uh_walk = mark;
+#ifdef U_DEBUG
+ ++headers_written;
+#endif
+ }
+ if (uhp->uh_save_nr == savenr)
+ val=uhp->uh_seq;
+ /* Now walk through the tree - algorithm from undo_time(). */
+ if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark)
+ uhp = uhp->uh_prev.ptr;
+ else if (uhp->uh_alt_next.ptr != NULL
+ && uhp->uh_alt_next.ptr->uh_walk != mark)
+ uhp = uhp->uh_alt_next.ptr;
+ else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
+ && uhp->uh_next.ptr->uh_walk != mark)
+ uhp = uhp->uh_next.ptr;
+ else if (uhp->uh_alt_prev.ptr != NULL)
+ uhp = uhp->uh_alt_prev.ptr;
+ else
+ uhp = uhp->uh_next.ptr;
+ }
+ return val;
+}
#if defined(FEAT_EVAL) || defined(PROTO)
/*
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1692,7 +1692,7 @@
call( {func}, {arglist} [, {dict}])
any call {func} with arguments {arglist}
ceil( {expr}) Float round {expr} up
-changenr() Number current change number
+changenr( [save_nr]) Number current change number
char2nr( {expr}) Number ASCII value of first char in {expr}
cindent( {lnum}) Number C indent for line {lnum}
clearmatches() none clear all matches
@@ -2242,13 +2242,16 @@
< 4.0
{only available when compiled with the |+float| feature}
-changenr() *changenr()*
+changenr([save_nr]) *changenr()*
Return the number of the most recent change. This is the same
number as what is displayed with |:undolist| and can be used
with the |:undo| command.
When a change was made it is the number of that change. After
redo it is the number of the redone change. After undo it is
one less than the number of the undone change.
+ If the optional argument [save_nr] is one, this will output
+ the number of the last save count. This can be used together
+ with the |:later| and |:earlier| commands.
char2nr({expr}) *char2nr()*
Return number value of the first char in {expr}. Examples: >
diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -7675,7 +7675,7 @@
#ifdef FEAT_FLOAT
{"ceil", 1, 1, f_ceil},
#endif
- {"changenr", 0, 0, f_changenr},
+ {"changenr", 0, 1, f_changenr},
{"char2nr", 1, 1, f_char2nr},
{"cindent", 1, 1, f_cindent},
{"clearmatches", 0, 0, f_clearmatches},
@@ -9071,7 +9071,13 @@
typval_T *argvars UNUSED;
typval_T *rettv;
{
- rettv->vval.v_number = curbuf->b_u_seq_cur;
+ if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1)
+ rettv->vval.v_number = curbuf->b_u_save_nr_cur;
+ else
+ rettv->vval.v_number = curbuf->b_u_seq_cur;
}
/*