The 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如何绑定到段落末尾的值。发生的是letpar-end的值设置为Lisp解释器评估表达式时返回的值

(save-excursion (end-of-paragraph-text) (point))

在此表达式中,(end-of-paragraph-text)将point移动到段落末尾,(point)返回point的值,然后save-excursion将point恢复到其原始位置。因此,letpar-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中执行此类操作的常见方式。