完整的 forward-sentence 函数定义

以下是forward-sentence的代码:

(defun forward-sentence (&optional arg)
  "向前移动到下一个句子末尾。带有参数时重复。带有负数参数时,反复向后移动到句子开头。

变量 `sentence-end' 是一个正则表达式,用于匹配句子的末尾。此外,每个段落边界也会终止句子。"
  (interactive "p")
  (or arg (setq arg 1))
  (let ((opoint (point))
        (sentence-end (sentence-end)))
    (while (< arg 0)
      (let ((pos (point))
            (par-beg (save-excursion (start-of-paragraph-text) (point))))
       (if (and (re-search-backward sentence-end par-beg t)
                (or (< (match-end 0) pos)
                    (re-search-backward sentence-end par-beg t)))
           (goto-char (match-end 0))
         (goto-char par-beg)))
      (setq arg (1+ arg)))
    (while (> arg 0)
      (let ((par-end (save-excursion (end-of-paragraph-text) (point))))
       (if (re-search-forward sentence-end par-end t)
           (skip-chars-backward " \t\n")
         (goto-char par-end)))
      (setq arg (1- arg)))
    (constrain-to-field nil opoint t)))

这个函数乍一看似乎很长,最好先看它的骨架,然后再看它的实现。看骨架的方法是查看从最左列开始的表达式:

(defun forward-sentence (&optional arg)
  "documentation…"
  (interactive "p")
  (or arg (setq arg 1))
  (let ((opoint (point)) (sentence-end (sentence-end)))
    (while (< arg 0)
      (let ((pos (point))
            (par-beg (save-excursion (start-of-paragraph-text) (point))))
       向后移动时 while 循环的其余部分的主体
    (while (> arg 0)
      (let ((par-end (save-excursion (end-of-paragraph-text) (point))))
       向前移动时 while 循环的其余部分的主体
    处理表单和等价物的表达式

这看起来简单得多!函数定义由文档、一个interactive表达式、一个or表达式、一个let表达式和while循环组成。

让我们逐个查看这些部分。

我们注意到文档写得很详细且易懂。

函数有一个interactive "p"声明。这意味着处理过的前缀参数(如果有)将作为函数的参数传递。 (这将是一个数字。)如果函数未以参数形式调用(它是可选的),则参数arg将绑定为1。

当以非交互方式调用forward-sentence且没有参数时,arg绑定为nilor表达式处理这一点。它的作用是仅在arg绑定到一个值时保持arg的值不变;或者在arg绑定到nil时将arg的值设置为1。

接下来是一个let。它指定了两个局部变量opointsentence-end的值。从搜索之前的点的局部值用于constrain-to-field函数,该函数处理表单和等价物。sentence-end变量由sentence-end函数设置。