Node:append save-excursion, Previous:append-to-buffer body, Up:append-to-buffer
save-excursion in append-to-bufferThe 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.