This question refers exclusively to interactive functions that modify the contents of the current buffer.
What does one need to do to ensure that a single execution of (undo)
, right after running the function, will fully undo all the changes it made to the buffer's contents?
(For the rest of this post I'll use the word undoable to mean "can be undone with a single execution of (undo)
".)
Apparently, interactive functions are not undoable by default, as the example below shows.
(NB: I stress that the function below is just an example of the problem; I'm looking for a general solution, not one that just works for this particular function/use-case. Also, please do not use this function! In addition to not being undoable, it has other shortcomings.)
The function quote-region
inserts single quotes at the beginning and end of the current region, and replaces all occurrences of single quotes in-between with a backslash-escaped single quote:
(defun quote-region ()
(interactive)
(let ((beginning (region-beginning))
(end (region-end)))
(goto-char end)
(insert "'")
(replace-string "'" "\\'" nil beginning end)
(goto-char beginning)
(insert "'")
))
For example, if the current region's content is
foo'bar
...then running M-x quote-region
will change it to
'foo\'bar'
...as desired.
But if I now hit C-/
(undo
), the buffer changes to
foo'bar'
I must then hit C-/
a second time to return to
foo'bar
Hence quote-region
is not undoable, as defined above.