Info Node: (emacs-lisp-intro.info)fwd-sentence while loops
(emacs-lisp-intro.info)fwd-sentence while loops
The `while' loops
-----------------
Two `while' loops follow the `or' expression. The first `while' has
a true-or-false-test that tests true if the prefix argument for
`forward-sentence' is a negative number. This is for going backwards.
The body of this loop is similar to the body of the second `while'
clause, but it is not exactly the same. We will skip this `while' loop
and concentrate on the second `while' loop.
The second `while' loop is for moving point forward. Its skeleton
looks like this:
(while (> arg 0) ; true-or-false-test
(let VARLIST
(if (TRUE-OR-FALSE-TEST)
THEN-PART
ELSE-PART
(setq arg (1- arg)))) ; `while' loop decrementer
The `while' loop is of the decrementing kind. (Note:A Loop with a
Decrementing Counter.) It has a true-or-false-test
that tests true so long as the counter (in this case, the variable
`arg') is greater than zero; and it has a decrementer that subtracts 1
from the value of the counter every time the loop repeats.
If no prefix argument is given to `forward-sentence', which is the
most common way the command is used, this `while' loop will run once,
since the value of `arg' will be 1.
The body of the `while' loop consists of a `let' expression, which
creates and binds a local variable, and has, as its body, an `if'
expression.
The body of the `while' loop looks like this:
(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)))
The `let' expression creates and binds the local variable `par-end'.
As we shall see, this local variable is designed to provide a bound or
limit to the regular expression search. If the search fails to find a
proper sentence ending in the paragraph, it will stop on reaching the
end of the paragraph.
But first, let us examine how `par-end' is bound to the value of the
end of the paragraph. What happens is that the `let' sets the value of
`par-end' to the value returned when the Lisp interpreter evaluates the
expression
(save-excursion (end-of-paragraph-text) (point))
In this expression, `(end-of-paragraph-text)' moves point to the end of
the paragraph, `(point)' returns the value of point, and then
`save-excursion' restores point to its original position. Thus, the
`let' binds `par-end' to the value returned by the `save-excursion'
expression, which is the position of the end of the paragraph. (The
`(end-of-paragraph-text)' function uses `forward-paragraph', which we
will discuss shortly.)
Emacs next evaluates the body of the `let', which is an `if'
expression that looks like this:
(if (re-search-forward sentence-end par-end t) ; if-part
(skip-chars-backward " \t\n") ; then-part
(goto-char par-end))) ; else-part
The `if' tests whether its first argument is true and if so,
evaluates its then-part; otherwise, the Emacs Lisp interpreter
evaluates the else-part. The true-or-false-test of the `if' expression
is the regular expression search.
It may seem odd to have what looks like the `real work' of the
`forward-sentence' function buried here, but this is a common way this
kind of operation is carried out in Lisp.