[This question is related to, but not a duplicate of, the question copy contents of current buffer in a temp buffer and operate on that. Besides other incidental things (e.g., the question itself is different), none of the solutions offered both (1) execute the elisp in the same context as the original buffer, AND (2) maintain the state of the original buffer. Indeed, the purpose of the macro offered as a possible solution (with-indirect-buffer-in-foo-mode
) in that question seems to be to actually edit the original text in a different mode. The macro also doesn't maintain the buffer-undo-list
, of course (nor any other 'state' that may change when the text of a buffer changes).]
I'd like to be able to write
(save-complete-buffer-state
(edit-the-buffer-arbitrarily)
(condition-p))
and have everything (or as much as is practical) be preserved from the original emacs buffer state before the call, including, for example, point, kill ring, undo list, etc. Does such a macro already exist? If not, how difficult would it be to implement? (What needs to be saved?)
(I've found c-save-buffer-state
at
Emacs: How to intelligently handle buffer-modified when setting text properties?
but I don't know enough about what needs to be done to understand how close this is to doing what I'm asking.)
EDIT: Using lawlist's and @phils' suggestions, I was able to come up with this solution. Please note that this macro works on a few simple test cases but has not been tested extensively.
(defmacro with-cloned-buffer (&rest body)
"Executes BODY just like `progn' but maintains original buffer state."
(declare (indent 0))
(let ((return-value (make-symbol "return-value")))
`(let (buffer-undo-list) ; maintain original buffer-undo-list
(clone-indirect-buffer nil t)
(let ((,return-value (progn ,@body)))
(primitive-undo 1 buffer-undo-list)
(kill-buffer-and-window)
,return-value))))
Here are two simple tests (first returns t
, second returns nil
):
(with-cloned-buffer
(insert "A")
(left-char 1)
(looking-at-p "A"))
(with-cloned-buffer
(insert "A")
(left-char 1)
(looking-at-p "B"))
(with-cloned-buffer ...)
macro makes slightly more sense than a(save-complete-buffer-state ...)
macro -- if you are not touching the original buffer, there's also nothing to fix if things go horribly wrong.