0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 9.0.1686: undotree() only works for the current buffer

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>
This commit is contained in:
Devin J. Pohly 2023-04-23 20:26:59 -05:00 committed by Christian Brabandt
parent 422b9dcbfa
commit 5fee111149
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
7 changed files with 82 additions and 21 deletions

View File

@ -707,7 +707,7 @@ trunc({expr}) Float truncate Float {expr}
type({expr}) Number type of value {expr} type({expr}) Number type of value {expr}
typename({expr}) String representation of the type of {expr} typename({expr}) String representation of the type of {expr}
undofile({name}) String undo file name for {name} 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}]]) uniq({list} [, {func} [, {dict}]])
List remove adjacent duplicates from a list List remove adjacent duplicates from a list
utf16idx({string}, {idx} [, {countcc} [, {charidx}]]) utf16idx({string}, {idx} [, {countcc} [, {charidx}]])
@ -10073,9 +10073,10 @@ undofile({name}) *undofile()*
Can also be used as a |method|: > Can also be used as a |method|: >
GetFilename()->undofile() GetFilename()->undofile()
undotree() *undotree()* undotree([{buf}]) *undotree()*
Return the current state of the undo tree in a dictionary with Return the current state of the undo tree for the current
the following items: 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_last" The highest undo sequence number used.
"seq_cur" The sequence number of the current position in "seq_cur" The sequence number of the current position in
the undo tree. This differs from "seq_last" the undo tree. This differs from "seq_last"

View File

@ -5535,7 +5535,6 @@ Undo:
- Undo history wrong when ":next file" re-uses a buffer. (#5426) ex_next() - 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 should pass flag to do_argfile(), then to do_ecmd(). Is there a test for
this? this?
- Add buffer argument to undotree(). (#4001)
- Undo problem: "g-" doesn't go back, gets stuck. (Björn Linse, 2016 Jul 18) - 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 - Undo message is not always properly displayed. Patch by Ken Takata, 2013
oct 3. Doesn't work properly according to Yukihiro Nakadaira. oct 3. Doesn't work properly according to Yukihiro Nakadaira.

View File

@ -1373,7 +1373,7 @@ Various: *various-functions*
libcallnr() idem, returning a number libcallnr() idem, returning a number
undofile() get the name of the undo file 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' shiftwidth() effective value of 'shiftwidth'

View File

@ -2798,7 +2798,7 @@ static funcentry_T global_functions[] =
ret_string, f_typename}, ret_string, f_typename},
{"undofile", 1, 1, FEARG_1, arg1_string, {"undofile", 1, 1, FEARG_1, arg1_string,
ret_string, f_undofile}, ret_string, f_undofile},
{"undotree", 0, 0, 0, NULL, {"undotree", 0, 1, FEARG_1, arg1_buffer,
ret_dict_any, f_undotree}, ret_dict_any, f_undotree},
{"uniq", 1, 3, FEARG_1, arg13_sortuniq, {"uniq", 1, 3, FEARG_1, arg13_sortuniq,
ret_first_arg, f_uniq}, ret_first_arg, f_uniq},

View File

@ -93,6 +93,53 @@ func FillBuffer()
endfor endfor
endfunc 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() func Test_global_local_undolevels()
new one new one
set undolevels=5 set undolevels=5

View File

@ -3629,7 +3629,7 @@ curbufIsChanged(void)
* Recursive. * Recursive.
*/ */
static void 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; u_header_T *uhp = first_uhp;
dict_T *dict; dict_T *dict;
@ -3641,9 +3641,9 @@ u_eval_tree(u_header_T *first_uhp, list_T *list)
return; return;
dict_add_number(dict, "seq", uhp->uh_seq); dict_add_number(dict, "seq", uhp->uh_seq);
dict_add_number(dict, "time", (long)uhp->uh_time); 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); dict_add_number(dict, "newhead", 1);
if (uhp == curbuf->b_u_curhead) if (uhp == buf->b_u_curhead)
dict_add_number(dict, "curhead", 1); dict_add_number(dict, "curhead", 1);
if (uhp->uh_save_nr > 0) if (uhp->uh_save_nr > 0)
dict_add_number(dict, "save", uhp->uh_save_nr); dict_add_number(dict, "save", uhp->uh_save_nr);
@ -3655,7 +3655,7 @@ u_eval_tree(u_header_T *first_uhp, list_T *list)
if (alt_list != NULL) if (alt_list != NULL)
{ {
// Recursive call to add alternate undo tree. // 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); dict_add_list(dict, "alt", alt_list);
} }
} }
@ -3721,28 +3721,40 @@ u_undofile_reset_and_delete(buf_T *buf)
#endif #endif
/* /*
* "undotree()" function * "undotree(expr)" function
*/ */
void void
f_undotree(typval_T *argvars UNUSED, typval_T *rettv) 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) if (rettv_dict_alloc(rettv) == FAIL)
return; return;
dict_T *dict = rettv->vval.v_dict; dict = rettv->vval.v_dict;
list_T *list;
dict_add_number(dict, "synced", (long)curbuf->b_u_synced); dict_add_number(dict, "synced", (long)buf->b_u_synced);
dict_add_number(dict, "seq_last", curbuf->b_u_seq_last); dict_add_number(dict, "seq_last", buf->b_u_seq_last);
dict_add_number(dict, "save_last", curbuf->b_u_save_nr_last); dict_add_number(dict, "save_last", buf->b_u_save_nr_last);
dict_add_number(dict, "seq_cur", curbuf->b_u_seq_cur); dict_add_number(dict, "seq_cur", buf->b_u_seq_cur);
dict_add_number(dict, "time_cur", (long)curbuf->b_u_time_cur); dict_add_number(dict, "time_cur", (long)buf->b_u_time_cur);
dict_add_number(dict, "save_cur", curbuf->b_u_save_nr_cur); dict_add_number(dict, "save_cur", buf->b_u_save_nr_cur);
list = list_alloc(); list = list_alloc();
if (list != NULL) 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); dict_add_list(dict, "entries", list);
} }
} }

View File

@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1686,
/**/ /**/
1685, 1685,
/**/ /**/