Undo changes in Emacs with ‘C-/’
, ‘C-x u’
or `C-_
’.
Quoting the EmacsManual,
‘C-/’
(or its aliases) undo earlier and earlier changes in the current buffer. If all the recorded changes have already been undone, the undo command signals an error.‘C-f’
or any other command that harmlessly breaks the sequence of undoing; then type ‘C-/’
to undo the undo command.‘M-x undo-only’
. This is like ‘undo’
, but will not redo changes you have just undone.When there is an active region, SelectiveUndo is performed on the region.
By default, Emacs keeps only a few dozen undo entries. You can control how many it keeps by customizing option ‘undo-limit’
.
Having once undone a change with ‘C-x u’
or `C-_
’ or ‘C-/’
, you can repeat the undo command by pressing ‘C-x z’
, which is ‘repeat’
. So the overall sequence of ‘C-x u C-x z z z z z’
undoes changes back through time, and may be easier to type than `C-_ C-_
…’.
Binding undo to ‘C-z’
makes it easier to use (and the command ‘suspend-frame’
is still available on ‘C-x C-z’
).
(global-unset-key "\C-z") (global-set-key "\C-z" 'advertised-undo)
Is a thin-convenience wrapper, adding undo/redo functionality over emacs built-in undo.
The UndoFu package does this without intrusive hooks or undo history manipulation which can be error prone.
Some people have trouble with the lack of redo or a way to browse the undo tree. There is no built-in way to do these things (aside from mentally trying to keep track of a long string of changes including undos, which some people find very difficult). The UndoTree package solves this issue nicely.
Here’s a command that will do all the possible undo actions available in the buffer. Use it by EvaluatingExpressions or adding it to your InitFile.
(defun undo-all () "Undo all edits." (interactive) (when (listp pending-undo-list) (undo)) (while (listp pending-undo-list) (undo-more 1)) (message "Buffer was completely undone"))
See also RevertBuffer.
Sometimes you want to change a buffer briefly, then change it back. Perhaps like momentary-string-display or PopupRuler where you don’t want the user’s undo list affected.
(defmacro temporary-invisible-change (&rest forms) "Executes FORMS with a temporary buffer-undo-list, undoing on return. The changes you make within FORMS are undone before returning. But more importantly, the buffer's buffer-undo-list is not affected. This allows you to temporarily modify read-only buffers too." `(let* ((buffer-undo-list) (modified (buffer-modified-p)) (inhibit-read-only t)) (save-excursion (unwind-protect (progn ,@forms) (primitive-undo (length buffer-undo-list) buffer-undo-list) (set-buffer-modified-p modified))) nil))
You would use this either with some kind of delay or read-event so a user sees what happened, or for operations like inserting form feed characters in before printing but having them removed again without a trace afterwords.
(temporary-invisible-change (insert "try this") (forward-line) (insert "try that") (read-key-sequence-vector "Any event:"))