kill-region 的完整定义

我们稍后会详细分析 condition-case 代码。首先, 让我们来看添加了注释的 kill-region 定义:

(defun kill-region (beg end)
  "删除(\"剪切cut\")光标与标记之间的文本。
会从缓冲区中删除文本并将其保存到删除环中。
命令 \\[yank] 可从中取回文本。... "

  ;; • 由于顺序重要,优先传入光标位置。
  (interactive (list (point) (mark)))
  ;; • 无法剪切文本时给出提示。
  ;; 'unless' 是没有 then 分支的 'if'。
  (unless (and beg end)
    (error "The mark is not set now, so there is no region"))

  ;; • 'condition-case' 接收三个参数。
  ;;    若第一个参数为 nil(此处即是),
  ;;    则不会存储错误信号信息供其他函数使用。
  (condition-case nil

      ;; • 'condition-case' 的第二个参数告知
      ;;    Lisp 解释器在一切正常时执行的操作。

      ;;    以 'let' 函数开头,提取字符串并判断其是否存在。
      ;;    若存在(即 'when' 所检查的条件),则调用 'if' 函数
      ;;    判断上一条命令是否同样为 'kill-region';
      ;;    若是,则将新文本追加到原有文本之后;
      ;;    若否,则调用另一个函数 'kill-new'。

      ;;    'kill-append' 函数将新字符串与旧字符串拼接。
      ;;    'kill-new' 函数将文本插入删除环的新项中。

      ;;    'when' 是没有 else 分支的 'if'。
      ;;    第二个 'when' 再次检查当前字符串是否存在;
      ;;    此外还会检查上一条命令是否同样为 'kill-region'。
      ;;    若任一条件成立,则将当前命令设为 'kill-region'。
      (let ((string (filter-buffer-substring beg end t)))
        (when string                    ;若 BEG = END,则 STRING 为 nil
          ;; 将该字符串以某种方式添加到删除环。
          (if (eq last-command 'kill-region)
              ;;    − 'yank-handler' 是 'kill-region' 的可选参数,
              ;;    用于告知 'kill-append' 和 'kill-new' 函数
              ;;    如何处理文本附加的属性,例如粗体或斜体。
              ;;    − 'yank-handler' is an optional argument to
              (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))
        nil)

    ;;  • 'condition-case' 的第三个参数告知解释器
    ;;    出现错误时执行的操作。
    ;;    第三个参数包含条件部分与主体部分。
    ;;    若条件满足(此处为
    ;;             文本或缓冲区为只读)
    ;;    则执行主体代码。
    ;;    第三个参数的第一部分如下:
    ((buffer-read-only text-read-only) ;; 条件部分
     ;; ...  执行部分
     (copy-region-as-kill beg end)
     ;;    同样作为执行部分,设置 this-command,
     ;;    确保出错时该变量也会被正确赋值
     (setq this-command 'kill-region)
     ;;    最后,在执行部分中,
     ;;    若可将文本复制到删除环且不触发错误,则给出提示;
     ;;    否则不提示。
     (if kill-read-only-ok
         (progn (message "Read only text copied to kill ring") nil)
       (barf-if-buffer-read-only)
       ;; If the buffer isn't read-only, the text is.
       (signal 'text-read-only (list (current-buffer)))))))