home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 2001 May
/
SGI Freeware 2001 May - Disc 3.iso
/
dist
/
fw_elisp-intro.idb
/
usr
/
freeware
/
info
/
emacs-lisp-intro.info-4.z
/
emacs-lisp-intro.info-4
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
Macintosh to JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
GNU Info File
|
1998-10-28
|
49.4 KB
|
1,223 lines
This is Info file emacs-lisp-intro.info, produced by Makeinfo version
1.67 from the input file emacs-lisp-intro.texi.
This is an introduction to `Programming in Emacs Lisp', for people
who are not programmers.
Edition 1.05, 21 October 1997
Copyright (C) 1990, '91, '92, '93, '94, '95, '97 Free Software
Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the sections entitled "Copying" and "GNU General Public License"
are included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Free Software Foundation.
File: emacs-lisp-intro.info, Node: Review, Next: defun Exercises, Prev: save-excursion, Up: Writing Defuns
Review
======
In the last few chapters we have introduced a fair number of
functions and special forms. Here they are described in brief, along
with a few similar functions that have not been mentioned yet.
`eval-last-sexp'
Evaluate the last symbolic expression before the current location
of point. The value is printed in the echo area unless the
function is invoked with an argument; in that case, the output is
printed in the current buffer. This command is normally bound to
`C-x C-e'.
`defun'
Define function. This special form has up to five parts: the name,
a template for the arguments that will be passed to the function,
documentation, an optional interactive declaration, and the body
of the definition.
For example:
(defun back-to-indentation ()
"Point to first visible character on line."
(interactive)
(beginning-of-line 1)
(skip-chars-forward " \t"))
`interactive'
Declare to the interpreter that the function can be used
interactively. This special form may be followed by a string with
one or more parts that pass the information to the arguments of the
function, in sequence. These parts may also tell the interpreter
to prompt for information. Parts of the string are separated by
newlines, `\n'.
Common code characters are:
`b'
The name of an existing buffer.
`f'
The name of an existing file.
`p'
The numeric prefix argument. (Note that this `p' is lower
case.)
`r'
Point and the mark, as two numeric arguments, smallest first.
This is the only code letter that specifies two successive
arguments rather than one.
*Note Code Characters for `interactive': (elisp)Interactive Codes,
for a complete list of code characters.
`let'
Declare that a list of variables is for use within the body of the
`let' and give them an initial value, either `nil' or a specified
value; then evaluate the rest of the expressions in the body of
the `let' and return the value of the last one. Inside the body
of the `let', the Lisp interpreter does not see the values of the
variables of the same names that are bound outside of the `let'.
For example,
(let ((foo (buffer-name))
(bar (buffer-size)))
(message
"This buffer is %s and has %d characters."
foo bar))
`save-excursion'
Record the values of point and mark and the current buffer before
evaluating the body of this special form. Restore the values of
point and mark and buffer afterward.
For example,
(message "We are %d characters into this buffer."
(- (point)
(save-excursion
(goto-char (point-min)) (point))))
`if'
Evaluate the first argument to the function; if it is true,
evaluate the second argument; else evaluate the third argument, if
there is one.
The `if' special form is called a "conditional". There are other
conditionals in Emacs Lisp, but `if' is perhaps the most commonly
used.
For example,
(if (string= (int-to-string 19)
(substring (emacs-version) 10 12))
(message "This is version 19 Emacs")
(message "This is not version 19 Emacs"))
`equal'
`eq'
Test whether two objects are the same. `equal' returns true if the
two objects have a similar structure and contents. Another
function, `eq', returns true if both arguments are actually the
same object.
`<'
`>'
`<='
`>='
The `<' function tests whether the first argument is smaller than
the second argument. A corresponding function, `>', tests whether
the first argument is greater than the second. Likewise, `<='
tests whether the first argument is less than or equal to the
second and `>=' tests whether the first argument is greater than
or equal to the second. In all cases, both arguments must be
numbers.
`message'
Print a message in the echo area. The message can be only one line
long. The first argument is a string that can contain `%s', `%d',
or `%c' to print the value of arguments that follow the string.
The argument used by `%s' must be a string or a symbol; the
argument used by `%d' must be a number. The argument used by `%c'
must be a number; it will be printed as the character with that
ASCII code.
`setq'
`set'
The `setq' function sets the value of its first argument to the
value of the second argument. The first argument is automatically
quoted by `setq'. It does the same for succeeding pairs of
arguments. Another function, `set', takes only two arguments and
evaluates both of them before setting the value returned by its
first argument to the value returned by its second argument.
`buffer-name'
Without an argument, return the name of the buffer, as a string.
`buffer-file-name'
Without an argument, return the name of the file the buffer is
visiting.
`current-buffer'
Return the buffer in which Emacs is active; it may not be the
buffer that is visible on the screen.
`other-buffer'
Return the most recently selected buffer (other than the buffer
passed to `other-buffer' as an argument and other than the current
buffer).
`switch-to-buffer'
Select a buffer for Emacs to be active in and display it in the
current window so users can look at it. Usually bound to `C-x b'.
`set-buffer'
Switch Emacs's attention to a buffer on which programs will run.
Don't alter what the window is showing.
`buffer-size'
Return the number of characters in the current buffer.
`point'
Return the value of the current position of the cursor, as an
integer counting the number of characters from the beginning of the
buffer.
`point-min'
Return the minimum permissible value of point in the current
buffer. This is 1, unless narrowing is in effect.
`point-max'
Return the value of the maximum permissible value of point in the
current buffer. This is the end of the buffer, unless narrowing
is in effect.
File: emacs-lisp-intro.info, Node: defun Exercises, Prev: Review, Up: Writing Defuns
Exercises
=========
* Write a non-interactive function that doubles the value of its
argument, a number. Make that function interactive.
* Write a function that tests whether the current value of
`fill-column' is greater than the argument passed to the function,
and if so, prints an appropriate message.
File: emacs-lisp-intro.info, Node: Buffer Walk Through, Next: More Complex, Prev: Writing Defuns, Up: Top
A Few Buffer-Related Functions
******************************
In this chapter we study in detail several of the functions used in
GNU Emacs. This is called a "walk-through". These functions are used
as examples of Lisp code, but are not imaginary examples; with the
exception of the first, simplified function definition, these functions
show the actual code used in GNU Emacs. You can learn a great deal from
these definitions. The functions described here are all related to
buffers. Later, we will study other functions.
* Menu:
* Finding More:: How to find more information.
* simplified-beginning-of-buffer:: Shows `goto-char',
`point-min', and `push-mark'.
* mark-whole-buffer:: Almost the same as `beginning-of-buffer'.
* append-to-buffer:: Uses `save-excursion' and
`insert-buffer-substring'.
* Buffer Related Review:: Review.
* Buffer Exercises::
File: emacs-lisp-intro.info, Node: Finding More, Next: simplified-beginning-of-buffer, Prev: Buffer Walk Through, Up: Buffer Walk Through
Finding More Information
========================
In this walk-through, I will describe each new function as we come to
it, sometimes in detail and sometimes briefly. If you are interested,
you can get the full documentation of any Emacs Lisp function at any
time by typing `C-h f' and then the name of the function (and then
<RET>). Similarly, you can get the full documentation for a variable
by typing `C-h v' and then the name of the variable (and then <RET>).
Also, if you want to see a function in its original source file, you
can use the `find-tags' function to jump to it. Type `M-.' (i.e., type
the <META> and the period key at the same time, or else type the <ESC>
key and then type the period key), and then, at the prompt, type in the
name of the function whose source code you want to see, such as
`mark-whole-buffer', and then type <RET>. Emacs will switch buffers
and display the source code for the function on your screen. To switch
back to this buffer, type `C-x b <RET>'.
Depending on how the initial default values of your copy of Emacs are
set, you may also need to specify a `tags table', which is a file
called `TAGS'. The one you will most likely want to specify is in the
`emacs/src' directory; thus you would use the `M-x visit-tags-table'
command and specify a pathname such as
`/usr/local/lib/emacs/19.23/src/TAGS'. *Note Tag Tables: (emacs)Tags.
Also, see *Note Create Your Own `TAGS' File: etags, for how to create
your own.
After you become more familiar with Emacs Lisp, you will find that
you will frequently use `find-tags' to navigate your way around source
code; and you will create your own `TAGS' tables.
Incidentally, the files that contain Lisp code are conventionally
called "libraries". The metaphor is derived from that of a specialized
library, such as a law library or an engineering library, rather than a
general library. Each library, or file, contains functions that relate
to a particular topic or activity, such as `abbrev.el' for handling
abbreviations and other typing shortcuts, and `help.el' for on-line
help. (Sometimes several libraries provide code for a single activity,
as the various `rmail...' files provide code for reading electronic
mail.) In `The GNU Emacs Manual', you will see sentences such as "The
`C-h p' command lets you search the standard Emacs Lisp libraries by
topic keywords."
File: emacs-lisp-intro.info, Node: simplified-beginning-of-buffer, Next: mark-whole-buffer, Prev: Finding More, Up: Buffer Walk Through
A Simplified `beginning-of-buffer' Definition
=============================================
The `beginning-of-buffer' command is a good function to start with
since you are likely to be familiar with it and it is easy to
understand. Used as an interactive command, `beginning-of-buffer'
moves the cursor to the beginning of the buffer, leaving the mark at the
previous position. It is generally bound to `M-<'.
In this section, we will discuss a shortened version of the function
that shows how it is most frequently used. This shortened function
works as written, but it does not contain the code for a complex option.
In another section, we will describe the entire function. (*Note
Complete Definition of `beginning-of-buffer': beginning-of-buffer.)
Before looking at the code, let's consider what the function
definition has to contain: it must include an expression that makes the
function interactive so it can be called by typing `M-x
beginning-of-buffer' or by typing a keychord such as `C-<'; it must
include code to leave a mark at the original position in the buffer;
and it must include code to move the cursor to the beginning of the
buffer.
Here is the complete text of the shortened version of the function:
(defun simplified-beginning-of-buffer ()
"Move point to the beginning of the buffer;
leave mark at previous position."
(interactive)
(push-mark)
(goto-char (point-min)))
Like all function definitions, this definition has five parts
following the special form `defun':
1. The name: in this case, `simplified-beginning-of-buffer'.
2. A list of the arguments: in this case, an empty list, `()',
3. The documentation string.
4. The interactive expression.
5. The body.
In this function definition, the argument list is empty; this means that
this function does not require any arguments. (When we look at the
definition for the complete function, we will see that it may be passed
an optional argument.)
The interactive expression tells Emacs that the function is intended
to be used interactively. In this case, `interactive' does not have an
argument because `simplified-beginning-of-buffer' does not require one.
The body of the function consists of the two lines:
(push-mark)
(goto-char (point-min))
The first of these lines is the expression, `(push-mark)'. When
this expression is evaluated by the Lisp interpreter, it sets a mark at
the current position of the cursor, wherever that may be. The position
of this mark is saved in the mark ring.
The next line is `(goto-char (point-min))'. This expression jumps
the cursor to the minimum point in the buffer, that is, to the
beginning of the buffer (or to the beginning of the accessible portion
of the buffer if it is narrowed. *Note Narrowing and Widening:
Narrowing & Widening.)
The `push-mark' command sets a mark at the place where the cursor
was located before it was moved to the beginning of the buffer by the
`(goto-char (point-min))' expression. Consequently, you can, if you
wish, go back to where you were originally by typing `C-x C-x'.
That is all there is to the function definition!
When you are reading code such as this and come upon an unfamiliar
function, such as `goto-char', you can find out what it does by using
the `describe-function' command. To use this command, type `C-h f' and
then type in the name of the function and press <RET>. The
`describe-function' command will print the function's documentation
string in a `*Help*' window. For example, the documentation for
`goto-char' is:
One arg, a number. Set point to that number.
Beginning of buffer is position (point-min),
end is (point-max).
(The prompt for `describe-function' will offer you the symbol preceding
the cursor, so you can save typing by positioning the cursor right
after the function and then typing `C-h f <RET>'.)
The `end-of-buffer' function definition is written in the same way as
the `beginning-of-buffer' definition except that the body of the
function contains the expression `(goto-char (point-max))' in place of
`(goto-char (point-min))'.
File: emacs-lisp-intro.info, Node: mark-whole-buffer, Next: append-to-buffer, Prev: simplified-beginning-of-buffer, Up: Buffer Walk Through
The Definition of `mark-whole-buffer'
=====================================
The `mark-whole-buffer' function is no harder to understand than the
`simplified-beginning-of-buffer' function. In this case, however, we
will look at the complete function, not a shortened version.
The `mark-whole-buffer' function is not as commonly used as the
`beginning-of-buffer' function, but is useful nonetheless: it marks a
whole buffer as a region by putting point at the beginning and a mark
at the end of the buffer. It is generally bound to `C-x h'.
The code for the complete function looks like this:
(defun mark-whole-buffer ()
"Put point at beginning and mark at end of buffer."
(interactive)
(push-mark (point))
(push-mark (point-max))
(goto-char (point-min)))
Like all other functions, the `mark-whole-buffer' function fits into
the template for a function definition. The template looks like this:
(defun NAME-OF-FUNCTION (ARGUMENT-LIST)
"DOCUMENTATION..."
(INTERACTIVE-EXPRESSION...)
BODY...)
Here is how the function works: the name of the function is
`mark-whole-buffer'; it is followed by an empty argument list, `()',
which means that the function does not require arguments. The
documentation comes next.
The next line is an `(interactive)' expression that tells Emacs that
the function will be used interactively. These details are similar to
the `simplified-beginning-of-buffer' function described in the previous
section.
* Menu:
* Body of mark-whole-buffer:: Only three lines of code.
File: emacs-lisp-intro.info, Node: Body of mark-whole-buffer, Prev: mark-whole-buffer, Up: mark-whole-buffer
Body of `mark-whole-buffer'
---------------------------
The body of the `mark-whole-buffer' function consists of three lines
of code:
(push-mark (point))
(push-mark (point-max))
(goto-char (point-min))
The first of these lines is the expression, `(push-mark (point))'.
This line does exactly the same job as the first line of the body of
the `simplified-beginning-of-buffer' function, which is written
`(push-mark)'. In both cases, the Lisp interpreter sets a mark at the
current position of the cursor.
I don't know why the expression in `mark-whole-buffer' is written
`(push-mark (point))' and the expression in `beginning-of-buffer' is
written `(push-mark)'. Perhaps whoever wrote the code did not know
that the argument for `push-mark' is optional and that if `push-mark'
is not passed an argument, the function automatically sets mark at the
location of point by default. Or perhaps the expression was written so
as to parallel the structure of the next line. In any case, the line
causes Emacs to determine the position of point and set a mark there.
The next line of `mark-whole-buffer' is `(push-mark (point-max))'.
This expression sets a mark at the point in the buffer that has the
highest number. This will be the end of the buffer (or, if the buffer
is narrowed, the end of the accessible portion of the buffer. *Note
Narrowing and Widening: Narrowing & Widening, for more about
narrowing.) After this mark has been set, the previous mark, the one
set at point, is no longer set, but Emacs remembers its position, just
as all other recent marks are always remembered. This means that you
can, if you wish, go back to that position by typing `C-u C-<SPC>'
twice.
Finally, the last line of the function is `(goto-char
(point-min)))'. This is written exactly the same way as it is written
in `beginning-of-buffer'. The expression moves the cursor to the
minimum point in the buffer, that is, to the beginning of the buffer
(or to the beginning of the accessible portion of the buffer). As a
result of this, point is placed at the beginning of the buffer and mark
is set at the end of the buffer. The whole buffer is, therefore, the
region.
File: emacs-lisp-intro.info, Node: append-to-buffer, Next: Buffer Related Review, Prev: mark-whole-buffer, Up: Buffer Walk Through
The Definition of `append-to-buffer'
====================================
The `append-to-buffer' command is very nearly as simple as the
`mark-whole-buffer' command. What it does is copy the region (that is,
the part of the buffer between point and mark) from the current buffer
to a specified buffer.
The `append-to-buffer' command uses the `insert-buffer-substring'
function to copy the region. `insert-buffer-substring' is described by
its name: it takes a string of characters from part of a buffer, a
"substring", and inserts them into another buffer. Most of
`append-to-buffer' is concerned with setting up the conditions for
`insert-buffer-substring' to work: the code must specify both the
buffer to which the text will go and the region that will be copied.
Here is the complete text of the function:
(defun append-to-buffer (buffer start end)
"Append to specified buffer the text of the region.
It is inserted into that buffer before its point.
When calling from a program, give three arguments:
a buffer or the name of one, and two character numbers
specifying the portion of the current buffer to be copied."
(interactive "BAppend to buffer: \nr")
(let ((oldbuf (current-buffer)))
(save-excursion
(set-buffer (get-buffer-create buffer))
(insert-buffer-substring oldbuf start end))))
The function can be understood by looking at it as a series of
filled-in templates.
The outermost template is for the function definition. In this case,
it looks like this (with several slots filled in):
(defun append-to-buffer (buffer start end)
"DOCUMENTATION..."
(interactive "BAppend to buffer: \nr")
BODY...)
The first line of the function includes its name and three arguments.
The arguments are the `buffer' to which the text will be copied, and
the `start' and `end' of the region in the current buffer that will be
copied.
The next part of the function is the documentation, which is clear
and complete.
* Menu:
* append interactive:: A two part interactive expression.
* append-to-buffer body:: Incorporates a `let' expression.
* append save-excursion:: How the `save-excursion' works.
File: emacs-lisp-intro.info, Node: append interactive, Next: append-to-buffer body, Prev: append-to-buffer, Up: append-to-buffer
The `append-to-buffer' Interactive Expression
---------------------------------------------
Since the `append-to-buffer' function will be used interactively,
the function must have an `interactive' expression. (For a review of
`interactive', see *Note Making a Function Interactive: Interactive.)
The expression reads as follows:
(interactive "BAppend to buffer: \nr")
This expression has an argument inside of quotation marks and that
argument has two parts, separated by `\n'.
The first part is `BAppend to buffer: '. Here, the `B' tells Emacs
to ask for the name of the buffer that will be passed to the function.
Emacs will ask for the name by prompting the user in the minibuffer,
using the string following the `B', which is the string `Append to
buffer: '. Emacs then binds the variable `buffer' in the function's
argument list to the specified buffer.
The newline, `\n', separates the first part of the argument from the
second part. It is followed by an `r' that tells Emacs to bind the two
arguments that follow the symbol `buffer' in the function's argument
list (that is, `start' and `end') to the values of point and mark.
File: emacs-lisp-intro.info, Node: append-to-buffer body, Next: append save-excursion, Prev: append interactive, Up: append-to-buffer
The Body of `append-to-buffer'
------------------------------
The body of the `append-to-buffer' function begins with `let'.
As we have seen before (*note `let': let.), the purpose of a `let'
expression is to create and give initial values to one or more
variables that will only be used within the body of the `let'. This
means that such a variable will not be confused with any variable of
the same name outside the `let' expression.
We can see how the `let' expression fits into the function as a
whole by showing a template for `append-to-buffer' with the `let'
expression in outline:
(defun append-to-buffer (buffer start end)
"DOCUMENTATION..."
(interactive "BAppend to buffer: \nr")
(let ((VARIABLE VALUE))
BODY...)
The `let' expression has three elements:
1. The symbol `let';
2. A varlist containing, in this case, a single two-element list,
`(VARIABLE VALUE)';
3. The body of the `let' expression.
In the `append-to-buffer' function, the varlist looks like this:
(oldbuf (current-buffer))
In this part of the `let' expression, the one variable, `oldbuf', is
bound to the value returned by the `(current-buffer)' expression. The
variable, `oldbuf', is used to keep track of the buffer in which you
are working.
The element or elements of a varlist are surrounded by a set of
parentheses so the Lisp interpreter can distinguish the varlist from
the body of the `let'. As a consequence, the two-element list within
the varlist is surrounded by a circumscribing set of parentheses. The
line looks like this:
(let ((oldbuf (current-buffer)))
... )
The two parentheses before `oldbuf' might surprise you if you did not
realize that the first parenthesis before `oldbuf' marks the boundary
of the varlist and the second parenthesis marks the beginning of the
two-element list, `(oldbuf (current-buffer))'.
File: emacs-lisp-intro.info, Node: append save-excursion, Prev: append-to-buffer body, Up: append-to-buffer
`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.
File: emacs-lisp-intro.info, Node: Buffer Related Review, Next: Buffer Exercises, Prev: append-to-buffer, Up: Buffer Walk Through
Review
======
Here is a brief summary of the various functions discussed in this
chapter.
`describe-function'
`describe-variable'
Print the documentation for a function or variable.
Conventionally bound to `C-h f' and `C-h v'.
`find-tag'
Find the file containing the source for a function or variable and
switch buffers to it, positioning point at the beginning of the
item. Conventionally bound to `M-.' (that's a period following the
<META> key).
`save-excursion'
Save the location of point and mark and restore their values after
the arguments to `save-excursion' have been evaluated. Also,
remember the current buffer and return to it.
`push-mark'
Set mark at a location and record the value of the previous mark
on the mark ring. The mark is a location in the buffer that will
keep its relative position even if text is added to or removed
from the buffer.
`goto-char'
Set point to the location specified by the value of the argument,
which can be a number, a marker, or an expression that returns
the number of a position, such as `(point-min)'.
`insert-buffer-substring'
Copy a region of text from a buffer that is passed to the function
as an argument and insert the region into the current buffer.
`mark-whole-buffer'
Mark the whole buffer as a region. Normally bound to `C-x h'.
`set-buffer'
Switch the attention of Emacs to another buffer, but do not change
the window being displayed. Used when the program rather than a
human is to work on a different buffer.
`get-buffer-create'
`get-buffer'
Find a named buffer or create one if a buffer of that name does not
exist. The `get-buffer' function returns `nil' if the named
buffer does not exist.
File: emacs-lisp-intro.info, Node: Buffer Exercises, Prev: Buffer Related Review, Up: Buffer Walk Through
Exercises
=========
* Write your own `simplified-end-of-buffer' function definition;
then test it to see whether it works.
* Use `if' and `get-buffer' to write a function that prints a
message telling you whether a buffer exists.
* Using `find-tag', find the source for the `copy-to-buffer'
function.
File: emacs-lisp-intro.info, Node: More Complex, Next: Narrowing & Widening, Prev: Buffer Walk Through, Up: Top
A Few More Complex Functions
****************************
In this chapter, we build on what we have learned in previous
chapters by looking at more complex functions. The `copy-to-buffer'
function illustrates use of two `save-excursion' expressions in one
definition, while the `insert-buffer' function illustrates use of <*>
in an `interactive' expression, use of `or', and the important
distinction between a name and the object to which the name refers.
* Menu:
* copy-to-buffer:: With `set-buffer', `get-buffer-create'.
* insert-buffer:: Read-only, and with `or'.
* beginning-of-buffer:: Shows `goto-char',
`point-min', and `push-mark'.
* Second Buffer Related Review::
* &optional Exercise ::
File: emacs-lisp-intro.info, Node: copy-to-buffer, Next: insert-buffer, Prev: More Complex, Up: More Complex
The Definition of `copy-to-buffer'
==================================
After understanding how `append-to-buffer' works, it is easy to
understand `copy-to-buffer'. This function copies text into a buffer,
but instead of adding to the second buffer, it replaces the previous
text in the second buffer. The code for the `copy-to-buffer' function
is almost the same as the code for `append-to-buffer', except that
`erase-buffer' and a second `save-excursion' are used. (*Note The
Definition of `append-to-buffer': append-to-buffer, for the description
of `append-to-buffer'.)
The body of `copy-to-buffer' looks like this
...
(interactive "BCopy to buffer: \nr")
(let ((oldbuf (current-buffer)))
(save-excursion
(set-buffer (get-buffer-create buffer))
(erase-buffer)
(save-excursion
(insert-buffer-substring oldbuf start end)))))
This code is similar to the code in `append-to-buffer': it is only
after changing to the buffer to which the text will be copied that the
definition for this function diverges from the definition for
`append-to-buffer': the `copy-to-buffer' function erases the buffer's
former contents. (This is what is meant by `replacement'; to replace
text, Emacs erases the previous text and then inserts new text.) After
erasing the previous contents of the buffer, `save-excursion' is used
for a second time and the new text is inserted.
Why is `save-excursion' used twice? Consider again what the
function does.
In outline, the body of `copy-to-buffer' looks like this:
(let (BIND-`oldbuf'-TO-VALUE-OF-`current-buffer')
(save-excursion ; First use of `save-excursion'.
CHANGE-BUFFER
(erase-buffer)
(save-excursion ; Second use of `save-excursion'.
INSERT-SUBSTRING-FROM-`oldbuf'-INTO-BUFFER)))
The first use of `save-excursion' returns Emacs to the buffer from
which the text is being copied. That is clear, and is just like its use
in `append-to-buffer'. Why the second use? The reason is that
`insert-buffer-substring' always leaves point at the *end* of the
region being inserted. The second `save-excursion' causes Emacs to
leave point at the beginning of the text being inserted. In most
circumstances, users prefer to find point at the beginning of inserted
text. (Of course, the `copy-to-buffer' function returns the user to
the original buffer when done--but if the user *then* switches to the
copied-to buffer, point will go to the beginning of the text. Thus,
this use of a second `save-excursion' is a little nicety.)
File: emacs-lisp-intro.info, Node: insert-buffer, Next: beginning-of-buffer, Prev: copy-to-buffer, Up: More Complex
The Definition of `insert-buffer'
=================================
`insert-buffer' is yet another buffer-related function. This
command copies another buffer *into* the current buffer. It is the
reverse of `append-to-buffer' or `copy-to-buffer', since they copy a
region of text *from* the current buffer to another buffer.
In addition, this code illustrates the use of `interactive' with a
buffer that might be "read-only" and the important distinction between
the name of an object and the object actually referred to. Here is the
code:
(defun insert-buffer (buffer)
"Insert after point the contents of BUFFER.
Puts mark after the inserted text.
BUFFER may be a buffer or a buffer name."
(interactive "*bInsert buffer: ")
(or (bufferp buffer)
(setq buffer (get-buffer buffer)))
(let (start end newmark)
(save-excursion
(save-excursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
(insert-buffer-substring buffer start end)
(setq newmark (point)))
(push-mark newmark)))
As with other function definitions, you can use a template to see an
outline of the function:
(defun insert-buffer (buffer)
"DOCUMENTATION..."
(interactive "*bInsert buffer: ")
BODY...)
* Menu:
* insert interactive expression:: A read-only situation.
* insert-buffer body:: The body has an `or' and a ` let'.
* if & or:: Using an `if' instead of an `or'.
* insert or:: How the `or' expression works.
* insert let:: Two `save-excursion' expressions.
File: emacs-lisp-intro.info, Node: insert interactive expression, Next: insert-buffer body, Prev: insert-buffer, Up: insert-buffer
The Interactive Expression in `insert-buffer'
---------------------------------------------
In `insert-buffer', the argument to the `interactive' declaration
has two parts, an asterisk, `*', and `bInsert buffer: '.
* Menu:
* read-only buffer::
* b for interactive::
File: emacs-lisp-intro.info, Node: read-only buffer, Next: b for interactive, Prev: insert interactive expression, Up: insert interactive expression
A Read-only Buffer
..................
The asterisk is for the situation when the buffer is a read-only
buffer--a buffer that cannot be modified. If `insert-buffer' is called
on a buffer that is read-only, a message to this effect is printed in
the echo area and the terminal may beep or blink at you; you will not
be permitted to insert anything into current buffer. The asterisk does
not need to be followed by a newline to separate it from the next
argument.
File: emacs-lisp-intro.info, Node: b for interactive, Prev: read-only buffer, Up: insert interactive expression
`b' in an Interactive Expression
................................
The next argument in the interactive expression starts with a lower
case `b'. (This is different from the code for `append-to-buffer',
which uses an upper-case `B'. *Note The Definition of
`append-to-buffer': append-to-buffer.) The lower-case `b' tells the
Lisp interpreter that the argument for `insert-buffer' should be an
existing buffer or else its name. (The upper-case `B' option provides
for the possibility that the buffer does not exist.) Emacs will prompt
you for the name of the buffer, offering you a default buffer, with
name completion enabled. If the buffer does not exist, you receive a
message that says "No match"; your terminal may beep at you as well.
File: emacs-lisp-intro.info, Node: insert-buffer body, Next: if & or, Prev: insert interactive expression, Up: insert-buffer
The Body of the `insert-buffer' Function
----------------------------------------
The body of the `insert-buffer' function has two major parts: an
`or' expression and a `let' expression. The purpose of the `or'
expression is to ensure that the argument `buffer' is bound to a buffer
and not just the name of a buffer. The body of the `let' expression
contains the code which copies the other buffer into the current buffer.
In outline, the two expressions fit into the `insert-buffer'
function like this:
(defun insert-buffer (buffer)
"DOCUMENTATION..."
(interactive "*bInsert buffer: ")
(or ...
...
(let (VARLIST)
BODY-OF-`let'... )
To understand how the `or' expression ensures that the argument
`buffer' is bound to a buffer and not to the name of a buffer, it is
first necessary to understand the `or' function.
Before doing this, let me rewrite this part of the function using
`if' so that you can see what is done in a manner that will be familiar.
File: emacs-lisp-intro.info, Node: if & or, Next: insert or, Prev: insert-buffer body, Up: insert-buffer
`insert-buffer' With an `if' Instead of an `or'
-----------------------------------------------
The job to be done is to make sure the value of `buffer' is a buffer
itself and not the name of a buffer. If the value is the name, then
the buffer itself must be got.
You can imagine yourself at a conference where an usher is wandering
around holding a list with your name on it and looking for you: the
usher is "bound" to your name, not to you; but when the usher finds you
and takes your arm, the usher becomes "bound" to you.
In Lisp, you might describe this situation like this:
(if (not (holding-on-to-guest))
(find-and-take-arm-of-guest))
We want to do the same thing with a buffer--if we do not have the
buffer itself, we want to get it.
Using a predicate called `bufferp' that tells us whether we have a
buffer (rather than its name), we can write the code like this:
(if (not (bufferp buffer)) ; if-part
(setq buffer (get-buffer buffer))) ; then-part
Here, the true-or-false-test of the `if' expression is
`(not (bufferp buffer))'; and the then-part is the expression
`(setq buffer (get-buffer buffer))'.
In the test, the function `bufferp' returns true if its argument is
a buffer--but false if its argument is the name of the buffer. (The
last character of the function name `bufferp' is the character `p'; as
we saw earlier, such use of `p' is a convention that indicates that the
function is a predicate, which is a term that means that the function
will determine whether some property is true or false. *Note Using the
Wrong Type Object as an Argument: Wrong Type of Argument.)
The function `not' precedes the expression `(bufferp buffer)', so
the true-or-false-test looks like this:
(not (bufferp buffer))
`not' is a function the returns true if its argument is false and false
if its argument is true. So if `(bufferp buffer)' returns true, the
`not' expression returns false and vice-versa: what is "not true" is
false and what is "not false" is true.
Using this test, the `if' expression works as follows: when the
value of the variable `buffer' is actually a buffer rather then its
name, the true-or-false-test returns false and the `if' expression does
not evaluate the then-part. This is fine, since we do not need to do
anything to the variable `buffer' if it really is a buffer.
On the other hand, when the value of `buffer' is not a buffer
itself, but the name of a buffer, the true-or-false-test returns true
and the then-part of the expression is evaluated. In this case, the
then-part is `(setq buffer (get-buffer buffer))'. This expression uses
the `get-buffer' function to return an actual buffer itself, given its
name. The `setq' then sets the variable `buffer' to the value of the
buffer itself, replacing its previous value (which was the name of the
buffer).
File: emacs-lisp-intro.info, Node: insert or, Next: insert let, Prev: if & or, Up: insert-buffer
The `or' in the Body
--------------------
The purpose of the `or' expression in the `insert-buffer' function
is to ensure that the argument `buffer' is bound to a buffer and not
just the name of a buffer. The previous section shows how the job
could have been done using an `if' expression. However, the
`insert-buffer' function actually uses `or'. To understand this, it is
necessary to understand how `or' works.
An `or' function can have any number of arguments. It evaluates
each argument in turn and returns the value of the first of its
arguments that is not `nil'. Also, and this is a crucial feature of
`or', it does not evaluate any subsequent arguments after returning the
first non-`nil' value.
The `or' expression looks like this:
(or (bufferp buffer)
(setq buffer (get-buffer buffer)))
The first argument to `or' is the expression `(bufferp buffer)'. This
expression returns true (a non-`nil' value) if the buffer is actually a
buffer, and not just the name of a buffer. In the `or' expression, if
this is the case, the `or' expression returns this true value and does
not evaluate the next expression--and this is fine with us, since we do
not want to do anything to the value of `buffer' if it really is a
buffer.
On the other hand, if the value of `(bufferp buffer)' is `nil',
which it will be if the value of `buffer' is the name of a buffer, the
Lisp interpreter evaluates the next element of the `or' expression.
This is the expression `(setq buffer (get-buffer buffer))'. This
expression returns a non-`nil' value, which is the value to which it
sets the variable `buffer'--and this value is a buffer itself, not the
name of a buffer.
The result of all this is that the symbol `buffer' is always bound
to a buffer itself rather than the name of a buffer. All this is
necessary because the `set-buffer' function in a following line only
works with a buffer itself, not with the name to a buffer.
Incidentally, using `or', the situation with the usher would be
written like this:
(or (holding-on-to-guest) (find-and-take-arm-of-guest))
File: emacs-lisp-intro.info, Node: insert let, Prev: insert or, Up: insert-buffer
The `let' Expression in `insert-buffer'
---------------------------------------
After ensuring that the variable `buffer' refers to a buffer itself
and not just to the name of a buffer, the `insert-buffer function'
continues with a `let' expression. This specifies three local
variables, `start', `end', and `newmark' and binds them to the initial
value `nil'. These variables are used inside the remainder of the
`let' and temporarily hide any other occurrence of variables of the
same name in Emacs until the end of the `let'.
The body of the `let' contains two `save-excursion' expressions.
First, we will look at the inner `save-excursion' expression in detail.
The expression looks like this:
(save-excursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
The expression `(set-buffer buffer)' changes Emacs's attention from the
current buffer to the one from which the text will copied. In that
buffer, the variables `start' and `end' are set to the beginning and
end of the buffer, using the commands `point-min' and `point-max'.
Note that we have here an illustration of how `setq' is able to set two
variables in the same expression. `setq''s first argument is set to
the value of its second and its third argument is set to the value of
its fourth.
After the body of the inner `save-excursion' is evaluated, the
`save-excursion' restores the original buffer, but `start' and `end'
remain set to the values of the beginning and end of the buffer from
which the text will be copied.
The outer `save-excursion' expression looks like this:
(save-excursion
(INNER-`save-excursion'-EXPRESSION
(GO-TO-NEW-BUFFER-AND-SET-`start'-AND-`end')
(insert-buffer-substring buffer start end)
(setq newmark (point)))
The `insert-buffer-substring' function copies the text *into* the
current buffer *from* the region indicated by `start' and `end' in
`buffer'. Since the whole of the second buffer lies between `start'
and `end', the whole of the second buffer is copied into the buffer you
are editing. Next, the value of point, which will be at the end of the
inserted text, is recorded in the variable `newmark'.
After the body of the outer `save-excursion' is evaluated, point and
mark are relocated to their original places.
However, it is convenient to locate a mark at the end of the newly
inserted text and locate point at its beginning. The `newmark'
variable records the end of the inserted text. In the last line of the
`let' expression, the `(push-mark newmark)' expression function sets a
mark to this location. (The previous location of the mark is still
accessible; it is recorded on the mark ring and you can go back to it
with `C-u C-<SPC>'.) Meanwhile, point is located at the beginning of
the inserted text, which is where it was before you called the insert
function.
The whole `let' expression looks like this:
(let (start end newmark)
(save-excursion
(save-excursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
(insert-buffer-substring buffer start end)
(setq newmark (point)))
(push-mark newmark))
Like the `append-to-buffer' function, the `insert-buffer' function
uses `let', `save-excursion', and `set-buffer'. In addition, the
function illustrates one way to use `or'. All these functions are
building blocks that we will find and use again and again.