copy-to-buffer 的定义 ¶理解 append-to-buffer 之后,理解 copy-to-buffer 就很容易。该函数将文本复制到目标缓冲区,但不会追加内容,而是替换目标缓冲区中原有的全部文本。
copy-to-buffer 的函数体如下:
...
(interactive "BCopy to buffer: \nr")
(let ((oldbuf (current-buffer)))
(with-current-buffer (get-buffer-create buffer)
(barf-if-buffer-read-only)
(erase-buffer)
(save-excursion
(insert-buffer-substring oldbuf start end)))))
copy-to-buffer 的 interactive 表达式比 append-to-buffer 更简单。
定义接下来的语句是:
(with-current-buffer (get-buffer-create buffer) ...
首先看最内层的表达式,它会被优先执行。该表达式以 get-buffer-create buffer 开头,让计算机使用指定名称的缓冲区作为复制目标,不存在则创建。随后,with-current-buffer 函数会临时将该缓冲区设为当前缓冲区并执行其函数体,执行完毕后切回当前缓冲区13。
(这展示了另一种只切换程序操作目标、不改变用户显示窗口的方法。append-to-buffer 使用 save-excursion 与 set-buffer 实现了同样效果,而 with-current-buffer 是更新、更易用的机制。)
barf-if-buffer-read-only 函数会在缓冲区不可修改时,提示缓冲区为只读并报错。
下一行仅包含 erase-buffer 函数,该函数会清空缓冲区。
最后两行是 save-excursion 表达式,其函数体为 insert-buffer-substring。insert-buffer-substring 从你当前所在的缓冲区复制文本(你不会察觉到程序已切换缓冲区,该原始缓冲区已被记为 oldbuf)。
顺便一提,这就是 “替换(replacement)” 的含义:Emacs 先清空原有文本,再插入新文本。
框架结构上,copy-to-buffer 的函数体如下:
(let (bind-oldbuf-to-value-of-current-buffer) (with-the-buffer-you-are-copying-to (but-do-not-erase-or-copy-to-a-read-only-buffer) (erase-buffer) (save-excursion insert-substring-from-oldbuf-into-buffer)))
这相当于一次性调用 (save-excursion (set-buffer …) …),尽管其定义略有不同,感兴趣的读者可通过 describe-function 查看。