yank-pop
在理解了 yank
和 current-kill
之后,你就知道如何处理 yank-pop
函数了。为了节省空间,下面是省略了文档的函数定义:
(defun yank-pop (&optional arg) "…" (interactive "*p") (if (not (eq last-command 'yank)) (error "上一个命令不是 yank"))
(setq this-command 'yank) (unless arg (setq arg 1)) (let ((inhibit-read-only t) (before (< (point) (mark t))))
(if before (funcall (or yank-undo-function 'delete-region) (point) (mark t)) (funcall (or yank-undo-function 'delete-region) (mark t) (point))) (setq yank-undo-function nil)
(set-marker (mark-marker) (point) (current-buffer)) (insert-for-yank (current-kill arg)) ;; 如果可能,将窗口的起始位置设置回 yank 命令之前的位置。 (set-window-start (selected-window) yank-window-start t)
(if before ;; 这类似于 exchange-point-and-mark, ;; 但不激活标记。 ;; 即使命令循环会因为我们插入文本而取消激活标记, ;; 这样做更干净,因为我们避免了激活。 (goto-char (prog1 (mark t) (set-marker (mark-marker) (point) (current-buffer)))))) nil)
这个函数是交互式的,带有一个小的 ‘p’,因此前缀参数会被处理并传递给函数。该命令只能在先前的 yank 后使用;否则会发送错误消息。此检查使用变量 last-command
,该变量由 yank
设置,并在其他地方进行了讨论。(See copy-region-as-kill
。)
let
子句将变量 before
设置为 true 或 false,具体取决于 point 是否在 mark 之前,然后删除 point 和 mark 之间的区域。这是由前一个 yank 命令刚插入的区域,也就是将被替换的文本。
funcall
将其第一个参数作为函数调用,并将其余参数传递给它。第一个参数是 or
表达式返回的内容。其余两个参数是由前一个 yank
命令设置的 point 和 mark 的位置。
还有更多内容,但这是最难的部分。