let*
expressionThe next line of the forward-paragraph
function begins a
let*
expression (see let*
introduced), in which Emacs binds a total of seven variables:
opoint
, fill-prefix-regexp
, parstart
,
parsep
, sp-parstart
, start
, and
found-start
. The first part of the let*
expression
looks like below:
(let* ((opoint (point)) (fill-prefix-regexp (and fill-prefix (not (equal fill-prefix "")) (not paragraph-ignore-fill-prefix) (regexp-quote fill-prefix))) ;; Remove ^ from paragraph-start and paragraph-sep if they are there. ;; These regexps shouldn't be anchored, because we look for them ;; starting at the left-margin. This allows paragraph commands to ;; work normally with indented text. ;; This hack will not find problem cases like "whatever\\|^something". (parstart (if (and (not (equal "" paragraph-start)) (equal ?^ (aref paragraph-start 0))) (substring paragraph-start 1) paragraph-start)) (parsep (if (and (not (equal "" paragraph-separate)) (equal ?^ (aref paragraph-separate 0))) (substring paragraph-separate 1) paragraph-separate)) (parsep (if fill-prefix-regexp (concat parsep "\\|" fill-prefix-regexp "[ \t]*$") parsep)) ;; This is used for searching. (sp-parstart (concat "^[ \t]*\\(?:" parstart "\\|" parsep "\\)")) start found-start) ...)
The variable parsep
appears twice, first, to remove instances
of ‘^’, and second, to handle fill prefixes.
The variable opoint
is just the value of point
. As you
can guess, it is used in a constrain-to-field
expression, just
as in forward-sentence
.
The variable fill-prefix-regexp
is set to the value returned by
evaluating the following list:
(and fill-prefix (not (equal fill-prefix "")) (not paragraph-ignore-fill-prefix) (regexp-quote fill-prefix))
This is an expression whose first element is the and
special form.
As we learned earlier (see The kill-new
function), the and
special form evaluates each of its
arguments until one of the arguments returns a value of nil
, in
which case the and
expression returns nil
; however, if
none of the arguments returns a value of nil
, the value
resulting from evaluating the last argument is returned. (Since such
a value is not nil
, it is considered true in Lisp.) In other
words, an and
expression returns a true value only if all its
arguments are true.
In this case, the variable fill-prefix-regexp
is bound to a
non-nil
value only if the following four expressions produce a
true (i.e., a non-nil
) value when they are evaluated; otherwise,
fill-prefix-regexp
is bound to nil
.
fill-prefix
When this variable is evaluated, the value of the fill prefix, if any,
is returned. If there is no fill prefix, this variable returns
nil
.
(not (equal fill-prefix "")
This expression checks whether an existing fill prefix is an empty string, that is, a string with no characters in it. An empty string is not a useful fill prefix.
(not paragraph-ignore-fill-prefix)
This expression returns nil
if the variable
paragraph-ignore-fill-prefix
has been turned on by being set to a
true value such as t
.
(regexp-quote fill-prefix)
This is the last argument to the and
special form. If all the
arguments to the and
are true, the value resulting from
evaluating this expression will be returned by the and
expression
and bound to the variable fill-prefix-regexp
,
The result of evaluating this and
expression successfully is that
fill-prefix-regexp
will be bound to the value of
fill-prefix
as modified by the regexp-quote
function.
What regexp-quote
does is read a string and return a regular
expression that will exactly match the string and match nothing else.
This means that fill-prefix-regexp
will be set to a value that
will exactly match the fill prefix if the fill prefix exists.
Otherwise, the variable will be set to nil
.
The next two local variables in the let*
expression are
designed to remove instances of ‘^’ from parstart
and
parsep
, the local variables which indicate the paragraph start
and the paragraph separator. The next expression sets parsep
again. That is to handle fill prefixes.
This is the setting that requires the definition call let*
rather than let
. The true-or-false-test for the if
depends on whether the variable fill-prefix-regexp
evaluates to
nil
or some other value.
If fill-prefix-regexp
does not have a value, Emacs evaluates
the else-part of the if
expression and binds parsep
to
its local value. (parsep
is a regular expression that matches
what separates paragraphs.)
But if fill-prefix-regexp
does have a value, Emacs evaluates
the then-part of the if
expression and binds parsep
to a
regular expression that includes the fill-prefix-regexp
as part
of the pattern.
Specifically, parsep
is set to the original value of the
paragraph separate regular expression concatenated with an alternative
expression that consists of the fill-prefix-regexp
followed by
optional whitespace to the end of the line. The whitespace is defined
by "[ \t]*$"
.) The ‘\\|’ defines this portion of the
regexp as an alternative to parsep
.
According to a comment in the code, the next local variable,
sp-parstart
, is used for searching, and then the final two,
start
and found-start
, are set to nil
.
Now we get into the body of the let*
. The first part of the body
of the let*
deals with the case when the function is given a
negative argument and is therefore moving backwards. We will skip this
section.