In version 22 the
kill-new function looks like this:
(defun kill-new (string &optional replace yank-handler) "Make STRING the latest kill in the kill ring. Set `kill-ring-yank-pointer' to point to it. If `interprogram-cut-function' is non-nil, apply it to STRING. Optional second argument REPLACE non-nil means that STRING will replace the front of the kill ring, rather than being added to the list. ..." (if (> (length string) 0) (if yank-handler (put-text-property 0 (length string) 'yank-handler yank-handler string)) (if yank-handler (signal 'args-out-of-range (list string "yank-handler specified for empty string")))) (if (fboundp 'menu-bar-update-yank-menu) (menu-bar-update-yank-menu string (and replace (car kill-ring)))) (if (and replace kill-ring) (setcar kill-ring string) (push string kill-ring) (if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) (setq kill-ring-yank-pointer kill-ring) (if interprogram-cut-function (funcall interprogram-cut-function string (not replace))))
(Notice that the function is not interactive.)
As usual, we can look at this function in parts.
The function definition has an optional
which when invoked tells the function how to deal with properties
added to the text, such as bold or italics. We will skip that.
The first line of the documentation makes sense:
Make STRING the latest kill in the kill ring.
Let's skip over the rest of the documentation for the moment.
Also, let's skip over the initial
if expression and those lines
of code involving
menu-bar-update-yank-menu. We will explain
The critical lines are these:
(if (and replace kill-ring) ;; then (setcar kill-ring string) ;; else (push string kill-ring) (if (> (length kill-ring) kill-ring-max) ;; avoid overly long kill ring (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) (setq kill-ring-yank-pointer kill-ring) (if interprogram-cut-function (funcall interprogram-cut-function string (not replace))))
The conditional test is
(and replace kill-ring).
This will be true when two conditions are met: the kill ring has
something in it, and the
replace variable is true.
kill-append function sets
replace to be true
and when the kill ring has at least one item in it, the
expression is executed:
(setcar kill-ring string)
setcar function actually changes the first element of the
kill-ring list to the value of
string. It replaces the
On the other hand, if the kill ring is empty, or replace is false, the else-part of the condition is executed:
(push string kill-ring)
push puts its first argument onto the second. It is similar to
(setq kill-ring (cons string kill-ring))
or the newer
(add-to-list kill-ring string)
When it is false, the expression first constructs a new version of the
kill ring by prepending
string to the existing kill ring as a
new element (that is what the
push does). Then it executes a
if clause. This second
if clause keeps the kill
ring from growing too long.
Let's look at these two expressions in order.
push line of the else-part sets the new value of the kill
ring to what results from adding the string being killed to the old
We can see how this works with an example.
(setq example-list '("here is a clause" "another clause"))
After evaluating this expression with C-x C-e, you can evaluate
example-list and see what it returns:
example-list ⇒ ("here is a clause" "another clause")
Now, we can add a new element on to this list by evaluating the following expression:
(push "a third clause" example-list)
When we evaluate
example-list, we find its value is:
example-list ⇒ ("a third clause" "here is a clause" "another clause")
Thus, the third clause is added to the list by
Now for the second part of the
if clause. This expression
keeps the kill ring from growing too long. It looks like this:
(if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
The code checks whether the length of the kill ring is greater than
the maximum permitted length. This is the value of
kill-ring-max (which is 60, by default). If the length of the
kill ring is too long, then this code sets the last element of the
kill ring to
nil. It does this by using two functions,
We looked at
setcdr earlier (see
It sets the cdr of a list, just as
setcar sets the
car of a list. In this case, however,
setcdr will not be
setting the cdr of the whole kill ring; the
function is used to cause it to set the cdr of the next to last
element of the kill ring—this means that since the cdr of the
next to last element is the last element of the kill ring, it will set
the last element of the kill ring.
nthcdr function works by repeatedly taking the cdr of a
list—it takes the cdr of the cdr of the cdr
... It does this N times and returns the results.
Thus, if we had a four element list that was supposed to be three
elements long, we could set the cdr of the next to last element
nil, and thereby shorten the list. (If you set the last
element to some other value than
nil, which you could do, then
you would not have shortened the list. See
You can see shortening by evaluating the following three expressions
in turn. First set the value of
(maple oak pine
birch), then set the cdr of its second cdr to
and then find the value of
(setq trees '(maple oak pine birch)) ⇒ (maple oak pine birch) (setcdr (nthcdr 2 trees) nil) ⇒ nil trees ⇒ (maple oak pine)
(The value returned by the
setcdr expression is
that is what the cdr is set to.)
To repeat, in
nthcdr function takes the
cdr a number of times that is one less than the maximum permitted
size of the kill ring and
setcdr sets the cdr of that
element (which will be the rest of the elements in the kill ring) to
nil. This prevents the kill ring from growing too long.
The next to last expression in the
kill-new function is
(setq kill-ring-yank-pointer kill-ring)
kill-ring-yank-pointer is a global variable that is set to be
Even though the
kill-ring-yank-pointer is called a
‘pointer’, it is a variable just like the kill ring. However, the
name has been chosen to help humans understand how the variable is used.
Now, to return to an early expression in the body of the function:
(if (fboundp 'menu-bar-update-yank-menu) (menu-bar-update-yank-menu string (and replace (car kill-ring))))
It starts with an
In this case, the expression tests first to see whether
menu-bar-update-yank-menu exists as a function, and if so,
calls it. The
fboundp function returns true if the symbol it
is testing has a function definition that is not void. If the
symbol's function definition were void, we would receive an error
message, as we did when we created errors intentionally (see Generate an Error Message).
The then-part contains an expression whose first element is the
and special form evaluates each of its arguments until one
of the arguments returns a value of
nil, in which case the
and expression returns
nil; however, if none of the
arguments returns a value of
nil, the value resulting from
evaluating the last argument is returned. (Since such a value is not
nil, it is considered true in Emacs Lisp.) In other words, an
and expression returns a true value only if all its arguments
are true. (See Second Buffer Related Review.)
The expression determines whether the second argument to
menu-bar-update-yank-menu is true or not.
menu-bar-update-yank-menu is one of the functions that make it
possible to use the “Select and Paste” menu in the Edit item of a menu
bar; using a mouse, you can look at the various pieces of text you
have saved and select one piece to paste.
The last expression in the
kill-new function adds the newly
copied string to whatever facility exists for copying and pasting
among different programs running in a windowing system. In the X
Windowing system, for example, the
x-select-text function takes
the string and stores it in memory operated by X. You can paste the
string in another program, such as an Xterm.
The expression looks like this:
(if interprogram-cut-function (funcall interprogram-cut-function string (not replace))))
interprogram-cut-function exists, then Emacs executes
funcall, which in turn calls its first argument as a function
and passes the remaining arguments to it. (Incidentally, as far as I
can see, this
if expression could be replaced by an
expression similar to the one in the first part of the function.)
We are not going to discuss windowing systems and other programs further, but merely note that this is a mechanism that enables GNU Emacs to work easily and well with other programs.
This code for placing text in the kill ring, either concatenated with an existing element or as a new element, leads us to the code for bringing back text that has been cut out of the buffer—the yank commands. However, before discussing the yank commands, it is better to learn how lists are implemented in a computer. This will make clear such mysteries as the use of the term “pointer”. But before that, we will digress into C.