B.2 yank

在学习了current-kill之后,yank函数的代码几乎变得很简单。

yank函数不直接使用kill-ring-yank-pointer变量。它调用insert-for-yank,而insert-for-yank又调用current-kill,后者设置了kill-ring-yank-pointer变量。

代码如下:

(defun yank (&optional arg)
  "重新插入(\"粘贴\")最近一次删除的文本段。
更准确地说,重新插入最近一次删除或粘贴的文本段。将光标放在末尾,并在开头设置标记。
使用 \\[universal-argument] 作为参数时,效果相同,但将光标放在开头(标记放在末尾)。
带有参数N时,重新插入第N个最近删除的文本段。

当此命令将删除的文本插入缓冲区时,将遵循`yank-excluded-properties'和`yank-handler',如`insert-for-yank-1'的文档字符串所述,请参见。

还可以参考命令`yank-pop'(\\[yank-pop])."
  (interactive "*P")
  (setq yank-window-start (window-start))
  ;; 如果没有完全执行,使last-command指示随后的命令。
  (setq this-command t)
  (push-mark (point))
  (insert-for-yank (current-kill (cond
                                  ((listp arg) 0)
                                  ((eq arg '-) -2)
                                  (t (1- arg)))))
  (if (consp arg)
      ;; 这类似于exchange-point-and-mark,但不激活标记。
      ;; 尽管命令循环会因为插入文本而取消激活标记,但避免激活更清晰。
      (goto-char (prog1 (mark t)
                   (set-marker (mark-marker) (point) (current-buffer)))))
  ;; 如果完全执行,使this-command指示。
  (if (eq this-command t)
      (setq this-command 'yank))
  nil)

关键表达式是insert-for-yank,它插入由current-kill返回的字符串,但从中删除了一些文本属性。

然而,在到达该表达式之前,函数将yank-window-start的值设置为(window-start)表达式返回的位置,即显示当前开始的位置。yank函数还设置了this-command并推送了标记。

在它插入适当的元素之后,如果可选参数是CONS而不是数字或为空,它将光标放在插入的文本的开头,并在其末尾设置标记。

prog1函数类似于progn,但返回其第一个参数的值,而不是其最后一个参数的值。其第一个参数被强制为整数返回缓冲区的标记。可以通过将光标置于此缓冲区中的这些函数上,然后键入C-h fdescribe-function)并随后键入RET来查看这些函数的文档;默认为函数。)

函数成功时的最后部分说明了要做什么。