Info Node: (emacs-lisp-intro.info)append save-excursion
(emacs-lisp-intro.info)append save-excursion
`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.