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

Commit: 
https://github.com/vim/vim/commit/5fee11114975b7405b7ccd3ee8758e54bf559760
Author: Devin J. Pohly <djpo...@gmail.com>
Date:   Sun Apr 23 20:26:59 2023 -0500

    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 <c...@256bit.org>
    Co-authored-by: zeertzjq <zeert...@outlook.com>
    Co-authored-by: Devin J. Pohly <djpo...@gmail.com>

diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 34f76d6f4..e74b39740 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -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}]])
@@ -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"
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index 60903f922..93c19b514 100644
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -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.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 2d6792af4..2112fbb1b 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -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'
 
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 8970ac793..0903fa8e6 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -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},
diff --git a/src/testdir/test_undo.vim b/src/testdir/test_undo.vim
index 2529e2108..461b28f69 100644
--- a/src/testdir/test_undo.vim
+++ b/src/testdir/test_undo.vim
@@ -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
diff --git a/src/undo.c b/src/undo.c
index 9e122f932..85c46707e 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -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;
@@ -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);
@@ -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);
            }
        }
@@ -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);
     }
 }
diff --git a/src/version.c b/src/version.c
index 713421813..f4c73e799 100644
--- a/src/version.c
+++ b/src/version.c
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1686,
 /**/
     1685,
 /**/

-- 
-- 
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

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1qUZEr-00F9X3-RX%40256bit.org.

Raspunde prin e-mail lui