Info Node: (emacs-lisp-intro.info)rotate-yk-ptr else-part
(emacs-lisp-intro.info)rotate-yk-ptr else-part
The else-part of the `if' expression
....................................
The 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. (Note: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 (Note: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)