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