while
loops接下来是两个while
循环。第一个while
具有一个真假测试,如果forward-sentence
的前缀参数是负数,则测试为真。这是用于向后移动的情况。该循环的主体类似于第二个while
子句的主体,但不完全相同。我们将跳过这个while
循环,专注于第二个while
循环。
第二个while
循环是用于向前移动点的。它的框架如下:
(while (> arg 0) ; 真假测试
(let varlist
(if (真假测试)
then-part
else-part
(setq arg (1- arg)))) ; while
循环递减器
该while
循环是递减型的。(See A Loop with a Decrementing Counter.) 它有一个真假测试,只要计数器(在这种情况下是变量arg
)大于零,测试就为真;并且有一个递减器,每次循环重复时从计数器的值中减去1。
如果没有给forward-sentence
提供前缀参数,这是该命令最常用的方式,那么这个while
循环将运行一次,因为arg
的值将为1。
while
循环的主体包含一个let
表达式,该表达式创建和绑定一个局部变量,并且其主体是一个if
表达式。
while
循环的主体如下:
(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)))
let
表达式创建并绑定局部变量par-end
。正如我们将看到的,此局部变量旨在为正则表达式搜索提供一个边界或限制。如果搜索未能在段落中找到适当的句子结束,它将在达到段落末尾时停止。
但首先,让我们查看par-end
如何绑定到段落末尾的值。发生的是let
将par-end
的值设置为Lisp解释器评估表达式时返回的值
(save-excursion (end-of-paragraph-text) (point))
在此表达式中,(end-of-paragraph-text)
将point移动到段落末尾,(point)
返回point的值,然后save-excursion
将point恢复到其原始位置。因此,let
将par-end
绑定到由save-excursion
表达式返回的值,即段落末尾的位置。 (end-of-paragraph-text
函数使用forward-paragraph
,我们将很快讨论。)
接下来,Emacs评估let
的主体,这是一个if
表达式,如下所示:
(if (re-search-forward sentence-end par-end t) ; if部分 (skip-chars-backward " \t\n") ; then部分 (goto-char par-end))) ; else部分
if
测试其第一个参数是否为真,如果是,则评估其then部分;否则,Emacs Lisp解释器将评估else部分。if
表达式的真假测试是正则表达式搜索。
可能看起来奇怪的是,在这里埋藏看起来像是forward-sentence
函数的实际工作,但这是Lisp中执行此类操作的常见方式。