kill-region
定义我们将逐步讲解 condition-case
代码。首先,让我们看一下 kill-region
的定义,附带注释:
(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. … "
;; • 由于顺序很重要,首先传递 point。 (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' 函数将文本插入到 kill 环中的新项目中。
;; 'when' 是没有 else 部分的 'if'。 ;; 第二个 'when' 再次检查当前字符串是否存在; ;; 此外,它还检查前一个命令是否是对 'kill-region' 的另一个调用。 ;; 如果其中一个条件为真,则将当前命令设置为 'kill-region'。
(let ((string (filter-buffer-substring beg end t))) (when string ; 如果 BEG = END,则 STRING 为 nil ;; 将该字符串添加到 kill ring 中,以某种方式。 (if (eq last-command 'kill-region)
;; − 'yank-handler' 是传递给 'kill-region' 的可选参数, ;; 告诉 'kill-append' 和 'kill-new' 函数如何处理添加到文本中的属性, ;; 例如 'bold' 或 '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)) nil)
;; • 'condition-case' 的第三个参数告诉解释器 ;; 发生错误时要做什么。
;; 第三个参数有一个条件部分和一个体部分。 ;; 如果满足条件(在这种情况下,如果文本或缓冲区是只读的) ;; 那么就执行体部分。
((buffer-read-only text-read-only) ;; 条件部分 ;; … 体部分 (copy-region-as-kill beg end)
;; 接下来,同样作为体部分的一部分,设置 this-command, ;; 这样它将在错误中被设置。 (setq this-command 'kill-region) ;; 最后,在体部分,如果可以在不发出错误的情况下将文本复制到 kill ring 中,则发送消息,否则不发送。
(if kill-read-only-ok (progn (message "Read only text copied to kill ring") nil) (barf-if-buffer-read-only) ;; 如果缓冲区不是只读的,则文本是只读的。 (signal 'text-read-only (list (current-buffer)))))))