8

From the save-excursion docstring:

Save point, mark, and current buffer; execute BODY; restore those things.

My understanding was that the restored buffer would again be visible following the evaluation of the body, but that appears not to be the case. A basic function demonstrating the behavior that I find surprising:

(defun test-excursion () (interactive) (save-excursion (find-file "just-a-test")) (insert "blah")) 

On my system (using emacs -q; running Debian version 24.5.1) interactively running this function using M-x test-excursion I get most of the behavior I expect. A new empty file buffer is created (there is no such file on disk) named "just-a-test" and "blah" is inserted in the scratch buffer that I happened to have open at the time. However; the buffer that remains visible is "just-a-test" and not "*scratch*" which was (current-buffer) at the time the command was invoked. No additional windows were created. It is only apparent by switching back to "*scratch*" that the string was inserted as expected.

My memory may be inaccurate on this, but I recall using save-excursion when writing a function and observing the alternate behavior (the restored buffer restored as visible). Is there any chance that this behavior has changed or that there has been a regression in 24.5.1? I know that the definition has changed in 25. I checked on another system (also 24.5.1) and observed the same behavior as my system. Evaluation non-interactively (via eval-last-sexp) yields the same. switch-buffer and save-current-buffer also yield the same.

My understanding is that each window (in the emacs sense) has a current buffer (edit: perhaps appropriately referred to simply as the "displayed buffer" and is returned by current-buffer when the window has focus) which necessarily is visible and there are no other conceptions of a "visible buffer". If save-excursion restores the current buffer then shouldn't it be visible?

I've been scratching my head at this one for a while. I hope someone can help me out.

2 Answers 2

9

The current buffer need not be visible in a window.

You're looking for save-window-excursion (or quite possibly a combination of the two).

n.b. C-uC-ha ^save- will point out all of the following:

save-current-buffer Function: Record which buffer is current; execute BODY; make that buffer current. save-excursion Function: Save point, mark, and current buffer; execute BODY; restore those things. save-match-data Macro: Execute the BODY forms, restoring the global value of the match data. save-restriction Function: Execute BODY, saving and restoring current buffer's restrictions. save-selected-window Macro: Execute BODY, then select the previously selected window. save-window-excursion Macro: Execute BODY, then restore previous window configuration. 
3
  • Do all windows necessarily lack focus when current-buffer is not visible? I don't ever recall observing emacs in such a state, but it would be a rare condition in the first place. Commented Jun 22, 2016 at 23:22
  • 2
    The documentation for set-buffer suggests that the command loop restores the current buffer to the selected window's buffer at the end of each command, in which case that wouldn't be a state that Emacs could get into. Commented Jun 23, 2016 at 0:40
  • Confirmed by (elisp) Current Buffer which states "When an editing command returns to the editor command loop, Emacs automatically calls ‘set-buffer’ on the buffer shown in the selected window." Commented Jun 23, 2016 at 1:26
4

Facing a similar problem, I realize this behavior is due to find-file in particular. I didn't try using save-window-excursion instead of save-excursion. What I used instead was

(with-current-buffer (find-file-noselect "just-a-test") (insert "blah")) 

That way, just-a-test is loaded or switched to if it already visited in the background. It remains open. As far as I can see, for this simple example the two methods (this and the one by phils) is a matter of taste.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.