Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live diffing (like undo-tree has) #112

Open
Martinsos opened this issue Oct 23, 2024 · 2 comments
Open

Live diffing (like undo-tree has) #112

Martinsos opened this issue Oct 23, 2024 · 2 comments

Comments

@Martinsos
Copy link

Hi, first of all thanks a lot for this package and effort that goes into it!

I have been using undo-tree for years but learned about undo-fu + vundo combo and decided to switch, and I love it, the only thing I have been missing is how undo-tree shows diff. What it does, if I am correct, is show diff between the node you are currently viewing and the node before it, therefore giving you an idea of the changes that this node introduces. I find this super helpful and it usually helps me figure out where I made specific change, so I can go back there, pick a piece of it maybe, then return, and similar. This is done "live" -> so as you move around the tree, the diff window is updated.

I know vundo has the option to show diff on demand, but that makes the workflow from above much harder, I would have to keep marking and unmarking nodes.

How hard would this be to add? Maybe I can help out? I am experienced programmer but not with elisp, however I could probably find my way around with enough time. Would this be a good match for vundo, both regarding DX and current architecture?

Also, do you have any suggestion on how I might hack this in the meantime? Maybe I could hook in into the move functions of vundo (with advice?) and try to automate marking, unmarking, and diffing to run on every move hm.

Thanks!

@casouri
Copy link
Owner

casouri commented Oct 24, 2024

Thanks for your kind words :)

Try this:

(defun vundo-live-diff-post-command ()
  "Post command hook function for live diffing."
  (when (and vundo-diff--marked-node
             (not (memq this-command
                        '(vundo-quit vundo-confirm))))
    (vundo-diff)))

(define-minor-mode vundo-live-diff-mode
  "Live diff when moving in vundo buffer."
  :lighter ""
  (if vundo-live-diff-mode
      (add-hook 'post-command-hook #'vundo-live-diff-post-command 0 t)
    (remove-hook 'post-command-hook #'vundo-live-diff-post-command t)))

(define-key vundo-mode-map (kbd "D") #'vundo-live-diff-mode)

@Martinsos
Copy link
Author

Thanks for this @casouri !

I went a step further and ended up with this:

;; Displays undo history as a tree and lets you move through it.
(use-package vundo
  :defer t
  :config
  (setq vundo-glyph-alist vundo-unicode-symbols)

  ;;;;;; Vundo Live Diff ;;;;;;
  ;; In vundo, you have to manually mark one node and call diff on another node to get their diff.
  ;; Here we extend vundo to have "live diff mode", that always shows diff between current node and its parent.
  ;; I turn it on by default. It can be toggled by pressing "f".
  (defun vundo-live-diff-post-command ()
    "Post command hook function for live diffing."
    (when (not (memq this-command '(vundo-quit vundo-confirm)))
      (progn
	(vundo-diff-mark (vundo-m-parent (vundo--current-node vundo--prev-mod-list)))
        (vundo-diff)
      )
    )
  )
  (define-minor-mode vundo-live-diff-mode
    "Shows live diff between the current node and its parent."
    :lighter nil
    (if vundo-live-diff-mode
      (add-hook 'post-command-hook #'vundo-live-diff-post-command 0 t)
      (remove-hook 'post-command-hook #'vundo-live-diff-post-command t)
    )
  )
  (evil-define-key 'normal vundo-mode-map (kbd "F") #'vundo-live-diff-mode)
  (add-hook 'vundo-mode-hook (lambda () (vundo-live-diff-mode 1)))
  ;;;;;/ Vundo Live Diff ;;;;;;
)

Now, diff opens immediately, and mark follows the current node so we always see the diff between it and its parent -> this is exactly the behaviour from node-tree that I wanted to replicate. And I can turn it off, of course, if I want.

Your code helped a lot, I never wrote minor mode and wouldn't think of it as a solution, and it also helped a lot the fact that the code in vundo(-diff).el is quite nicely written / documented.

Btw, a couple of weird errors I hit:

  1. First time I was testing it I was getting ; Error in post-command-hook (vundo-live-diff-post-command): (error "No possible route") error that would crash the minor mode. I was able to trigger it by moving over saved node, but not consistently, and later I wasn't able to replicate it at all, so maybe it was caused by my live evaling of parts of init.el, not sure.
  2. Later, I hit another situation where buffer content went bonkers, parts of text closer to start of the buffer started appearing at the middle of the buffer, all mixed. Here I am sure I didn't do any half evals, and I think I triggered it by moving really fast through the undo tree. Not sure if this is something already known, or I caused it by live-diff -> although I don't see how this code could have caused it. I also wasn't successful in replicating this again, but I haven't tried for long.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants