Skip to content

Commit

Permalink
patch 9.0.1686: undotree() only works for the current buffer
Browse files Browse the repository at this point in the history
Problem:    undotree() only works for the current buffer
Solution:   Add an optional "buffer number" parameter to undotree().  If
            omitted, use the current buffer for backwards compatibility.

closes: #4001
closes: #12292

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Devin J. Pohly <djpohly@gmail.com>
  • Loading branch information
2 people authored and chrisbra committed Aug 11, 2023
1 parent 422b9dc commit 5fee111
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 21 deletions.
9 changes: 5 additions & 4 deletions runtime/doc/builtin.txt
Expand Up @@ -707,7 +707,7 @@ trunc({expr}) Float truncate Float {expr}
type({expr}) Number type of value {expr}
typename({expr}) String representation of the type of {expr}
undofile({name}) String undo file name for {name}
undotree() List undo file tree
undotree([{buf}]) List undo file tree for buffer {buf}
uniq({list} [, {func} [, {dict}]])
List remove adjacent duplicates from a list
utf16idx({string}, {idx} [, {countcc} [, {charidx}]])
Expand Down Expand Up @@ -10073,9 +10073,10 @@ undofile({name}) *undofile()*
Can also be used as a |method|: >
GetFilename()->undofile()
undotree() *undotree()*
Return the current state of the undo tree in a dictionary with
the following items:
undotree([{buf}]) *undotree()*
Return the current state of the undo tree for the current
buffer, or for a specific buffer if {buf} is given. The
result is a dictionary with the following items:
"seq_last" The highest undo sequence number used.
"seq_cur" The sequence number of the current position in
the undo tree. This differs from "seq_last"
Expand Down
1 change: 0 additions & 1 deletion runtime/doc/todo.txt
Expand Up @@ -5535,7 +5535,6 @@ Undo:
- Undo history wrong when ":next file" re-uses a buffer. (#5426) ex_next()
should pass flag to do_argfile(), then to do_ecmd(). Is there a test for
this?
- Add buffer argument to undotree(). (#4001)
- Undo problem: "g-" doesn't go back, gets stuck. (Björn Linse, 2016 Jul 18)
- Undo message is not always properly displayed. Patch by Ken Takata, 2013
oct 3. Doesn't work properly according to Yukihiro Nakadaira.
Expand Down
2 changes: 1 addition & 1 deletion runtime/doc/usr_41.txt
Expand Up @@ -1373,7 +1373,7 @@ Various: *various-functions*
libcallnr() idem, returning a number

undofile() get the name of the undo file
undotree() return the state of the undo tree
undotree() return the state of the undo tree for a buffer

shiftwidth() effective value of 'shiftwidth'

Expand Down
2 changes: 1 addition & 1 deletion src/evalfunc.c
Expand Up @@ -2798,7 +2798,7 @@ static funcentry_T global_functions[] =
ret_string, f_typename},
{"undofile", 1, 1, FEARG_1, arg1_string,
ret_string, f_undofile},
{"undotree", 0, 0, 0, NULL,
{"undotree", 0, 1, FEARG_1, arg1_buffer,
ret_dict_any, f_undotree},
{"uniq", 1, 3, FEARG_1, arg13_sortuniq,
ret_first_arg, f_uniq},
Expand Down
47 changes: 47 additions & 0 deletions src/testdir/test_undo.vim
Expand Up @@ -93,6 +93,53 @@ func FillBuffer()
endfor
endfunc

func Test_undotree_bufnr()
new
let buf1 = bufnr()

normal! Aabc
set ul=100

" Save undo tree without bufnr as ground truth for buffer 1
let d1 = undotree()

new
let buf2 = bufnr()

normal! Adef
set ul=100

normal! Aghi
set ul=100

" Save undo tree without bufnr as ground truth for buffer 2
let d2 = undotree()

" Check undotree() with bufnr argument
let d = undotree(buf1)
call assert_equal(d1, d)
call assert_notequal(d2, d)

let d = undotree(buf2)
call assert_notequal(d1, d)
call assert_equal(d2, d)

" Switch buffers and check again
wincmd p

let d = undotree(buf1)
call assert_equal(d1, d)

let d = undotree(buf2)
call assert_notequal(d1, d)
call assert_equal(d2, d)

" Drop created windows
set ul&
new
only!
endfunc

func Test_global_local_undolevels()
new one
set undolevels=5
Expand Down
40 changes: 26 additions & 14 deletions src/undo.c
Expand Up @@ -3629,7 +3629,7 @@ curbufIsChanged(void)
* Recursive.
*/
static void
u_eval_tree(u_header_T *first_uhp, list_T *list)
u_eval_tree(buf_T *buf, u_header_T *first_uhp, list_T *list)
{
u_header_T *uhp = first_uhp;
dict_T *dict;
Expand All @@ -3641,9 +3641,9 @@ u_eval_tree(u_header_T *first_uhp, list_T *list)
return;
dict_add_number(dict, "seq", uhp->uh_seq);
dict_add_number(dict, "time", (long)uhp->uh_time);
if (uhp == curbuf->b_u_newhead)
if (uhp == buf->b_u_newhead)
dict_add_number(dict, "newhead", 1);
if (uhp == curbuf->b_u_curhead)
if (uhp == buf->b_u_curhead)
dict_add_number(dict, "curhead", 1);
if (uhp->uh_save_nr > 0)
dict_add_number(dict, "save", uhp->uh_save_nr);
Expand All @@ -3655,7 +3655,7 @@ u_eval_tree(u_header_T *first_uhp, list_T *list)
if (alt_list != NULL)
{
// Recursive call to add alternate undo tree.
u_eval_tree(uhp->uh_alt_next.ptr, alt_list);
u_eval_tree(buf, uhp->uh_alt_next.ptr, alt_list);
dict_add_list(dict, "alt", alt_list);
}
}
Expand Down Expand Up @@ -3721,28 +3721,40 @@ u_undofile_reset_and_delete(buf_T *buf)
#endif

/*
* "undotree()" function
* "undotree(expr)" function
*/
void
f_undotree(typval_T *argvars UNUSED, typval_T *rettv)
{
typval_T *tv = &argvars[0];
buf_T *buf;
dict_T *dict;
list_T *list;

if (in_vim9script() && check_for_opt_buffer_arg(argvars, 0) == FAIL)
return;

if (tv->v_type == VAR_UNKNOWN)
buf = curbuf;
else
buf = tv_get_buf_from_arg(tv);

if (rettv_dict_alloc(rettv) == FAIL)
return;

dict_T *dict = rettv->vval.v_dict;
list_T *list;
dict = rettv->vval.v_dict;

dict_add_number(dict, "synced", (long)curbuf->b_u_synced);
dict_add_number(dict, "seq_last", curbuf->b_u_seq_last);
dict_add_number(dict, "save_last", curbuf->b_u_save_nr_last);
dict_add_number(dict, "seq_cur", curbuf->b_u_seq_cur);
dict_add_number(dict, "time_cur", (long)curbuf->b_u_time_cur);
dict_add_number(dict, "save_cur", curbuf->b_u_save_nr_cur);
dict_add_number(dict, "synced", (long)buf->b_u_synced);
dict_add_number(dict, "seq_last", buf->b_u_seq_last);
dict_add_number(dict, "save_last", buf->b_u_save_nr_last);
dict_add_number(dict, "seq_cur", buf->b_u_seq_cur);
dict_add_number(dict, "time_cur", (long)buf->b_u_time_cur);
dict_add_number(dict, "save_cur", buf->b_u_save_nr_cur);

list = list_alloc();
if (list != NULL)
{
u_eval_tree(curbuf->b_u_oldhead, list);
u_eval_tree(buf, buf->b_u_oldhead, list);
dict_add_list(dict, "entries", list);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -695,6 +695,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1686,
/**/
1685,
/**/
Expand Down

0 comments on commit 5fee111

Please sign in to comment.