Go to the previous, next section.

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. (See section  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
     @result{} ("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 section  nthcdr ), the  nthcdr function works by repeatedly taking the CDR of a list--it takes the CDR of the CDR of the CDR @dots{}

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.

In this case, 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)

Go to the previous, next section.