Function: vundo--build-tree

vundo--build-tree is a natively compiled function defined in vundo.el.

Signature

(vundo--build-tree MOD-LIST MOD-HASH &optional FROM)

Documentation

Connect equivalent modifications and build the tree in MOD-LIST.

MOD-HASH maps undo-lists to modifications. If FROM non-nil, build from FORM-th modification in MOD-LIST.

Source Code

;; Defined in /nix/store/386w2ds6bdh3gcz9k23jssw4cni4lfr2-emacs-packages-deps/share/emacs/site-lisp/elpa/vundo-2.4.0/vundo.el
(defun vundo--build-tree (mod-list mod-hash &optional from)
  "Connect equivalent modifications and build the tree in MOD-LIST.
MOD-HASH maps undo-lists to modifications.
If FROM non-nil, build from FORM-th modification in MOD-LIST."
  (cl-loop
   for m from (or from 0) to (1- (length mod-list))
   for mod = (aref mod-list m)
   ;; If MOD is an undo, the buffer state it represents is equivalent
   ;; to a previous one.
   do (let ((prev-undo (undo--last-change-was-undo-p
                        (vundo-m-undo-list mod))))
        (pcase prev-undo
          ;; This is an undo. Merge it with its equivalent nodes.
          ((and (pred consp)
                ;; It is possible for us to not find the PREV-UNDO in
                ;; our mod-list: if Emacs garbage collected prev-m,
                ;; then it will not end up in mod-list. NOTE: Is it
                ;; also possible that unable to find PREV-M is an
                ;; error? Maybe, but I think that's highly unlikely.
                (guard (gethash prev-undo mod-hash)))
           (let ((prev-m (gethash prev-undo mod-hash)))
             (vundo--eqv-merge-mod prev-m mod)))
          ;; This undo undoes to root, merge with the root node.
          ('t (vundo--eqv-merge-mod (aref mod-list 0) mod))
          ;; This modification either is a region-undo, nil undo, or
          ;; not an undo. We treat them the same.
          ((or 'undo-in-region 'empty _)
           ;; If MOD isn't an undo, it represents a new buffer state,
           ;; we connect M-1 with M, where M-1 is the parent and M is
           ;; the child.
           (unless (eq m 0)
             (let* ((m-1 (aref mod-list (1- m)))
                    (min-eqv-mod (vundo--master-eqv-mod-of m-1)))
               (setf (vundo-m-parent mod) min-eqv-mod)
               (let ((children (vundo-m-children min-eqv-mod)))
                 ;; If everything goes right, we should never encounter
                 ;; this.
                 (cl-assert (not (memq mod children)))
                 (setf (vundo-m-children min-eqv-mod)
                       ;; We sort in reverse order, ie, later mod
                       ;; comes first. Later in `vundo--build-tree' we
                       ;; draw the tree depth-first.
                       (vundo--sort-mod (cons mod children)
                                        'reverse))))))))))