[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Whenever you cut or clip text out of a buffer with a `kill' command in GNU Emacs, it is stored in a list and you can bring it back with a `yank' command.
(The use of the word `kill' in Emacs for processes which specifically do not destroy the values of the entities is an unfortunate historical accident. A much more appropriate word would be `clip' since that is what the kill commands do; they clip text out of a buffer and put it into storage from which it can be brought back. I have often been tempted to replace globally all occurrences of `kill' in the Emacs sources with `clip' and all occurrences of `killed' with `clipped'.)
Storing Text in a List | Text is stored in a list. | |
8.1 zap-to-char | Cutting out text up to a character. | |
8.2 kill-region | Cutting text out of a region. | |
8.3 delete-and-extract-region : Digressing into C | Minor note on C programming language macros. | |
8.4 Initializing a Variable with defvar | How to give a variable an initial value. | |
8.5 copy-region-as-kill | A definition for copying text. | |
8.6 Review | ||
8.7 Searching Exercises |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When text is cut out of a buffer, it is stored on a list. Successive pieces of text are stored on the list successively, so the list might look like this:
("a piece of text" "previous piece") |
The function cons
can be used to add a piece of text to the list,
like this:
(cons "another piece" '("a piece of text" "previous piece")) |
If you evaluate this expression, a list of three elements will appear in the echo area:
("another piece" "a piece of text" "previous piece") |
With the car
and nthcdr
functions, you can retrieve
whichever piece of text you want. For example, in the following code,
nthcdr 1 ...
returns the list with the first item removed;
and the car
returns the first element of that remainder--the
second element of the original list:
(car (nthcdr 1 '("another piece" "a piece of text" "previous piece"))) => "a piece of text" |
The actual functions in Emacs are more complex than this, of course. The code for cutting and retrieving text has to be written so that Emacs can figure out which element in the list you want--the first, second, third, or whatever. In addition, when you get to the end of the list, Emacs should give you the first element of the list, rather than nothing at all.
The list that holds the pieces of text is called the kill ring.
This chapter leads up to a description of the kill ring and how it is
used by first tracing how the zap-to-char
function works. This
function uses (or `calls') a function that invokes a function that
manipulates the kill ring. Thus, before reaching the mountains, we
climb the foothills.
A subsequent chapter describes how text that is cut from the buffer is retrieved. See section Yanking Text Back.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
zap-to-char
The zap-to-char
function barely changed between GNU Emacs
version 19 and GNU Emacs version 21. However, zap-to-char
calls another function, kill-region
, which enjoyed a major rewrite
on the way to version 21.
The kill-region
function in Emacs 19 is complex, but does not
use code that is important at this time. We will skip it.
The kill-region
function in Emacs 21 is easier to read than the
same function in Emacs 19 and introduces a very important concept,
that of error handling. We will walk through the function.
But first, let us look at the interactive zap-to-char
function.
The Complete zap-to-char Implementation | The complete implementation. | |
8.1.1 The interactive Expression | A three part interactive expression. | |
8.1.2 The Body of zap-to-char | A short overview. | |
8.1.3 The search-forward Function | How to search for a string. | |
8.1.4 The progn Special Form | The progn special form. | |
8.1.5 Summing up zap-to-char | Using point and search-forward . |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
zap-to-char
Implementation
The GNU Emacs version 19 and version 21 implementations of the
zap-to-char
function are nearly identical in form, and they
work alike. The function removes the text in the region between the
location of the cursor (i.e., of point) up to and including the next
occurrence of a specified character. The text that zap-to-char
removes is put in the kill ring; and it can be retrieved from the kill
ring by typing C-y (yank
). If the command is given an
argument, it removes text through that number of occurrences. Thus,
if the cursor were at the beginning of this sentence and the character
were `s', `Thus' would be removed. If the argument were
two, `Thus, if the curs' would be removed, up to and including
the `s' in `cursor'.
If the specified character is not found, zap-to-char
will say
"Search failed", tell you the character you typed, and not remove
any text.
In order to determine how much text to remove, zap-to-char
uses
a search function. Searches are used extensively in code that
manipulates text, and we will focus attention on them as well as on the
deletion command.
Here is the complete text of the version 19 implementation of the function:
(defun zap-to-char (arg char) ; version 19 implementation "Kill up to and including ARG'th occurrence of CHAR. Goes backward if ARG is negative; error if CHAR not found." (interactive "*p\ncZap to char: ") (kill-region (point) (progn (search-forward (char-to-string char) nil nil arg) (point)))) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
interactive
Expression
The interactive expression in the zap-to-char
command looks like
this:
(interactive "*p\ncZap to char: ") |
The part within quotation marks, "*p\ncZap to char: "
, specifies
three different things. First, and most simply, the asterisk, `*',
causes an error to be signalled if the buffer is read-only. This means that
if you try zap-to-char
in a read-only buffer you will not be able to
remove text, and you will receive a message that says "Buffer is
read-only"; your terminal may beep at you as well.
The version 21 implementation does not have the asterisk, `*'. The function works the same as in version 19: in both cases, it cannot remove text from a read-only buffer but the function does copy the text that would have been removed to the kill ring. Also, in both cases, you see an error message.
However, the version 19 implementation copies text from a read-only
buffer only because of a mistake in the implementation of
interactive
. According to the documentation for
interactive
, the asterisk, `*', should prevent the
zap-to-char
function from doing anything at all when the buffer
is read only. The function should not copy the text to the kill ring.
It is a bug that it does.
In version 21, interactive
is implemented correctly. So the
asterisk, `*', had to be removed from the interactive
specification. If you insert an `*' and evaluate the function
definition, then the next time you run the zap-to-char
function
on a read-only buffer, you will not copy any text.
That change aside, and a change to the documentation, the two versions
of the zap-to-char
function are identical.
Let us continue with the interactive specification.
The second part of "*p\ncZap to char: "
is the `p'.
This part is separated from the next part by a newline, `\n'.
The `p' means that the first argument to the function will be
passed the value of a `processed prefix'. The prefix argument is
passed by typing C-u and a number, or M- and a number. If
the function is called interactively without a prefix, 1 is passed to
this argument.
The third part of "*p\ncZap to char: "
is `cZap to char:
'. In this part, the lower case `c' indicates that
interactive
expects a prompt and that the argument will be a
character. The prompt follows the `c' and is the string `Zap
to char: ' (with a space after the colon to make it look good).
What all this does is prepare the arguments to zap-to-char
so they
are of the right type, and give the user a prompt.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
zap-to-char
The body of the zap-to-char
function contains the code that
kills (that is, removes) the text in the region from the current
position of the cursor up to and including the specified character.
The first part of the code looks like this:
(kill-region (point) ... |
(point)
is the current position of the cursor.
The next part of the code is an expression using progn
. The body
of the progn
consists of calls to search-forward
and
point
.
It is easier to understand how progn
works after learning about
search-forward
, so we will look at search-forward
and
then at progn
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
search-forward
Function
The search-forward
function is used to locate the
zapped-for-character in zap-to-char
. If the search is
successful, search-forward
leaves point immediately after the
last character in the target string. (In zap-to-char
, the
target string is just one character long.) If the search is
backwards, search-forward
leaves point just before the first
character in the target. Also, search-forward
returns t
for true. (Moving point is therefore a `side effect'.)
In zap-to-char
, the search-forward
function looks like this:
(search-forward (char-to-string char) nil nil arg) |
The search-forward
function takes four arguments:
As it happens, the argument passed to zap-to-char
is a single
character. Because of the way computers are built, the Lisp
interpreter may treat a single character as being different from a
string of characters. Inside the computer, a single character has a
different electronic format than a string of one character. (A single
character can often be recorded in the computer using exactly one
byte; but a string may be longer, and the computer needs to be ready
for this.) Since the search-forward
function searches for a
string, the character that the zap-to-char
function receives as
its argument must be converted inside the computer from one format to
the other; otherwise the search-forward
function will fail.
The char-to-string
function is used to make this conversion.
nil
.
nil
. A nil
as the third argument causes the function to
signal an error when the search fails.
search-forward
is the repeat count--how
many occurrences of the string to look for. This argument is optional
and if the function is called without a repeat count, this argument is
passed the value 1. If this argument is negative, the search goes
backwards.
In template form, a search-forward
expression looks like this:
(search-forward "target-string" limit-of-search what-to-do-if-search-fails repeat-count) |
We will look at progn
next.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
progn
Special Form
progn
is a special form that causes each of its arguments to be
evaluated in sequence and then returns the value of the last one. The
preceding expressions are evaluated only for the side effects they
perform. The values produced by them are discarded.
The template for a progn
expression is very simple:
(progn body...) |
In zap-to-char
, the progn
expression has to do two things:
put point in exactly the right position; and return the location of
point so that kill-region
will know how far to kill to.
The first argument to the progn
is search-forward
. When
search-forward
finds the string, the function leaves point
immediately after the last character in the target string. (In this
case the target string is just one character long.) If the search is
backwards, search-forward
leaves point just before the first
character in the target. The movement of point is a side effect.
The second and last argument to progn
is the expression
(point)
. This expression returns the value of point, which in
this case will be the location to which it has been moved by
search-forward
. This value is returned by the progn
expression and is passed to kill-region
as kill-region
's
second argument.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
zap-to-char
Now that we have seen how search-forward
and progn
work,
we can see how the zap-to-char
function works as a whole.
The first argument to kill-region
is the position of the cursor
when the zap-to-char
command is given--the value of point at
that time. Within the progn
, the search function then moves
point to just after the zapped-to-character and point
returns the
value of this location. The kill-region
function puts together
these two values of point, the first one as the beginning of the region
and the second one as the end of the region, and removes the region.
The progn
special form is necessary because the kill-region
command takes two arguments; and it would fail if search-forward
and point
expressions were written in sequence as two
additional arguments. The progn
expression is a single argument
to kill-region
and returns the one value that kill-region
needs for its second argument.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
kill-region
The zap-to-char
function uses the kill-region
function.
This function clips text from a region and copies that text to
the kill ring, from which it may be retrieved.
The Emacs 21 version of that function uses condition-case
and
copy-region-as-kill
, both of which we will explain.
condition-case
is an important special form.
In essence, the kill-region
function calls
condition-case
, which takes three arguments. In this function,
the first argument does nothing. The second argument contains the
code that does the work when all goes well. The third argument
contains the code that is called in the event of an error.
The Complete kill-region Definition | The function definition. | |
8.2.1 condition-case | Dealing with a problem. | |
8.2.2 delete-and-extract-region | Doing the work. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
kill-region
Definition
We will go through the condition-case
code in a moment. First,
let us look at the complete definition of kill-region
, with
comments added:
(defun kill-region (beg end) "Kill between point and mark. The text is deleted but saved in the kill ring." (interactive "r") ;; 1. `condition-case' takes three arguments. ;; If the first argument is nil, as it is here, ;; information about the error signal is not ;; stored for use by another function. (condition-case nil ;; 2. The second argument to `condition-case' ;; tells the Lisp interpreter what to do when all goes well. ;; The `delete-and-extract-region' function usually does the ;; work. If the beginning and ending of the region are both ;; the same, then the variable `string' will be empty, or nil (let ((string (delete-and-extract-region beg end))) ;; `when' is an `if' clause that cannot take an `else-part'. ;; Emacs normally sets the value of `last-command' to the ;; previous command. ;; `kill-append' concatenates the new string and the old. ;; `kill-new' inserts text into a new item in the kill ring. (when string (if (eq last-command 'kill-region) ;; if true, prepend string (kill-append string (< end beg)) (kill-new string))) (setq this-command 'kill-region)) ;; 3. The third argument to `condition-case' tells the interpreter ;; what to do with an error. ;; The third argument has a conditions part and a body part. ;; If the conditions are met (in this case, ;; if text or buffer is read-only) ;; then the body is executed. ((buffer-read-only text-read-only) ;; this is the if-part ;; then... (copy-region-as-kill beg end) (if kill-read-only-ok ;; usually this variable is nil (message "Read only text copied to kill ring") ;; or else, signal an error if the buffer is read-only; (barf-if-buffer-read-only) ;; and, in any case, signal that the text is read-only. (signal 'text-read-only (list (current-buffer))))))) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
condition-case
As we have seen earlier (see section Generate an Error Message), when the Emacs Lisp interpreter has trouble evaluating an expression, it provides you with help; in the jargon, this is called "signaling an error". Usually, the computer stops the program and shows you a message.
However, some programs undertake complicated actions. They should not
simply stop on an error. In the kill-region
function, the most
likely error is that you will try to kill text that is read-only and
cannot be removed. So the kill-region
function contains code
to handle this circumstance. This code, which makes up the body of
the kill-region
function, is inside of a condition-case
special form.
The template for condition-case
looks like this:
(condition-case var bodyform error-handler...) |
The second argument, bodyform, is straightforward. The
condition-case
special form causes the Lisp interpreter to
evaluate the code in bodyform. If no error occurs, the special
form returns the code's value and produces the side-effects, if any.
In short, the bodyform part of a condition-case
expression determines what should happen when everything works
correctly.
However, if an error occurs, among its other actions, the function generating the error signal will define one or more error condition names.
An error handler is the third argument to condition case
.
An error handler has two parts, a condition-name and a
body. If the condition-name part of an error handler
matches a condition name generated by an error, then the body
part of the error handler is run.
As you will expect, the condition-name part of an error handler may be either a single condition name or a list of condition names.
Also, a complete condition-case
expression may contain more
than one error handler. When an error occurs, the first applicable
handler is run.
Lastly, the first argument to the condition-case
expression,
the var argument, is sometimes bound to a variable that
contains information about the error. However, if that argument is
nil, as is the case in kill-region
, that information is
discarded.
In brief, in the kill-region
function, the code
condition-case
works like this:
If no errors, run only this code but, if errors, run this other code. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
delete-and-extract-region
A condition-case
expression has two parts, a part that is
evaluated in the expectation that all will go well, but which may
generate an error; and a part that is evaluated when there is an
error.
First, let us look at the code in kill-region
that is run in
the expectation that all goes well. This is the core of the function.
The code looks like this:
(let ((string (delete-and-extract-region beg end))) (when string (if (eq last-command 'kill-region) (kill-append string (< end beg)) (kill-new string))) (setq this-command 'kill-region)) |
It looks complicated because we have the new functions
delete-and-extract-region
, kill-append
, and
kill-new
as well as the new variables,
last-command
and this-command
.
The delete-and-extract-region
function is straightforward. It
is a built-in function that deletes the text in a region (a side
effect) and also returns that text. This is the function that
actually removes the text. (And if it cannot do that, it signals the
error.)
In this let
expression, the text that
delete-and-extract-region
returns is placed in the local
variable called `string'. This is the text that is removed from
the buffer. (To be more precise, the variable is set to point to the
address of the extracted text; to say it is `placed in' the variable
is simply a shorthand.)
If the variable `string' does point to text, that text is added
to the kill ring. The variable will have a nil
value if no
text was removed.
The code uses when
to determine whether the variable
`string' points to text. A when
statement is simply a
programmers' convenience. A when
statement is an if
statement without the possibility of an else clause. In your mind, you
can replace when
with if
and understand what goes on.
That is what the Lisp interpreter does.
Technically speaking, when
is a Lisp macro. A Lisp macro
enables you to define new control constructs and other language
features. It tells the interpreter how to compute another Lisp
expression which will in turn compute the value. In this case, the
`other expression' is an if
expression. For more about Lisp
macros, see section `Macros' in The GNU Emacs Lisp Reference Manual. The C programming language also provides macros. These are
different, but also useful. We will briefly look at C macros in
delete-and-extract-region
: Digressing into C.
If the string has content, then another conditional expression is
executed. This is an if
with both a then-part and an else-part.
(if (eq last-command 'kill-region) (kill-append string (< end beg)) (kill-new string))) |
The then-part is evaluated if the previous command was another call to
kill-region
; if not, the else-part is evaluated.
last-command
is a variable that comes with Emacs that we have
not seen before. Normally, whenever a function is executed, Emacs
sets the value of last-command
to the previous command.
In this segment of the definition, the if
expression checks
whether the previous command was kill-region
. If it was,
(kill-append string (< end beg)) |
concatenates a copy of the newly clipped text to the just previously
clipped text in the kill ring. (If the (< end beg))
expression is true, kill-append
prepends the string to the just
previously clipped text. For a detailed discussion, see
The kill-append
function.)
If you then yank back the text, i.e., `paste' it, you get both
pieces of text at once. That way, if you delete two words in a row,
and then yank them back, you get both words, in their proper order,
with one yank. (The (< end beg))
expression makes sure the
order is correct.)
On the other hand, if the previous command is not kill-region
,
then the kill-new
function is called, which adds the text to
the kill ring as the latest item, and sets the
kill-ring-yank-pointer
variable to point to it.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
delete-and-extract-region
: Digressing into C
The zap-to-char
command uses the
delete-and-extract-region
function, which in turn uses two
other functions, copy-region-as-kill
and
del_range_1
. The copy-region-as-kill
function will be
described in a following section; it puts a copy of the region in the
kill ring so it can be yanked back. (See section copy-region-as-kill
.)
The delete-and-extract-region
function removes the contents of
a region and you cannot get them back.
Unlike the other code discussed here, delete-and-extract-region
is not written in Emacs Lisp; it is written in C and is one of the
primitives of the GNU Emacs system. Since it is very simple, I will
digress briefly from Lisp and describe it here.
Like many of the other Emacs primitives,
delete-and-extract-region
is written as an instance of a C
macro, a macro being a template for code. The complete macro looks
like this:
DEFUN ("delete-and-extract-region", Fdelete_and_extract_region, Sdelete_and_extract_region, 2, 2, 0, "Delete the text between START and END and return it.") (start, end) Lisp_Object start, end; { validate_region (&start, &end); return del_range_1 (XINT (start), XINT (end), 1, 1); } |
Without going into the details of the macro writing process, let me
point out that this macro starts with the word DEFUN
. The word
DEFUN
was chosen since the code serves the same purpose as
defun
does in Lisp. The word DEFUN
is followed by seven
parts inside of parentheses:
delete-and-extract-region
.
Fdelete_and_extract_region
. By convention, it starts with
`F'. Since C does not use hyphens in names, underscores are used
instead.
interactive
declaration in a function written in Lisp: a letter
followed, perhaps, by a prompt. The only difference from the Lisp is
when the macro is called with no arguments. Then you write a 0
(which is a `null string'), as in this macro.
If you were to specify arguments, you would place them between
quotation marks. The C macro for goto-char
includes
"NGoto char: "
in this position to indicate that the function
expects a raw prefix, in this case, a numerical location in a buffer,
and provides a prompt.
Thus, the first two lines of documentation for goto-char
are
written like this:
"Set point to POSITION, a number or marker.\n\ Beginning of buffer is position (point-min), end is (point-max). |
In a C macro, the formal parameters come next, with a statement of
what kind of object they are, followed by what might be called the `body'
of the macro. For delete-and-extract-region
the `body'
consists of the following two lines:
validate_region (&start, &end); return del_range_1 (XINT (start), XINT (end), 1, 1); |
The first function, validate_region
checks whether the values
passed as the beginning and end of the region are the proper type and
are within range. The second function, del_range_1
, actually
deletes the text.
del_range_1
is a complex function we will not look into. It
updates the buffer and does other things.
However, it is worth looking at the two arguments passed to
del_range
. These are XINT (start)
and XINT
(end)
.
As far as the C language is concerned, start
and end
are
two integers that mark the beginning and end of the region to be
deleted(7).
In early versions of Emacs, these two numbers were thirty-two bits long, but the code is slowly being generalized to handle other lengths. Three of the available bits are used to specify the type of information and a fourth bit is used for handling the computer's memory; the remaining bits are used as `content'.
`XINT' is a C macro that extracts the relevant number from the longer collection of bits; the four other bits are discarded.
The command in delete-and-extract-region
looks like this:
del_range_1 (XINT (start), XINT (end), 1, 1); |
It deletes the region between the beginning position, start
,
and the ending position, end
.
From the point of view of the person writing Lisp, Emacs is all very simple; but hidden underneath is a great deal of complexity to make it all work.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
defvar
Unlike the delete-and-extract-region
function, the
copy-region-as-kill
function is written in Emacs Lisp. Two
functions within it, kill-append
and kill-new
, copy a
region in a buffer and save it in a variable called the
kill-ring
. This section describes how the kill-ring
variable is created and initialized using the defvar
special
form.
(Again we note that the term kill-ring
is a misnomer. The text
that is clipped out of the buffer can be brought back; it is not a ring
of corpses, but a ring of resurrectable text.)
In Emacs Lisp, a variable such as the kill-ring
is created and
given an initial value by using the defvar
special form. The
name comes from "define variable".
The defvar
special form is similar to setq
in that it sets
the value of a variable. It is unlike setq
in two ways: first,
it only sets the value of the variable if the variable does not already
have a value. If the variable already has a value, defvar
does
not override the existing value. Second, defvar
has a
documentation string.
(Another special form, defcustom
, is designed for variables
that people customize. It has more features than defvar
.
(See section Setting Variables with defcustom
.)
Seeing the Current Value of a Variable | ||
8.4.1 defvar and an asterisk | An old-time convention. |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can see the current value of a variable, any variable, by using
the describe-variable
function, which is usually invoked by
typing C-h v. If you type C-h v and then kill-ring
(followed by RET) when prompted, you will see what is in your
current kill ring--this may be quite a lot! Conversely, if you have
been doing nothing this Emacs session except read this document, you
may have nothing in it. Also, you will see the documentation for
kill-ring
:
Documentation: List of killed text sequences. Since the kill ring is supposed to interact nicely with cut-and-paste facilities offered by window systems, use of this variable should interact nicely with `interprogram-cut-function' and `interprogram-paste-function'. The functions `kill-new', `kill-append', and `current-kill' are supposed to implement this interaction; you may want to use them instead of manipulating the kill ring directly. |
The kill ring is defined by a defvar
in the following way:
(defvar kill-ring nil "List of killed text sequences. ...") |
In this variable definition, the variable is given an initial value of
nil
, which makes sense, since if you have saved nothing, you want
nothing back if you give a yank
command. The documentation
string is written just like the documentation string of a defun
.
As with the documentation string of the defun
, the first line of
the documentation should be a complete sentence, since some commands,
like apropos
, print only the first line of documentation.
Succeeding lines should not be indented; otherwise they look odd when
you use C-h v (describe-variable
).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
defvar
and an asterisk
In the past, Emacs used the defvar
special form both for
internal variables that you would not expect a user to change and for
variables that you do expect a user to change. Although you can still
use defvar
for user customizable variables, please use
defcustom
instead, since that special form provides a path into
the Customization commands. (See section Setting Variables with defcustom
.)
When you specified a variable using the defvar
special form,
you could distinguish a readily settable variable from others by
typing an asterisk, `*', in the first column of its documentation
string. For example:
(defvar shell-command-default-error-buffer nil "*Buffer name for `shell-command' ... error output. ... ") |
This means that you could (and still can) use the edit-options
command to change the value of
shell-command-default-error-buffer
temporarily.
However, options set using edit-options
are set only for the
duration of your editing session. The new values are not saved
between sessions. Each time Emacs starts, it reads the original
value, unless you change the value within your `.emacs' file,
either by setting it manually or by using customize
.
See section Your `.emacs' File.
For me, the major use of the edit-options
command is to suggest
variables that I might want to set in my `.emacs' file. I urge
you to look through the list. (See section `Editing Variable Values' in The GNU Emacs Manual.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
copy-region-as-kill
The copy-region-as-kill
function copies a region of text from a
buffer and (via either kill-append
or kill-new
) saves it
in the kill-ring
.
If you call copy-region-as-kill
immediately after a
kill-region
command, Emacs appends the newly copied text to the
previously copied text. This means that if you yank back the text, you
get it all, from both this and the previous operation. On the other
hand, if some other command precedes the copy-region-as-kill
,
the function copies the text into a separate entry in the kill ring.
The complete copy-region-as-kill function definition | The complete function definition. | |
8.5.1 The Body of copy-region-as-kill | The body of copy-region-as-kill . |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
copy-region-as-kill
function definition
Here is the complete text of the version 21 copy-region-as-kill
function:
(defun copy-region-as-kill (beg end) "Save the region as if killed, but don't kill it. In Transient Mark mode, deactivate the mark. If `interprogram-cut-function' is non-nil, also save the text for a window system cut and paste." (interactive "r") (if (eq last-command 'kill-region) (kill-append (buffer-substring beg end) (< end beg)) (kill-new (buffer-substring beg end))) (if transient-mark-mode (setq deactivate-mark t)) nil) |
As usual, this function can be divided into its component parts:
(defun copy-region-as-kill (argument-list) "documentation..." (interactive "r") body...) |
The arguments are beg
and end
and the function is
interactive with "r"
, so the two arguments must refer to the
beginning and end of the region. If you have been reading though this
document from the beginning, understanding these parts of a function is
almost becoming routine.
The documentation is somewhat confusing unless you remember that the
word `kill' has a meaning different from its usual meaning. The
`Transient Mark' and interprogram-cut-function
comments explain
certain side-effects.
After you once set a mark, a buffer always contains a region. If you wish, you can use Transient Mark mode to highlight the region temporarily. (No one wants to highlight the region all the time, so Transient Mark mode highlights it only at appropriate times. Many people turn off Transient Mark mode, so the region is never highlighted.)
Also, a windowing system allows you to copy, cut, and paste among
different programs. In the X windowing system, for example, the
interprogram-cut-function
function is x-select-text
,
which works with the windowing system's equivalent of the Emacs kill
ring.
The body of the copy-region-as-kill
function starts with an
if
clause. What this clause does is distinguish between two
different situations: whether or not this command is executed
immediately after a previous kill-region
command. In the first
case, the new region is appended to the previously copied text.
Otherwise, it is inserted into the beginning of the kill ring as a
separate piece of text from the previous piece.
The last two lines of the function prevent the region from lighting up if Transient Mark mode is turned on.
The body of copy-region-as-kill
merits discussion in detail.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
copy-region-as-kill
The copy-region-as-kill
function works in much the same way as
the kill-region
function (see section kill-region
). Both are written so that two or more kills in
a row combine their text into a single entry. If you yank back the
text from the kill ring, you get it all in one piece. Moreover, kills
that kill forward from the current position of the cursor are added to
the end of the previously copied text and commands that copy text
backwards add it to the beginning of the previously copied text. This
way, the words in the text stay in the proper order.
Like kill-region
, the copy-region-as-kill
function makes
use of the last-command
variable that keeps track of the
previous Emacs command.
last-command and this-command | ||
The kill-append function | ||
The kill-new function |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
last-command
and this-command
Normally, whenever a function is executed, Emacs sets the value of
this-command
to the function being executed (which in this case
would be copy-region-as-kill
). At the same time, Emacs sets
the value of last-command
to the previous value of
this-command
.
In the first part of the body of the copy-region-as-kill
function, an if
expression determines whether the value of
last-command
is kill-region
. If so, the then-part of
the if
expression is evaluated; it uses the kill-append
function to concatenate the text copied at this call to the function
with the text already in the first element (the CAR) of the kill
ring. On the other hand, if the value of last-command
is not
kill-region
, then the copy-region-as-kill
function
attaches a new element to the kill ring using the kill-new
function.
The if
expression reads as follows; it uses eq
, which is
a function we have not yet seen:
(if (eq last-command 'kill-region) ;; then-part (kill-append (buffer-substring beg end) (< end beg)) ;; else-part (kill-new (buffer-substring beg end))) |
The eq
function tests whether its first argument is the same Lisp
object as its second argument. The eq
function is similar to the
equal
function in that it is used to test for equality, but
differs in that it determines whether two representations are actually
the same object inside the computer, but with different names.
equal
determines whether the structure and contents of two
expressions are the same.
If the previous command was kill-region
, then the Emacs Lisp
interpreter calls the kill-append
function
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
kill-append
function
The kill-append
function looks like this:
(defun kill-append (string before-p) "Append STRING to the end of the latest kill in the kill ring. If BEFORE-P is non-nil, prepend STRING to the kill. If `interprogram-cut-function' is set, pass the resulting kill to it." (kill-new (if before-p (concat string (car kill-ring)) (concat (car kill-ring) string)) t)) |
The kill-append
function is fairly straightforward. It uses
the kill-new
function, which we will discuss in more detail in
a moment.
First, let us look at the conditional that is one of the two arguments
to kill-new
. It uses concat
to concatenate the new text
to the CAR of the kill ring. Whether it prepends or appends the
text depends on the results of an if
expression:
(if before-p ; if-part (concat string (car kill-ring)) ; then-part (concat (car kill-ring) string)) ; else-part |
If the region being killed is before the region that was killed in the
last command, then it should be prepended before the material that was
saved in the previous kill; and conversely, if the killed text follows
what was just killed, it should be appended after the previous text.
The if
expression depends on the predicate before-p
to
decide whether the newly saved text should be put before or after the
previously saved text.
The symbol before-p
is the name of one of the arguments to
kill-append
. When the kill-append
function is
evaluated, it is bound to the value returned by evaluating the actual
argument. In this case, this is the expression (< end beg)
.
This expression does not directly determine whether the killed text in
this command is located before or after the kill text of the last
command; what is does is determine whether the value of the variable
end
is less than the value of the variable beg
. If it
is, it means that the user is most likely heading towards the
beginning of the buffer. Also, the result of evaluating the predicate
expression, (< end beg)
, will be true and the text will be
prepended before the previous text. On the other hand, if the value of
the variable end
is greater than the value of the variable
beg
, the text will be appended after the previous text.
When the newly saved text will be prepended, then the string with the new text will be concatenated before the old text:
(concat string (car kill-ring)) |
But if the text will be appended, it will be concatenated after the old text:
(concat (car kill-ring) string)) |
To understand how this works, we first need to review the
concat
function. The concat
function links together or
unites two strings of text. The result is a string. For example:
(concat "abc" "def") => "abcdef" (concat "new " (car '("first element" "second element"))) => "new first element" (concat (car '("first element" "second element")) " modified") => "first element modified" |
We can now make sense of kill-append
: it modifies the contents
of the kill ring. The kill ring is a list, each element of which is
saved text. The kill-append
function uses the kill-new
function which in turn uses the setcar
function.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
kill-new
function
The kill-new
function looks like this:
(defun kill-new (string &optional replace) "Make STRING the latest kill in the kill ring. Set the kill-ring-yank pointer to point to it. If `interprogram-cut-function' is non-nil, apply it to STRING. Optional second argument REPLACE non-nil means that STRING will replace the front of the kill ring, rather than being added to the list." (and (fboundp 'menu-bar-update-yank-menu) (menu-bar-update-yank-menu string (and replace (car kill-ring)))) (if (and replace kill-ring) (setcar kill-ring string) (setq kill-ring (cons string kill-ring)) (if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) (setq kill-ring-yank-pointer kill-ring) (if interprogram-cut-function (funcall interprogram-cut-function string (not replace)))) |
As usual, we can look at this function in parts.
The first line of the documentation makes sense:
Make STRING the latest kill in the kill ring. |
Let's skip over the rest of the documentation for the moment.
Also, let's skip over the first two lines of code, those involving
menu-bar-update-yank-menu
. We will explain them below.
The critical lines are these:
(if (and replace kill-ring) ;; then (setcar kill-ring string) ;; else (setq kill-ring (cons string kill-ring)) (if (> (length kill-ring) kill-ring-max) ;; avoid overly long kill ring (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) (setq kill-ring-yank-pointer kill-ring) (if interprogram-cut-function (funcall interprogram-cut-function string (not replace)))) |
The conditional test is (and replace kill-ring)
.
This will be true when two conditions are met: the kill ring has
something in it, and the replace
variable is true.
The kill-append
function sets replace
to be true; then,
when the kill ring has at least one item in it, the setcar
expression is executed:
(setcar kill-ring string) |
The setcar
function actually changes the first element of the
kill-ring
list to the value of string
. It replaces the
first element.
On the other hand, if the kill ring is empty, or replace is false, the else-part of the condition is executed:
(setq kill-ring (cons string kill-ring)) (if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)) |
This expression first constructs a new version of the kill ring by
prepending string
to the existing kill ring as a new element.
Then it executes a second if
clause. This second if
clause keeps the kill ring from growing too long.
Let's look at these two expressions in order.
The setq
line of the else-part sets the new value of the kill
ring to what results from adding the string being killed to the old kill
ring.
We can see how this works with an example:
(setq example-list '("here is a clause" "another clause")) |
After evaluating this expression with C-x C-e, you can evaluate
example-list
and see what it returns:
example-list => ("here is a clause" "another clause") |
Now, we can add a new element on to this list by evaluating the following expression:
(setq example-list (cons "a third clause" example-list)) |
When we evaluate example-list
, we find its value is:
example-list => ("a third clause" "here is a clause" "another clause") |
Thus, the third clause was added to the list by cons
.
This is exactly similar to what the setq
and cons
do in
the function. Here is the line again:
(setq kill-ring (cons string kill-ring)) |
Now for the second part of the if
clause. This expression
keeps the kill ring from growing too long. It looks like this:
(if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)) |
The code checks whether the length of the kill ring is greater than
the maximum permitted length. This is the value of
kill-ring-max
(which is 60, by default). If the length of the
kill ring is too long, then this code sets the last element of the
kill ring to nil
. It does this by using two functions,
nthcdr
and setcdr
.
We looked at setcdr
earlier (see section setcdr
).
It sets the CDR of a list, just as setcar
sets the
CAR of a list. In this case, however, setcdr
will not be
setting the CDR of the whole kill ring; the nthcdr
function is used to cause it to set the CDR of the next to last
element of the kill ring--this means that since the CDR of the
next to last element is the last element of the kill ring, it will set
the last element of the kill ring.
The nthcdr
function works by repeatedly taking the CDR of a
list--it takes the CDR of the CDR of the CDR
... It does this N times and returns the results.
Thus, if we had a four element list that was supposed to be three
elements long, we could set the CDR of the next to last element
to nil
, and thereby shorten the list.
You can see this by evaluating the following three expressions in turn.
First set the value of trees
to (maple oak pine birch)
,
then set the CDR of its second CDR to nil
and then
find the value of trees
:
(setq trees '(maple oak pine birch)) => (maple oak pine birch) (setcdr (nthcdr 2 trees) nil) => nil trees => (maple oak pine) |
(The value returned by the setcdr
expression is nil
since
that is what the CDR is set to.)
To repeat, in kill-new
, the nthcdr
function takes the
CDR a number of times that is one less than the maximum permitted
size of the kill ring and sets the CDR of that element (which
will be the rest of the elements in the kill ring) to nil
.
This prevents the kill ring from growing too long.
The next to last expression in the kill-new
function is
(setq kill-ring-yank-pointer kill-ring) |
The kill-ring-yank-pointer
is a global variable that is set to be
the kill-ring
.
Even though the kill-ring-yank-pointer
is called a
`pointer', it is a variable just like the kill ring. However, the
name has been chosen to help humans understand how the variable is used.
The variable is used in functions such as yank
and
yank-pop
(see section Yanking Text Back).
Now, to return to the first two lines in the body of the function:
(and (fboundp 'menu-bar-update-yank-menu) (menu-bar-update-yank-menu string (and replace (car kill-ring)))) |
This is an expression whose first element is the function and
.
The and
special form evaluates each of its arguments until one of
the arguments returns a value of nil
, in which case the
and
expression returns nil
; however, if none of the
arguments returns a value of nil
, the value resulting from
evaluating the last argument is returned. (Since such a value is not
nil
, it is considered true in Emacs Lisp.) In other words, an
and
expression returns a true value only if all its arguments
are true.
In this case, the expression tests first to see whether
menu-bar-update-yank-menu
exists as a function, and if so,
calls it. The fboundp
function returns true if the symbol it
is testing has a function definition that `is not void'. If the
symbol's function definition were void, we would receive an error
message, as we did when we created errors intentionally (see section Generate an Error Message).
Essentially, the and
is an if
expression that reads like
this:
if the-menu-bar-function-exists then execute-it |
menu-bar-update-yank-menu
is one of the functions that make it
possible to use the `Select and Paste' menu in the Edit item of a menu
bar; using a mouse, you can look at the various pieces of text you
have saved and select one piece to paste.
Finally, the last expression in the kill-new
function adds the
newly copied string to whatever facility exists for copying and
pasting among different programs running in a windowing system. In
the X Windowing system, for example, the x-select-text
function
takes the string and stores it in memory operated by X. You can paste
the string in another program, such as an Xterm.
The expression looks like this:
(if interprogram-cut-function (funcall interprogram-cut-function string (not replace)))) |
If an interprogram-cut-function
exists, then Emacs executes
funcall
, which in turn calls its first argument as a function
and passes the remaining arguments to it. (Incidentally, as far as I
can see, this if
expression could be replaced by an and
expression similar to the one in the first part of the function.)
We are not going to discuss windowing systems and other programs further, but merely note that this is a mechanism that enables GNU Emacs to work easily and well with other programs.
This code for placing text in the kill ring, either concatenated with an existing element or as a new element, leads us to the code for bringing back text that has been cut out of the buffer--the yank commands. However, before discussing the yank commands, it is better to learn how lists are implemented in a computer. This will make clear such mysteries as the use of the term `pointer'.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Here is a brief summary of some recently introduced functions.
car
cdr
car
returns the first element of a list; cdr
returns the
second and subsequent elements of a list.
For example:
(car '(1 2 3 4 5 6 7)) => 1 (cdr '(1 2 3 4 5 6 7)) => (2 3 4 5 6 7) |
cons
cons
constructs a list by prepending its first argument to its
second argument.
For example:
(cons 1 '(2 3 4)) => (1 2 3 4) |
nthcdr
For example:
(nthcdr 3 '(1 2 3 4 5 6 7)) => (4 5 6 7) |
setcar
setcdr
setcar
changes the first element of a list; setcdr
changes the second and subsequent elements of a list.
For example:
(setq triple '(1 2 3)) (setcar triple '37) triple => (37 2 3) (setcdr triple '("foo" "bar")) triple => (37 "foo" "bar") |
progn
For example:
(progn 1 2 3 4) => 4 |
save-restriction
search-forward
Takes four arguments:
nil
or an
error message.
kill-region
delete-region
copy-region-as-kill
kill-region
cuts the text between point and mark from the
buffer and stores that text in the kill ring, so you can get it back
by yanking.
delete-and-extract-region
removes the text between point and
mark from the buffer and throws it away. You cannot get it back.
copy-region-as-kill
copies the text between point and mark into
the kill ring, from which you can get it by yanking. The function
does not cut or remove the text from the buffer.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
search-forward
for the name
of this function; if you do, you will overwrite the existing version of
search-forward
that comes with Emacs. Use a name such as
test-search
instead.)
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |