Go to the previous, next section.

The  kill-append function

The  kill-append function looks like this:

(defun kill-append (string before-p)
  (setcar kill-ring
          (if before-p
              (concat string (car kill-ring))
              (concat (car kill-ring) string))))

We can look at this function in parts. The  setcar function uses  concat to concatenate the new text to the CAR of the kill ring. Whether it prepends or appends the text depends on the results of an  if expression:

(if before-p                            ; if-part
    (concat string (car kill-ring))     ; then-part
  (concat (car kill-ring) string))      ; else-part

If the region being killed is before the region that was killed in the last command, then it should be prepended before the material that was saved in the previous kill; and conversely, if the killed text follows what was just killed, it should be appended after the previous text. The  if expression depends on the predicate  before-p to decide whether the newly saved text should be put before or after the previously saved text.

The symbol  before-p is the name of one of the arguments to  kill-append . When the  kill-append function is evaluated, it is bound to the value returned by evaluating the actual argument. In this case, this is the expression  (< end beg) . This expression does not directly determine whether the killed text in this command is located before or after the kill text of the last command; what is does is determine whether the value of the variable  end is less than the value of the variable  beg . If it is, it means that the user is most likely heading towards the beginning of the buffer. Also, the result of evaluating the predicate expression,  (< end beg) , will be true and the text will be prepended before the previous text. On the other hand, if the value of the variable  end is greater than the value of the variable  beg , the text will be appended after the previous text.

When the newly saved text will be prepended, then the string with the new text will be concatenated before the old test:

(concat string (car kill-ring))

But if the text will be appended, it will be concatenated after the old text:

(concat (car kill-ring) string))

To understand how this works, we first need to review the  concat function. The  concat function links together or unites two strings of text. The result is a string. For example:

(concat "abc" "def")
     @result{} "abcdef"

(concat "new " 
        (car '("first element" "second element")))
     @result{} "new first element"

(concat (car 
        '("first element" "second element")) " modified")
     @result{} "first element modified"

We can now make sense of  kill-append : it modifies the contents of the kill ring. The kill ring is a list, each element of which is saved text. The  setcar function actually changes the first element of this list. It does this by using  concat to replace the old first element of the kill ring (the CAR of the kill ring) with a new first element made by concatenating together the old saved text and the newly saved text. The newly saved text is put in front of the old text or after the old text, depending on whether it is in front of or after the old text in the buffer from which it is cut. The whole concatenation becomes the new first element of the kill ring.

Incidentally, this is what the beginning of my current kill ring looks like:

("concatenating together" "saved text" "element" @dots{}

Go to the previous, next section.