Node:rotate-yk-ptr else-part, Next:Remainder Function, Previous:Digression concerning error, Up:rotate-yk-ptr body
if
expressionThe else-part of the if
expression is dedicated to setting the
value of kill-ring-yank-pointer
when the kill ring has something
in it. The code looks like this:
(setq kill-ring-yank-pointer (nthcdr (% (+ arg (- length (length kill-ring-yank-pointer))) length) kill-ring)))))
This needs some examination. Clearly, kill-ring-yank-pointer
is being set to be equal to some CDR of the kill ring, using the
nthcdr
function that is described in an earlier section.
(See copy-region-as-kill.) But exactly how does it do this?
Before looking at the details of the code let's first consider the
purpose of the rotate-yank-pointer
function.
The rotate-yank-pointer
function changes what
kill-ring-yank-pointer
points to. If
kill-ring-yank-pointer
starts by pointing to the first element
of a list, a call to rotate-yank-pointer
causes it to point to
the second element; and if kill-ring-yank-pointer
points to the
second element, a call to rotate-yank-pointer
causes it to
point to the third element. (And if rotate-yank-pointer
is
given an argument greater than 1, it jumps the pointer that many
elements.)
The rotate-yank-pointer
function uses setq
to reset what
the kill-ring-yank-pointer
points to. If
kill-ring-yank-pointer
points to the first element of the kill
ring, then, in the simplest case, the rotate-yank-pointer
function must cause it to point to the second element. Put another
way, kill-ring-yank-pointer
must be reset to have a value equal
to the CDR of the kill ring.
That is, under these circumstances,
(setq kill-ring-yank-pointer ("some text" "a different piece of text" "yet more text")) (setq kill-ring ("some text" "a different piece of text" "yet more text"))
the code should do this:
(setq kill-ring-yank-pointer (cdr kill-ring))
As a result, the kill-ring-yank-pointer
will look like this:
kill-ring-yank-pointer => ("a different piece of text" "yet more text"))
The actual setq
expression uses the nthcdr
function to do
the job.
As we have seen before (see nthcdr), the nthcdr
function
works by repeatedly taking the CDR of a list--it takes the
CDR of the CDR of the CDR ...
The two following expressions produce the same result:
(setq kill-ring-yank-pointer (cdr kill-ring)) (setq kill-ring-yank-pointer (nthcdr 1 kill-ring))
In the rotate-yank-pointer
function, however, the first
argument to nthcdr
is a rather complex looking expression with
lots of arithmetic inside of it:
(% (+ arg (- length (length kill-ring-yank-pointer))) length)
As usual, we need to look at the most deeply embedded expression first and then work our way towards the light.
The most deeply embedded expression is (length
kill-ring-yank-pointer)
. This finds the length of the current value of
the kill-ring-yank-pointer
. (Remember that the
kill-ring-yank-pointer
is the name of a variable whose value is a
list.)
The measurement of the length is inside the expression:
(- length (length kill-ring-yank-pointer))
In this expression, the first length
is the variable that was
assigned the length of the kill ring in the let
statement at the
beginning of the function. (One might think this function would be
clearer if the variable length
were named
length-of-kill-ring
instead; but if you look at the text of the
whole function, you will see that it is so short that naming this
variable length
is not a bother, unless you are pulling the
function apart into very tiny pieces as we are doing here.)
So the line (- length (length kill-ring-yank-pointer))
tells the
difference between the length of the kill ring and the length of the list
whose name is kill-ring-yank-pointer
.
To see how all this fits into the rotate-yank-pointer
function, let's begin by analyzing the case where
kill-ring-yank-pointer
points to the first element of the kill
ring, just as kill-ring
does, and see what happens when
rotate-yank-pointer
is called with an argument of 1.
The variable length
and the value of the expression
(length kill-ring-yank-pointer)
will be the same since the
variable length
is the length of the kill ring and the
kill-ring-yank-pointer
is pointing to the whole kill ring.
Consequently, the value of
(- length (length kill-ring-yank-pointer))
will be zero. Since the value of arg
will be 1, this will mean
that the value of the whole expression
(+ arg (- length (length kill-ring-yank-pointer)))
will be 1.
Consequently, the argument to nthcdr
will be found as the result of
the expression
(% 1 length)