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绑定为nil。or表达式处理这一点。它的作用是仅在arg绑定到一个值时保持arg的值不变;或者在arg绑定到nil时将arg的值设置为1。
接下来是一个let。它指定了两个局部变量opoint和sentence-end的值。从搜索之前的点的局部值用于constrain-to-field函数,该函数处理表单和等价物。sentence-end变量由sentence-end函数设置。