0

When undoing you can press Ctrl-G to redo.

This runs keyboard-quit which signals quit.

However this isn't convenient because as far as I know you can't run commands after keyboard-quit.

Is there a more direct way to break the undo chain, or a way to run keyboard-quit so you can keep calling functions after it?


I tried this for an undo/redo that doesn't require explicit Ctrl-G.


(defvar-local my-undo-is-redo nil)

(defun my-redo ()
  (interactive)
  (let ((inhibit-quit t))
    (unless my-undo-is-redo (with-local-quit (keyboard-quit)))
    ;; redo continued...
    (undo)
    (setq my-undo-is-redo t)))

(defun my-undo-only ()
  (interactive)
  (undo-only)
  (setq my-undo-is-redo nil))

(define-key evil-normal-state-map (kbd "u") 'my-undo-only)
(define-key evil-normal-state-map (kbd "C-r") 'my-redo)

7
  • It is not quite clear what you are aiming at. Note that there is the construction (let ((inhibit-quit t)) (with-local-quit ... (command-where-quit-might-occur) ...) (function-after-it)).
    – Tobias
    Commented Aug 7, 2019 at 0:35
  • Something like this could work, but it didn't in my tests, edited question.
    – ideasman42
    Commented Aug 7, 2019 at 7:19
  • I think you just need (setq last-command 'ignore) to break the the undo chain. But then the redo chain gets broken too so it doesn't work very well...
    – npostavs
    Commented Aug 7, 2019 at 10:20
  • Note, that there is undo-tree supporting undo/redo in the undo tree by <up>, <down>, <left>, and <right>. I switched to undo-tree and never went back. Always when I test code with emacs -Q I notice how much I like undo-tree more than the standard undo system of Emacs.
    – Tobias
    Commented Aug 7, 2019 at 12:10
  • Are you trying to reinvent redo+? Or maybe you should go all the way to undo-tree... Commented Aug 7, 2019 at 13:33

2 Answers 2

2

undo decides to chain or not based on the value of last-command, so if you just set it to something other than undo it will break the chain. No need for quitting.

(defun my-redo ()
  (interactive)
  (setq last-command 'ignore)
  ;; redo continued...
  (undo))
0

Here's undo/redo for evil mode using the method described by @npostavs.

(defun my-redo ()
  (interactive)
  ;; Break undo chain, avoid having to press Ctrl-G.
  (when (string= last-command 'undo)
    (setq last-command 'ignore))
  (undo))

(defun my-undo ()
  (interactive)
  (undo-only)
  (setq this-command 'undo))

(define-key evil-normal-state-map (kbd "u") 'my-undo)
(define-key evil-normal-state-map (kbd "C-r") 'my-redo))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.