[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8. Cutting and Storing Text

Whenever you cut or clip text out of a buffer with a `kill' command in GNU Emacs, it is stored in a list and you can bring it back with a `yank' command.

(The use of the word `kill' in Emacs for processes which specifically do not destroy the values of the entities is an unfortunate historical accident. A much more appropriate word would be `clip' since that is what the kill commands do; they clip text out of a buffer and put it into storage from which it can be brought back. I have often been tempted to replace globally all occurrences of `kill' in the Emacs sources with `clip' and all occurrences of `killed' with `clipped'.)

Storing Text in a List  Text is stored in a list.
8.1 zap-to-char  Cutting out text up to a character.
8.2 kill-region  Cutting text out of a region.
8.3 delete-and-extract-region: Digressing into C  Minor note on C programming language macros.
8.4 Initializing a Variable with defvar  How to give a variable an initial value.
8.5 copy-region-as-kill  A definition for copying text.
8.6 Review  
8.7 Searching Exercises  

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Storing Text in a List

When text is cut out of a buffer, it is stored on a list. Successive pieces of text are stored on the list successively, so the list might look like this:

("a piece of text" "previous piece")

The function cons can be used to add a piece of text to the list, like this:

(cons "another piece"
      '("a piece of text" "previous piece"))

If you evaluate this expression, a list of three elements will appear in the echo area:

("another piece" "a piece of text" "previous piece")

With the car and nthcdr functions, you can retrieve whichever piece of text you want. For example, in the following code, nthcdr 1 ... returns the list with the first item removed; and the car returns the first element of that remainder--the second element of the original list:

(car (nthcdr 1 '("another piece"
                 "a piece of text"
                 "previous piece")))
     => "a piece of text"

The actual functions in Emacs are more complex than this, of course. The code for cutting and retrieving text has to be written so that Emacs can figure out which element in the list you want--the first, second, third, or whatever. In addition, when you get to the end of the list, Emacs should give you the first element of the list, rather than nothing at all.

The list that holds the pieces of text is called the kill ring. This chapter leads up to a description of the kill ring and how it is used by first tracing how the zap-to-char function works. This function uses (or `calls') a function that invokes a function that manipulates the kill ring. Thus, before reaching the mountains, we climb the foothills.

A subsequent chapter describes how text that is cut from the buffer is retrieved. See section Yanking Text Back.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1 zap-to-char

The zap-to-char function barely changed between GNU Emacs version 19 and GNU Emacs version 21. However, zap-to-char calls another function, kill-region, which enjoyed a major rewrite on the way to version 21.

The kill-region function in Emacs 19 is complex, but does not use code that is important at this time. We will skip it.

The kill-region function in Emacs 21 is easier to read than the same function in Emacs 19 and introduces a very important concept, that of error handling. We will walk through the function.

But first, let us look at the interactive zap-to-char function.

The Complete zap-to-char Implementation  The complete implementation.
8.1.1 The interactive Expression  A three part interactive expression.
8.1.2 The Body of zap-to-char  A short overview.
8.1.3 The search-forward Function  How to search for a string.
8.1.4 The progn Special Form  The progn special form.
8.1.5 Summing up zap-to-char  Using point and search-forward.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The Complete zap-to-char Implementation

The GNU Emacs version 19 and version 21 implementations of the zap-to-char function are nearly identical in form, and they work alike. The function removes the text in the region between the location of the cursor (i.e., of point) up to and including the next occurrence of a specified character. The text that zap-to-char removes is put in the kill ring; and it can be retrieved from the kill ring by typing C-y (yank). If the command is given an argument, it removes text through that number of occurrences. Thus, if the cursor were at the beginning of this sentence and the character were `s', `Thus' would be removed. If the argument were two, `Thus, if the curs' would be removed, up to and including the `s' in `cursor'.

If the specified character is not found, zap-to-char will say "Search failed", tell you the character you typed, and not remove any text.

In order to determine how much text to remove, zap-to-char uses a search function. Searches are used extensively in code that manipulates text, and we will focus attention on them as well as on the deletion command.

Here is the complete text of the version 19 implementation of the function:

(defun zap-to-char (arg char)  ; version 19 implementation
  "Kill up to and including ARG'th occurrence of CHAR.
Goes backward if ARG is negative; error if CHAR not found."
  (interactive "*p\ncZap to char: ")
  (kill-region (point)
                  (char-to-string char) nil nil arg)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1.1 The interactive Expression

The interactive expression in the zap-to-char command looks like this:

(interactive "*p\ncZap to char: ")

The part within quotation marks, "*p\ncZap to char: ", specifies three different things. First, and most simply, the asterisk, `*', causes an error to be signalled if the buffer is read-only. This means that if you try zap-to-char in a read-only buffer you will not be able to remove text, and you will receive a message that says "Buffer is read-only"; your terminal may beep at you as well.

The version 21 implementation does not have the asterisk, `*'. The function works the same as in version 19: in both cases, it cannot remove text from a read-only buffer but the function does copy the text that would have been removed to the kill ring. Also, in both cases, you see an error message.

However, the version 19 implementation copies text from a read-only buffer only because of a mistake in the implementation of interactive. According to the documentation for interactive, the asterisk, `*', should prevent the zap-to-char function from doing anything at all when the buffer is read only. The function should not copy the text to the kill ring. It is a bug that it does.

In version 21, interactive is implemented correctly. So the asterisk, `*', had to be removed from the interactive specification. If you insert an `*' and evaluate the function definition, then the next time you run the zap-to-char function on a read-only buffer, you will not copy any text.

That change aside, and a change to the documentation, the two versions of the zap-to-char function are identical.

Let us continue with the interactive specification.

The second part of "*p\ncZap to char: " is the `p'. This part is separated from the next part by a newline, `\n'. The `p' means that the first argument to the function will be passed the value of a `processed prefix'. The prefix argument is passed by typing C-u and a number, or M- and a number. If the function is called interactively without a prefix, 1 is passed to this argument.

The third part of "*p\ncZap to char: " is `cZap to char: '. In this part, the lower case `c' indicates that interactive expects a prompt and that the argument will be a character. The prompt follows the `c' and is the string `Zap to char: ' (with a space after the colon to make it look good).

What all this does is prepare the arguments to zap-to-char so they are of the right type, and give the user a prompt.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1.2 The Body of zap-to-char

The body of the zap-to-char function contains the code that kills (that is, removes) the text in the region from the current position of the cursor up to and including the specified character. The first part of the code looks like this:

(kill-region (point) ...

(point) is the current position of the cursor.

The next part of the code is an expression using progn. The body of the progn consists of calls to search-forward and point.

It is easier to understand how progn works after learning about search-forward, so we will look at search-forward and then at progn.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1.3 The search-forward Function

The search-forward function is used to locate the zapped-for-character in zap-to-char. If the search is successful, search-forward leaves point immediately after the last character in the target string. (In zap-to-char, the target string is just one character long.) If the search is backwards, search-forward leaves point just before the first character in the target. Also, search-forward returns t for true. (Moving point is therefore a `side effect'.)

In zap-to-char, the search-forward function looks like this:

(search-forward (char-to-string char) nil nil arg)

The search-forward function takes four arguments:

  1. The first argument is the target, what is searched for. This must be a string, such as `"z"'.

    As it happens, the argument passed to zap-to-char is a single character. Because of the way computers are built, the Lisp interpreter may treat a single character as being different from a string of characters. Inside the computer, a single character has a different electronic format than a string of one character. (A single character can often be recorded in the computer using exactly one byte; but a string may be longer, and the computer needs to be ready for this.) Since the search-forward function searches for a string, the character that the zap-to-char function receives as its argument must be converted inside the computer from one format to the other; otherwise the search-forward function will fail. The char-to-string function is used to make this conversion.

  2. The second argument bounds the search; it is specified as a position in the buffer. In this case, the search can go to the end of the buffer, so no bound is set and the second argument is nil.

  3. The third argument tells the function what it should do if the search fails--it can signal an error (and print a message) or it can return nil. A nil as the third argument causes the function to signal an error when the search fails.

  4. The fourth argument to search-forward is the repeat count--how many occurrences of the string to look for. This argument is optional and if the function is called without a repeat count, this argument is passed the value 1. If this argument is negative, the search goes backwards.

In template form, a search-forward expression looks like this:

(search-forward "target-string"

We will look at progn next.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1.4 The progn Special Form

progn is a special form that causes each of its arguments to be evaluated in sequence and then returns the value of the last one. The preceding expressions are evaluated only for the side effects they perform. The values produced by them are discarded.

The template for a progn expression is very simple:


In zap-to-char, the progn expression has to do two things: put point in exactly the right position; and return the location of point so that kill-region will know how far to kill to.

The first argument to the progn is search-forward. When search-forward finds the string, the function leaves point immediately after the last character in the target string. (In this case the target string is just one character long.) If the search is backwards, search-forward leaves point just before the first character in the target. The movement of point is a side effect.

The second and last argument to progn is the expression (point). This expression returns the value of point, which in this case will be the location to which it has been moved by search-forward. This value is returned by the progn expression and is passed to kill-region as kill-region's second argument.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1.5 Summing up zap-to-char

Now that we have seen how search-forward and progn work, we can see how the zap-to-char function works as a whole.

The first argument to kill-region is the position of the cursor when the zap-to-char command is given--the value of point at that time. Within the progn, the search function then moves point to just after the zapped-to-character and point returns the value of this location. The kill-region function puts together these two values of point, the first one as the beginning of the region and the second one as the end of the region, and removes the region.

The progn special form is necessary because the kill-region command takes two arguments; and it would fail if search-forward and point expressions were written in sequence as two additional arguments. The progn expression is a single argument to kill-region and returns the one value that kill-region needs for its second argument.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2 kill-region

The zap-to-char function uses the kill-region function. This function clips text from a region and copies that text to the kill ring, from which it may be retrieved.

The Emacs 21 version of that function uses condition-case and copy-region-as-kill, both of which we will explain. condition-case is an important special form.

In essence, the kill-region function calls condition-case, which takes three arguments. In this function, the first argument does nothing. The second argument contains the code that does the work when all goes well. The third argument contains the code that is called in the event of an error.

The Complete kill-region Definition  The function definition.
8.2.1 condition-case  Dealing with a problem.
8.2.2 delete-and-extract-region  Doing the work.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The Complete kill-region Definition

We will go through the condition-case code in a moment. First, let us look at the complete definition of kill-region, with comments added:

(defun kill-region (beg end)
  "Kill between point and mark.
The text is deleted but saved in the kill ring."
  (interactive "r")

  ;; 1. `condition-case' takes three arguments.
  ;;    If the first argument is nil, as it is here,
  ;;    information about the error signal is not
  ;;    stored for use by another function.
  (condition-case nil

      ;; 2. The second argument to `condition-case'
      ;;    tells the Lisp interpreter what to do when all goes well.

      ;;    The `delete-and-extract-region' function usually does the
      ;;    work.  If the beginning and ending of the region are both
      ;;    the same, then the variable `string' will be empty, or nil
      (let ((string (delete-and-extract-region beg end)))

        ;; `when' is an `if' clause that cannot take an `else-part'.
        ;; Emacs normally sets the value of `last-command' to the
        ;; previous command.
        ;; `kill-append' concatenates the new string and the old.
        ;; `kill-new' inserts text into a new item in the kill ring.
        (when string
          (if (eq last-command 'kill-region)
              ;; if true, prepend string
              (kill-append string (< end beg))
            (kill-new string)))
        (setq this-command 'kill-region))

    ;; 3. The third argument to `condition-case' tells the interpreter
    ;;    what to do with an error.
    ;;    The third argument has a conditions part and a body part.
    ;;    If the conditions are met (in this case,
    ;;             if text or buffer is read-only)
    ;;    then the body is executed.
    ((buffer-read-only text-read-only) ;; this is the if-part
     ;; then...
     (copy-region-as-kill beg end)
     (if kill-read-only-ok            ;; usually this variable is nil
         (message "Read only text copied to kill ring")
       ;; or else, signal an error if the buffer is read-only;
       ;; and, in any case, signal that the text is read-only.
       (signal 'text-read-only (list (current-buffer)))))))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2.1 condition-case

As we have seen earlier (see section Generate an Error Message), when the Emacs Lisp interpreter has trouble evaluating an expression, it provides you with help; in the jargon, this is called "signaling an error". Usually, the computer stops the program and shows you a message.

However, some programs undertake complicated actions. They should not simply stop on an error. In the kill-region function, the most likely error is that you will try to kill text that is read-only and cannot be removed. So the kill-region function contains code to handle this circumstance. This code, which makes up the body of the kill-region function, is inside of a condition-case special form.

The template for condition-case looks like this:


The second argument, bodyform, is straightforward. The condition-case special form causes the Lisp interpreter to evaluate the code in bodyform. If no error occurs, the special form returns the code's value and produces the side-effects, if any.

In short, the bodyform part of a condition-case expression determines what should happen when everything works correctly.

However, if an error occurs, among its other actions, the function generating the error signal will define one or more error condition names.

An error handler is the third argument to condition case. An error handler has two parts, a condition-name and a body. If the condition-name part of an error handler matches a condition name generated by an error, then the body part of the error handler is run.

As you will expect, the condition-name part of an error handler may be either a single condition name or a list of condition names.

Also, a complete condition-case expression may contain more than one error handler. When an error occurs, the first applicable handler is run.

Lastly, the first argument to the condition-case expression, the var argument, is sometimes bound to a variable that contains information about the error. However, if that argument is nil, as is the case in kill-region, that information is discarded.

In brief, in the kill-region function, the code condition-case works like this:

If no errors, run only this code
    but, if errors, run this other code.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2.2 delete-and-extract-region

A condition-case expression has two parts, a part that is evaluated in the expectation that all will go well, but which may generate an error; and a part that is evaluated when there is an error.

First, let us look at the code in kill-region that is run in the expectation that all goes well. This is the core of the function. The code looks like this:

(let ((string (delete-and-extract-region beg end)))
  (when string
    (if (eq last-command 'kill-region)
        (kill-append string (< end beg))
      (kill-new string)))
  (setq this-command 'kill-region))

It looks complicated because we have the new functions delete-and-extract-region, kill-append, and kill-new as well as the new variables, last-command and this-command.

The delete-and-extract-region function is straightforward. It is a built-in function that deletes the text in a region (a side effect) and also returns that text. This is the function that actually removes the text. (And if it cannot do that, it signals the error.)

In this let expression, the text that delete-and-extract-region returns is placed in the local variable called `string'. This is the text that is removed from the buffer. (To be more precise, the variable is set to point to the address of the extracted text; to say it is `placed in' the variable is simply a shorthand.)

If the variable `string' does point to text, that text is added to the kill ring. The variable will have a nil value if no text was removed.

The code uses when to determine whether the variable `string' points to text. A when statement is simply a programmers' convenience. A when statement is an if statement without the possibility of an else clause. In your mind, you can replace when with if and understand what goes on. That is what the Lisp interpreter does.

Technically speaking, when is a Lisp macro. A Lisp macro enables you to define new control constructs and other language features. It tells the interpreter how to compute another Lisp expression which will in turn compute the value. In this case, the `other expression' is an if expression. For more about Lisp macros, see section `Macros' in The GNU Emacs Lisp Reference Manual. The C programming language also provides macros. These are different, but also useful. We will briefly look at C macros in delete-and-extract-region: Digressing into C.

If the string has content, then another conditional expression is executed. This is an if with both a then-part and an else-part.

(if (eq last-command 'kill-region)
    (kill-append string (< end beg))
  (kill-new string)))

The then-part is evaluated if the previous command was another call to kill-region; if not, the else-part is evaluated.

last-command is a variable that comes with Emacs that we have not seen before. Normally, whenever a function is executed, Emacs sets the value of last-command to the previous command.

In this segment of the definition, the if expression checks whether the previous command was kill-region. If it was,

(kill-append string (< end beg))

concatenates a copy of the newly clipped text to the just previously clipped text in the kill ring. (If the (< end beg)) expression is true, kill-append prepends the string to the just previously clipped text. For a detailed discussion, see The kill-append function.)

If you then yank back the text, i.e., `paste' it, you get both pieces of text at once. That way, if you delete two words in a row, and then yank them back, you get both words, in their proper order, with one yank. (The (< end beg)) expression makes sure the order is correct.)

On the other hand, if the previous command is not kill-region, then the kill-new function is called, which adds the text to the kill ring as the latest item, and sets the kill-ring-yank-pointer variable to point to it.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3 delete-and-extract-region: Digressing into C

The zap-to-char command uses the delete-and-extract-region function, which in turn uses two other functions, copy-region-as-kill and del_range_1. The copy-region-as-kill function will be described in a following section; it puts a copy of the region in the kill ring so it can be yanked back. (See section copy-region-as-kill.)

The delete-and-extract-region function removes the contents of a region and you cannot get them back.

Unlike the other code discussed here, delete-and-extract-region is not written in Emacs Lisp; it is written in C and is one of the primitives of the GNU Emacs system. Since it is very simple, I will digress briefly from Lisp and describe it here.

Like many of the other Emacs primitives, delete-and-extract-region is written as an instance of a C macro, a macro being a template for code. The complete macro looks like this:

DEFUN ("delete-and-extract-region", Fdelete_and_extract_region,
       Sdelete_and_extract_region, 2, 2, 0,
  "Delete the text between START and END and return it.")
  (start, end)
     Lisp_Object start, end;
  validate_region (&start, &end);
  return del_range_1 (XINT (start), XINT (end), 1, 1);

Without going into the details of the macro writing process, let me point out that this macro starts with the word DEFUN. The word DEFUN was chosen since the code serves the same purpose as defun does in Lisp. The word DEFUN is followed by seven parts inside of parentheses:

In a C macro, the formal parameters come next, with a statement of what kind of object they are, followed by what might be called the `body' of the macro. For delete-and-extract-region the `body' consists of the following two lines:

validate_region (&start, &end);
return del_range_1 (XINT (start), XINT (end), 1, 1);

The first function, validate_region checks whether the values passed as the beginning and end of the region are the proper type and are within range. The second function, del_range_1, actually deletes the text.

del_range_1 is a complex function we will not look into. It updates the buffer and does other things.

However, it is worth looking at the two arguments passed to del_range. These are XINT (start) and XINT (end).

As far as the C language is concerned, start and end are two integers that mark the beginning and end of the region to be deleted(7).

In early versions of Emacs, these two numbers were thirty-two bits long, but the code is slowly being generalized to handle other lengths. Three of the available bits are used to specify the type of information and a fourth bit is used for handling the computer's memory; the remaining bits are used as `content'.

`XINT' is a C macro that extracts the relevant number from the longer collection of bits; the four other bits are discarded.

The command in delete-and-extract-region looks like this:

del_range_1 (XINT (start), XINT (end), 1, 1);

It deletes the region between the beginning position, start, and the ending position, end.

From the point of view of the person writing Lisp, Emacs is all very simple; but hidden underneath is a great deal of complexity to make it all work.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4 Initializing a Variable with defvar

Unlike the delete-and-extract-region function, the copy-region-as-kill function is written in Emacs Lisp. Two functions within it, kill-append and kill-new, copy a region in a buffer and save it in a variable called the kill-ring. This section describes how the kill-ring variable is created and initialized using the defvar special form.

(Again we note that the term kill-ring is a misnomer. The text that is clipped out of the buffer can be brought back; it is not a ring of corpses, but a ring of resurrectable text.)

In Emacs Lisp, a variable such as the kill-ring is created and given an initial value by using the defvar special form. The name comes from "define variable".

The defvar special form is similar to setq in that it sets the value of a variable. It is unlike setq in two ways: first, it only sets the value of the variable if the variable does not already have a value. If the variable already has a value, defvar does not override the existing value. Second, defvar has a documentation string.

(Another special form, defcustom, is designed for variables that people customize. It has more features than defvar. (See section Setting Variables with defcustom.)

Seeing the Current Value of a Variable  
8.4.1 defvar and an asterisk  An old-time convention.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Seeing the Current Value of a Variable

You can see the current value of a variable, any variable, by using the describe-variable function, which is usually invoked by typing C-h v. If you type C-h v and then kill-ring (followed by RET) when prompted, you will see what is in your current kill ring--this may be quite a lot! Conversely, if you have been doing nothing this Emacs session except read this document, you may have nothing in it. Also, you will see the documentation for kill-ring:

List of killed text sequences.
Since the kill ring is supposed to interact nicely with cut-and-paste
facilities offered by window systems, use of this variable should
interact nicely with `interprogram-cut-function' and
`interprogram-paste-function'.  The functions `kill-new',
`kill-append', and `current-kill' are supposed to implement this
interaction; you may want to use them instead of manipulating the kill
ring directly.

The kill ring is defined by a defvar in the following way:

(defvar kill-ring nil
  "List of killed text sequences.

In this variable definition, the variable is given an initial value of nil, which makes sense, since if you have saved nothing, you want nothing back if you give a yank command. The documentation string is written just like the documentation string of a defun. As with the documentation string of the defun, the first line of the documentation should be a complete sentence, since some commands, like apropos, print only the first line of documentation. Succeeding lines should not be indented; otherwise they look odd when you use C-h v (describe-variable).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.4.1 defvar and an asterisk

In the past, Emacs used the defvar special form both for internal variables that you would not expect a user to change and for variables that you do expect a user to change. Although you can still use defvar for user customizable variables, please use defcustom instead, since that special form provides a path into the Customization commands. (See section Setting Variables with defcustom.)

When you specified a variable using the defvar special form, you could distinguish a readily settable variable from others by typing an asterisk, `*', in the first column of its documentation string. For example:

(defvar shell-command-default-error-buffer nil
  "*Buffer name for `shell-command' ... error output.
... ")

This means that you could (and still can) use the edit-options command to change the value of shell-command-default-error-buffer temporarily.

However, options set using edit-options are set only for the duration of your editing session. The new values are not saved between sessions. Each time Emacs starts, it reads the original value, unless you change the value within your `.emacs' file, either by setting it manually or by using customize. See section Your `.emacs' File.

For me, the major use of the edit-options command is to suggest variables that I might want to set in my `.emacs' file. I urge you to look through the list. (See section `Editing Variable Values' in The GNU Emacs Manual.)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.5 copy-region-as-kill

The copy-region-as-kill function copies a region of text from a buffer and (via either kill-append or kill-new) saves it in the kill-ring.

If you call copy-region-as-kill immediately after a kill-region command, Emacs appends the newly copied text to the previously copied text. This means that if you yank back the text, you get it all, from both this and the previous operation. On the other hand, if some other command precedes the copy-region-as-kill, the function copies the text into a separate entry in the kill ring.

The complete copy-region-as-kill function definition  The complete function definition.
8.5.1 The Body of copy-region-as-kill  The body of copy-region-as-kill.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The complete copy-region-as-kill function definition

Here is the complete text of the version 21 copy-region-as-kill function:

(defun copy-region-as-kill (beg end)
  "Save the region as if killed, but don't kill it.
In Transient Mark mode, deactivate the mark.
If `interprogram-cut-function' is non-nil, also save
the text for a window system cut and paste."
  (interactive "r")
  (if (eq last-command 'kill-region)
      (kill-append (buffer-substring beg end) (< end beg))
    (kill-new (buffer-substring beg end)))
  (if transient-mark-mode
      (setq deactivate-mark t))

As usual, this function can be divided into its component parts:

(defun copy-region-as-kill (argument-list)
  (interactive "r")

The arguments are beg and end and the function is interactive with "r", so the two arguments must refer to the beginning and end of the region. If you have been reading though this document from the beginning, understanding these parts of a function is almost becoming routine.

The documentation is somewhat confusing unless you remember that the word `kill' has a meaning different from its usual meaning. The `Transient Mark' and interprogram-cut-function comments explain certain side-effects.

After you once set a mark, a buffer always contains a region. If you wish, you can use Transient Mark mode to highlight the region temporarily. (No one wants to highlight the region all the time, so Transient Mark mode highlights it only at appropriate times. Many people turn off Transient Mark mode, so the region is never highlighted.)

Also, a windowing system allows you to copy, cut, and paste among different programs. In the X windowing system, for example, the interprogram-cut-function function is x-select-text, which works with the windowing system's equivalent of the Emacs kill ring.

The body of the copy-region-as-kill function starts with an if clause. What this clause does is distinguish between two different situations: whether or not this command is executed immediately after a previous kill-region command. In the first case, the new region is appended to the previously copied text. Otherwise, it is inserted into the beginning of the kill ring as a separate piece of text from the previous piece.

The last two lines of the function prevent the region from lighting up if Transient Mark mode is turned on.

The body of copy-region-as-kill merits discussion in detail.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.5.1 The Body of copy-region-as-kill

The copy-region-as-kill function works in much the same way as the kill-region function (see section kill-region). Both are written so that two or more kills in a row combine their text into a single entry. If you yank back the text from the kill ring, you get it all in one piece. Moreover, kills that kill forward from the current position of the cursor are added to the end of the previously copied text and commands that copy text backwards add it to the beginning of the previously copied text. This way, the words in the text stay in the proper order.

Like kill-region, the copy-region-as-kill function makes use of the last-command variable that keeps track of the previous Emacs command.

last-command and this-command  
The kill-append function  
The kill-new function  

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

last-command and this-command

Normally, whenever a function is executed, Emacs sets the value of this-command to the function being executed (which in this case would be copy-region-as-kill). At the same time, Emacs sets the value of last-command to the previous value of this-command.

In the first part of the body of the copy-region-as-kill function, an if expression determines whether the value of last-command is kill-region. If so, the then-part of the if expression is evaluated; it uses the kill-append function to concatenate the text copied at this call to the function with the text already in the first element (the CAR) of the kill ring. On the other hand, if the value of last-command is not kill-region, then the copy-region-as-kill function attaches a new element to the kill ring using the kill-new function.

The if expression reads as follows; it uses eq, which is a function we have not yet seen:

  (if (eq last-command 'kill-region)
      ;; then-part
      (kill-append (buffer-substring beg end) (< end beg))
    ;; else-part
    (kill-new (buffer-substring beg end)))

The eq function tests whether its first argument is the same Lisp object as its second argument. The eq function is similar to the equal function in that it is used to test for equality, but differs in that it determines whether two representations are actually the same object inside the computer, but with different names. equal determines whether the structure and contents of two expressions are the same.

If the previous command was kill-region, then the Emacs Lisp interpreter calls the kill-append function

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The kill-append function

The kill-append function looks like this:

(defun kill-append (string before-p)
  "Append STRING to the end of the latest kill in the kill ring.
If BEFORE-P is non-nil, prepend STRING to the kill.
If `interprogram-cut-function' is set, pass the resulting kill to
  (kill-new (if before-p
                (concat string (car kill-ring))
              (concat (car kill-ring) string))

The kill-append function is fairly straightforward. It uses the kill-new function, which we will discuss in more detail in a moment.

First, let us look at the conditional that is one of the two arguments to kill-new. It 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 text:

(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")
     => "abcdef"

(concat "new "
        (car '("first element" "second element")))
     => "new first element"

(concat (car
        '("first element" "second element")) " modified")
     => "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 kill-append function uses the kill-new function which in turn uses the setcar function.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

The kill-new function

The kill-new function looks like this:

(defun kill-new (string &optional replace)
  "Make STRING the latest kill in the kill ring.
Set the 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."
  (and (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)
    (setq kill-ring (cons 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))))

As usual, we can look at this function in parts.

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 first two lines of code, those involving menu-bar-update-yank-menu. We will explain them below.

The critical lines are these:

  (if (and replace kill-ring)
      ;; then
      (setcar kill-ring string)
    ;; else
    (setq kill-ring (cons 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.

The kill-append function sets replace to be true; then, when the kill ring has at least one item in it, the setcar expression is executed:

(setcar kill-ring string)

The setcar function actually changes the first element of the kill-ring list to the value of string. It replaces the first element.

On the other hand, if the kill ring is empty, or replace is false, the else-part of the condition is executed:

(setq kill-ring (cons string kill-ring))
(if (> (length kill-ring) kill-ring-max)
    (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))

This expression first constructs a new version of the kill ring by prepending string to the existing kill ring as a new element. Then it executes a second if clause. This second if clause keeps the kill ring from growing too long.

Let's look at these two expressions in order.

The setq 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 kill ring.

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:

     => ("here is a clause" "another clause")

Now, we can add a new element on to this list by evaluating the following expression:

(setq example-list (cons "a third clause" example-list))

When we evaluate example-list, we find its value is:

     => ("a third clause" "here is a clause" "another clause")

Thus, the third clause was added to the list by cons.

This is exactly similar to what the setq and cons do in the function. Here is the line again:

(setq kill-ring (cons string kill-ring))

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, nthcdr and setcdr.

We looked at setcdr earlier (see section setcdr). 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 nthcdr 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.

The 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 to nil, and thereby shorten the list.

You can see this by evaluating the following three expressions in turn. First set the value of trees to (maple oak pine birch), then set the CDR of its second CDR to nil and then find the value of trees:

(setq trees '(maple oak pine birch))
     => (maple oak pine birch)

(setcdr (nthcdr 2 trees) nil)
     => nil

     => (maple oak pine)

(The value returned by the setcdr expression is nil since that is what the CDR is set to.)

To repeat, in kill-new, the nthcdr function takes the CDR a number of times that is one less than the maximum permitted size of the kill ring and 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)

The kill-ring-yank-pointer is a global variable that is set to be the kill-ring.

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. The variable is used in functions such as yank and yank-pop (see section Yanking Text Back).

Now, to return to the first two lines in the body of the function:

  (and (fboundp 'menu-bar-update-yank-menu)
       (menu-bar-update-yank-menu string (and replace (car kill-ring))))

This is an expression whose first element is the function and.

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.

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 section Generate an Error Message).

Essentially, the and is an if expression that reads like this:

if the-menu-bar-function-exists
  then execute-it

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.

Finally, 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))))

If an 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 and 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'.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.6 Review

Here is a brief summary of some recently introduced functions.

car returns the first element of a list; cdr returns the second and subsequent elements of a list.

For example:

(car '(1 2 3 4 5 6 7))
     => 1
(cdr '(1 2 3 4 5 6 7))
     => (2 3 4 5 6 7)

cons constructs a list by prepending its first argument to its second argument.

For example:

(cons 1 '(2 3 4))
     => (1 2 3 4)

Return the result of taking CDR `n' times on a list. The `rest of the rest', as it were.

For example:

(nthcdr 3 '(1 2 3 4 5 6 7))
     => (4 5 6 7)

setcar changes the first element of a list; setcdr changes the second and subsequent elements of a list.

For example:

(setq triple '(1 2 3))

(setcar triple '37)

     => (37 2 3)

(setcdr triple '("foo" "bar"))

     => (37 "foo" "bar")

Evaluate each argument in sequence and then return the value of the last.

For example:

(progn 1 2 3 4)
     => 4

Record whatever narrowing is in effect in the current buffer, if any, and restore that narrowing after evaluating the arguments.

Search for a string, and if the string is found, move point.

Takes four arguments:

  1. The string to search for.

  2. Optionally, the limit of the search.

  3. Optionally, what to do if the search fails, return nil or an error message.

  4. Optionally, how many times to repeat the search; if negative, the search goes backwards.


kill-region cuts the text between point and mark from the buffer and stores that text in the kill ring, so you can get it back by yanking.

delete-and-extract-region removes the text between point and mark from the buffer and throws it away. You cannot get it back.

copy-region-as-kill copies the text between point and mark into the kill ring, from which you can get it by yanking. The function does not cut or remove the text from the buffer.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.7 Searching Exercises

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Dohn Arms on March, 6 2005 using texi2html