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)