5.2.5 insert-buffer 中的 let 表达式

在确保变量 buffer 引用的是缓冲区本身而不仅仅是缓冲区的名称后,insert-buffer 函数继续使用 let 表达式。这个表达式指定了三个局部变量 startendnewmark,并将它们绑定到初始值 nil。这些变量在 let 的其余部分中被使用,并在 let 结束之前暂时隐藏了任何同名变量的其他出现。

let 的主体包含两个 save-excursion 表达式。首先,我们将详细查看内部 save-excursion 表达式。表达式如下:

(save-excursion
  (set-buffer buffer)
  (setq start (point-min) end (point-max)))

表达式 (set-buffer buffer) 将 Emacs 的注意力从当前缓冲区切换到将要复制文本的缓冲区。在该缓冲区中,使用命令 point-minpoint-max 将变量 startend 设置为缓冲区的开始和结束。请注意,这里演示了 setq 如何能够在同一个表达式中设置两个变量。setq 的第一个参数设置为其第二个参数的值,其第三个参数设置为其第四个参数的值。

在内部 save-excursion 的主体被评估之后,save-excursion 会恢复原始缓冲区,但是 startend 仍然设置为将要复制文本的缓冲区的开始和结束的值。

外部 save-excursion 表达式如下:

(save-excursion
  (inner-save-excursion-expression
     (go-to-new-buffer-and-set-start-and-end)
  (insert-buffer-substring buffer start end)
  (setq newmark (point)))

insert-buffer-substring 函数将文本从 buffer 中的 startend 位置插入到当前缓冲区中。由于第二个缓冲区的整体位于 startend 之间,第二个缓冲区的整体被复制到你正在编辑的缓冲区中。接下来,点的值,它将位于插入文本的末尾,被记录在变量 newmark 中。

在外部 save-excursion 的主体被评估之后,点被重新定位到其原始位置。

然而,方便的是在新插入的文本的末尾放置一个标记,并将点定位在其开头。newmark 变量记录了插入文本的末尾。在 let 表达式的最后一行中,(push-mark newmark) 表达式函数将标记设置为此位置。(标记的先前位置仍然可访问;它记录在标记环上,你可以使用 C-u C-SPC 返回到它。)与此同时,点位于插入文本的开头,这是你调用插入函数之前的位置,该位置由第一个 save-excursion 保存。

整个 let 表达式如下:

(let (start end newmark)
  (save-excursion
    (save-excursion
      (set-buffer buffer)
      (setq start (point-min) end (point-max)))
    (insert-buffer-substring buffer start end)
    (setq newmark (point)))
  (push-mark newmark))

append-to-buffer 函数一样,insert-buffer 函数使用了 letsave-excursionset-buffer。此外,该函数演示了使用 or 的一种方式。所有这些函数都是我们将一遍又一遍找到并使用的构建块。