copy-region-as-kill
Now, back to the explanation of copy-region-as-kill
:
If the last command is not kill-region
, then instead of calling
kill-append
, it calls the else-part of the following code:
(if true-or-false-test what-is-done-if-test-returns-true ;; else-part (setq kill-ring (cons (buffer-substring beg end) kill-ring)) (if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
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 a little 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, except that buffer-substring
is used to pull out a
copy of a region of text and hand it to the cons
. Here is the
line again:
(setq kill-ring (cons (buffer-substring beg end) kill-ring))
The next segment of the else-part of copy-region-as-kill
is
another if
clause. This if
clause keeps the kill ring
from growing too long. It reads as follows:
(if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
This 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 30, 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 copy-region-as-kill
, 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 line of the copy-region-as-kill
function is
(setq this-command 'kill-region)
This line is not part of either the inner or the outer if
expression, so it is evaluated every time copy-region-as-kill
is
called. Here we find the place where this-command
is set to
kill-region
. As we saw earlier, when the next command is given,
the variable last-command
will be given this value.
Finally, the last line of the copy-region-as-kill
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).
This 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'.
Go to the first, previous, next, last section, table of contents.