4.2 简化版 beginning-of-buffer 定义

beginning-of-buffer 命令是一个很好的入门函数,因为你很可能已经熟悉它,且易于理解。作为交互式命令,beginning-of-buffer 会将光标移至缓冲区开头,并在原位置留下标记。该命令通常绑定到 M-<

本节我们会讨论该函数的简化版本,展示其最常用的工作方式。该简化版本代码可正常运行,但不包含复杂选项的相关逻辑。后续章节我们会介绍完整的函数定义。(See Complete Definition of beginning-of-buffer.)

在查看代码之前,先思考函数定义需要包含哪些内容:必须包含使函数可交互的表达式,以便通过 M-x beginning-of-bufferM-< 这类组合键调用;必须包含在缓冲区原位置留下标记的代码;还必须包含将光标移至缓冲区开头的代码。

以下是该简化版函数的完整代码:

(defun simplified-beginning-of-buffer ()
  "Move point to the beginning of the buffer;
leave mark at previous position."
  (interactive)
  (push-mark)
  (goto-char (point-min)))

与所有函数定义一样,该定义在宏 defun 之后包含五个部分:

  1. 函数名:本例中为 simplified-beginning-of-buffer
  2. 参数列表:本例中为空列表 ()
  3. 文档字符串。
  4. 交互式表达式。
  5. 函数体。

该函数定义的参数列表为空,意味着此函数不需要任何参数。(后续查看完整函数定义时,你会发现它可接收一个可选参数。)

交互式表达式告知 Emacs 该函数可交互式使用。本例中 interactive 没有参数,因为 simplified-beginning-of-buffer 不需要参数。

函数体由两行代码组成:

(push-mark)
(goto-char (point-min))

第一行是表达式 (push-mark)。当 Lisp 解释器执行该表达式时,会在光标当前位置设置一个标记。该标记的位置会保存在标记环中。

下一行是 (goto-char (point-min))。该表达式将光标跳转到缓冲区的最小光标位置,即缓冲区开头(若缓冲区已缩窄,则跳转到可访问区域的开头。See Narrowing and Widening。)

push-mark 命令会在 (goto-char (point-min)) 将光标移至缓冲区开头之前,在光标原位置设置标记。因此,你可以按需按下 C-x C-x 回到原先位置。

这就是该函数定义的全部内容!

阅读此类代码时,若遇到不熟悉的函数(如 goto-char),可使用 describe-function 命令查看其功能。使用该命令时,按下 C-h f 并输入函数名,再按 RETdescribe-function 会在 *Help* 窗口中显示函数的文档字符串。例如,goto-char 的文档如下:

Set point to POSITION, a number or marker.
Beginning of buffer is position (point-min), end is (point-max).

该函数的唯一参数为目标位置。

describe-function 的提示符会自动补全光标下方或前方的符号,你可以将光标移至函数上方或后方,直接按下 C-h f RET 以减少输入。)

end-of-buffer 函数定义与 beginning-of-buffer 写法基本一致,区别仅在于函数体中使用 (goto-char (point-max)) 替代了 (goto-char (point-min))