save-excursion
in append-to-buffer
The body of the let
expression in append-to-buffer
consists of a save-excursion
expression.
The save-excursion
function saves the locations of point and
mark, and restores them to those positions after the expressions in the
body of the save-excursion
complete execution. In addition,
save-excursion
keeps track of the original buffer, and
restores it. This is how save-excursion
is used in
append-to-buffer
.
Incidentally, it is worth noting here that a Lisp function is normally
formatted so that everything that is enclosed in a multi-line spread is
indented more to the right than the first symbol. In this function
definition, the let
is indented more than the defun
, and
the save-excursion
is indented more than the let
, like
this:
(defun ... ... ... (let... (save-excursion ...
This formatting convention makes it easy to see that the two lines in
the body of the save-excursion
are enclosed by the parentheses
associated with save-excursion
, just as the
save-excursion
itself is enclosed by the parentheses associated
with the let
:
(let ((oldbuf (current-buffer))) (save-excursion (set-buffer (get-buffer-create buffer)) (insert-buffer-substring oldbuf start end))))
The use of the save-excursion
function can be viewed as a process
of filling in the slots of a template:
(save-excursion first-expression-in-body second-expression-in-body ... last-expression-in-body)
In this function, the body of the save-excursion
contains only
two expressions. The body looks like this:
(set-buffer (get-buffer-create buffer)) (insert-buffer-substring oldbuf start end)
When the append-to-buffer
function is evaluated, the two
expressions in the body of the save-excursion
are evaluated in
sequence. The value of the last expression is returned as the value of
the save-excursion
function; the other expression is evaluated
only for its side effects.
The first line in the body of the save-excursion
uses the
set-buffer
function to change the current buffer to the one
specified in the first argument to append-to-buffer
. (Changing
the buffer is the side effect; as we have said before, in Lisp, a side
effect is often the primary thing we want.) The second line does the
primary work of the function.
The set-buffer
function changes Emacs' attention to the buffer to
which the text will be copied and from which save-excursion
will
return. The line looks like this:
(set-buffer (get-buffer-create buffer))
The innermost expression of this list is (get-buffer-create
buffer)
. This expression uses the get-buffer-create
function,
which either gets the named buffer, or if it does not exist, creates one
with the given name. This means you can use append-to-buffer
to
put text into a buffer that did not previously exist.
get-buffer-create
also keeps set-buffer
from getting an
unnecessary error: set-buffer
needs a buffer to go to; if you
were to specify a buffer that does not exist, Emacs would baulk.
Since get-buffer-create
will create a buffer if none exists,
set-buffer
is always provided with a buffer.
The last line of append-to-buffer
does the work of appending
the text:
(insert-buffer-substring oldbuf start end)
The insert-buffer-substring
function copies a string from
the buffer specified as its first argument and inserts the string into
the present buffer. In this case, the argument to
insert-buffer-substring
is the value of the variable created and
bound by the let
, namely the value of oldbuf
, which was
the current buffer when you gave the append-to-buffer
command.
After insert-buffer-substring
has done its work,
save-excursion
will restore the action to the original buffer and
append-to-buffer
will have done its job.
Written in skeletal form, the workings of the body look like this:
(let (bind-oldbuf
-to-value-of-current-buffer
) (save-excursion ; Keep track of buffer. change-buffer insert-substring-from-oldbuf
-into-buffer) change-back-to-original-buffer-when-finished let-the-local-meaning-of-oldbuf
-disappear-when-finished
In summary, append-to-buffer
works as follows: it saves the value
of the current buffer in the variable called oldbuf
. It gets the
new buffer, creating one if need be, and switches Emacs to it. Using
the value of oldbuf
, it inserts the region of text from the old
buffer into the new buffer; and then using save-excursion
, it
brings you back to your original buffer.
In looking at append-to-buffer
, you have explored a fairly
complex function. It shows how to use let
and
save-excursion
, and how to change to and come back from another
buffer. Many function definitions use let
,
save-excursion
, and set-buffer
this way.
Go to the first, previous, next, last section, table of contents.