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
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.)
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
M-x quote-region will change it to
But if I now hit
undo), the buffer changes to
I must then hit
C-/ a second time to return to
quote-region is not undoable, as defined above.