Next: , Previous: kill-region, Up: kill-region

The Complete kill-region Definition

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

     (defun kill-region (beg end)
       "Kill (\"cut\") text between point and mark.
     This deletes the text from the buffer and saves it in the kill ring.
     The command \\[yank] can retrieve it from there. ... "
       ;; • Since order matters, pass point first.
       (interactive (list (point) (mark)))
       ;; • And tell us if we cannot cut the text.
       ;; `unless' is an `if' without a then-part.
       (unless (and beg end)
         (error "The mark is not set now, so there is no region"))
       ;; • `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
           ;; • The second argument to `condition-case' tells the
           ;;    Lisp interpreter what to do when all goes well.
           ;;    It starts with a `let' function that extracts the string
           ;;    and tests whether it exists.  If so (that is what the
           ;;    `when' checks), it calls an `if' function that determines
           ;;    whether the previous command was another call to
           ;;    `kill-region'; if it was, then the new text is appended to
           ;;    the previous text; if not, then a different function,
           ;;    `kill-new', is called.
           ;;    The `kill-append' function concatenates the new string and
           ;;    the old.  The `kill-new' function inserts text into a new
           ;;    item in the kill ring.
           ;;    `when' is an `if' without an else-part.  The second `when'
           ;;    again checks whether the current string exists; in
           ;;    addition, it checks whether the previous command was
           ;;    another call to `kill-region'.  If one or the other
           ;;    condition is true, then it sets the current command to
           ;;    be `kill-region'.
           (let ((string (filter-buffer-substring beg end t)))
             (when string                    ;STRING is nil if BEG = END
               ;; Add that string to the kill ring, one way or another.
               (if (eq last-command 'kill-region)
                   ;;    − `yank-handler' is an optional argument to
                   ;;    `kill-region' that tells the `kill-append' and
                   ;;    `kill-new' functions how deal with properties
                   ;;    added to the text, such as `bold' or `italics'.
                   (kill-append string (< end beg) yank-handler)
                 (kill-new string nil yank-handler)))
             (when (or string (eq last-command 'kill-region))
               (setq this-command 'kill-region))
         ;;  • 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 are read-only)
         ;;    then the body is executed.
         ;;    The first part of the third argument is the following:
         ((buffer-read-only text-read-only) ;; the if-part
          ;; ...  the then-part
          (copy-region-as-kill beg end)
          ;;    Next, also as part of the then-part, set this-command, so
          ;;    it will be set in an error
          (setq this-command 'kill-region)
          ;;    Finally, in the then-part, send a message if you may copy
          ;;    the text to the kill ring without signally an error, but
          ;;    don't if you may not.
          (if kill-read-only-ok
              (progn (message "Read only text copied to kill ring") nil)
            ;; If the buffer isn't read-only, the text is.
            (signal 'text-read-only (list (current-buffer)))))