It is often useful to move point “temporarily” within a localized
portion of the program. This is called an excursion, and it is
done with the save-excursion
special form. This construct
remembers the initial identity of the current buffer, and its values
of point and the mark, and restores them after the excursion
completes. It is the standard way to move point within one part of a
program and avoid affecting the rest of the program, and is used
thousands of times in the Lisp sources of Emacs.
If you only need to save and restore the identity of the current
buffer, use save-current-buffer
or with-current-buffer
instead (see Current Buffer). If you need to save or restore
window configurations, see the forms described in Window Configurations and in Frame Configurations.
This special form saves the identity of the current buffer and the
values of point and the mark in it, evaluates body, and finally
restores the buffer and its saved values of point and the mark. All
three saved values are restored even in case of an abnormal exit via
throw
or error (see Nonlocal Exits).
The value returned by save-excursion
is the result of the last
form in body, or nil
if no body forms were given.
Because save-excursion
only saves point and mark for the
buffer that was current at the start of the excursion, any changes
made to point and/or mark in other buffers, during the excursion, will
remain in effect afterward. This frequently leads to unintended
consequences, so the byte compiler warns if you call set-buffer
during an excursion:
Warning: Use `with-current-buffer' rather than save-excursion+set-buffer
To avoid such problems, you should call save-excursion
only
after setting the desired current buffer, as in the following example:
(defun append-string-to-buffer (string buffer) "Append STRING to the end of BUFFER." (with-current-buffer buffer (save-excursion (goto-char (point-max)) (insert string))))
Likewise, save-excursion
does not restore window-buffer
correspondences altered by functions such as switch-to-buffer
.
Warning: Ordinary insertion of text adjacent to the saved
point value relocates the saved value, just as it relocates all
markers. More precisely, the saved value is a marker with insertion
type nil
. See Marker Insertion Types. Therefore, when the
saved point value is restored, it normally comes before the inserted
text.
Although save-excursion
saves the location of the mark, it does
not prevent functions which modify the buffer from setting
deactivate-mark
, and thus causing the deactivation of the mark
after the command finishes. See The Mark.