4

In particular, I am using undo-tree-undo.

When I type a few words in a line, and undo, all those words disappear. Same thing happens when I type a function name and screw up a couple of symbols in the end - undo eats up the whole line.

Is there a way to adjust how eager undo is?

(Similar question for native undo: fine-grained undo)

user3496846
  • 378
  • 1
  • 10
  • duplicate? the other thread is for native undo, this one is for undo-tree as explained in the comments of the answer below – user3496846 Feb 16 '19 at 09:05

1 Answers1

2

I like to do two things with undo. I turn off the amalgamation stuff (which by doing so permits undo one keystroke at a time); and, I get rid of the timer (because timers affect performance and drive me absolutely bonkers, unless they are idle-timers).

(when (timerp undo-auto-current-boundary-timer)
  (cancel-timer undo-auto-current-boundary-timer))

(fset 'undo-auto--undoable-change
      (lambda () (add-to-list 'undo-auto--undoably-changed-buffers (current-buffer))))

(fset 'undo-auto-amalgamate 'ignore)

Alternatively, you can modify the function undo-auto-amalgamate (which is hard coded at 20) and set it to a lesser/greater amount.

lawlist
  • 18,826
  • 5
  • 37
  • 118
  • Why did you copy your answer from https://emacs.stackexchange.com/questions/47341/fine-grained-undo/47349#47349 rather than close the question as a duplicate? Do you think that there are potential answers to this question that wouldn't work for the earlier question? – Gilles 'SO- stop being evil' Feb 13 '19 at 18:10
  • @Gilles -- I am of the opinion that most people who use `undo-tree` would have no way of knowing that the answer applies equally to native undo (without `undo-tree`) and also to `undo-tree`. `undo-tree` is a complex library. I previously spent a couple hundred hours (*probably more*) creating a fork of `undo-tree` (with some assistance of a few forum participants who provided certain functions and guidance). Perhaps the only people who would know the answers are equally applicable are me, Stefan, Dr. Cubitt, Tobias, .... [and anyone who reads this comment :) ]. – lawlist Feb 13 '19 at 18:19
  • I see. What works for native undo might not work for undo-tree and vice versa. This does make sense, thanks. – Gilles 'SO- stop being evil' Feb 13 '19 at 18:27
  • Nice point on timers! I do see some results. When I delete a word after typing or issue some other command, undo catches up on that. But typing a dozen words and undoing (even on multiple lines) the whole line is removed by undoing. A couple of words would arguably be nicer. Modifying `last-amalgamating-count` to 2 or 50 from 20 seems of no help on this one too, unfortunately. Any ideas? – user3496846 Feb 13 '19 at 18:28
  • @user3496846 -- type `M-x find-function RET undo-auto-amalgamate RET` and see where it is hard-coded to 20. And, the timer also creates an undo boundary. – lawlist Feb 13 '19 at 18:29
  • @lawlist I have copied the whole function to my .emacs and set the value there. So, `find-function` points there. – user3496846 Feb 13 '19 at 18:33
  • @user3496846 -- If you want something more than 1 (which the answer above accomplishes) and less than 20, then you need to change the hard-coded value from 20 to a different amount; e.g., 5 instead of 20. – lawlist Feb 13 '19 at 18:36
  • @lawlist, that's what I do. I have the whole function in my `.emacs` and change 20 to other values (then save and launch another instance of emacs to see the changes). I can't modify the original file read-only `simple.el.gz`. But maybe modifying the function in `simple.el.gz` somehow and byte-compiling is what I need to do instead? – user3496846 Feb 13 '19 at 18:40
  • @user3496846 -- to try it out, first paste `undo-auto-amalgamate` into a `*scratch*` buffer and change the number 20 to something like 5. Then, type `M-x eval-buffer`. Then, do some **NEW** typing, and then do some undo/redos and see if you like it. Then, you can paste the modified function into your `.emacs` file, save, and restart. If the modified function is not being recognized, then you'll need to see if your `.emacs` contains an error and perhaps stops loading before reaching your modified code. Methods for debugging might include placing messages before/after the modified function. – lawlist Feb 13 '19 at 18:45
  • @lawlist I did as you said. For any values that I check (I tried a few from 0 to 100), if I just type `(defun hello-wolrd () (hello-world))` and call `undo-tree-undo`, both lines are removed (do you have the same behavior?). So, undo is being too greedy here nonetheless. `undo-auto-amalgamate` seems to account only for explicit commands and removals. – user3496846 Feb 13 '19 at 18:57
  • 1
    EX: (1) Launch Emacs 26.1 without any user-configuration (i.e., no `.emacs`, no `init.el`) aka `emacs -Q`. (2) `M-x list-packages`; (3) find the `undo-tree` package and install it; (4) type `M-x find-function` to locate and copy `undo-auto-amalgamate`; (5) switch to an empty `*scratch*` buffer and paste the copied function `undo-auto-amalgamate`; (6) change the number 20 to 3; (7) type `M-x eval-buffer`; (8) type `M-x undo-tree-mode`. (9) Place the cursor at the end of the copied function and hold down the backspace key for a few seconds. (10) `C-/` and watch the undo a few at at time. – lawlist Feb 13 '19 at 19:08
  • @lawlist it works! `C-/` works with my .emacs as well. `describe-key` says `u` and `C-/` both point to `undo-tree-undo`, yet `u` does something else, apparently in evil-mode map or some other map or using some hook. I think I can take it from here. Thank you for patience and an exhaustive answer! – user3496846 Feb 13 '19 at 19:38