GNU Info

Info Node: (emacs-lisp-intro.info)append save-excursion

(emacs-lisp-intro.info)append save-excursion


Prev: append-to-buffer body Up: append-to-buffer
Enter node , (file) or (file)node

`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.


automatically generated by info2www version 1.2.2.9