eintr: Complete forward-sentence
Complete ‘forward-sentence’ function definition
-----------------------------------------------
Here is the code for ‘forward-sentence’:
(defun forward-sentence (&optional arg)
"Move forward to next end of sentence. With argument, repeat.
With negative argument, move backward repeatedly to start of sentence.
The variable `sentence-end' is a regular expression that matches ends of
sentences. Also, every paragraph boundary terminates sentences as well."
(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)))
The function looks long at first sight and it is best to look at its
skeleton first, and then its muscle. The way to see the skeleton is to
look at the expressions that start in the left-most columns:
(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))))
REST-OF-BODY-OF-WHILE-LOOP-WHEN-GOING-BACKWARDS
(while (> arg 0)
(let ((par-end (save-excursion (end-of-paragraph-text) (point))))
REST-OF-BODY-OF-WHILE-LOOP-WHEN-GOING-FORWARDS
HANDLE-FORMS-AND-EQUIVALENT
This looks much simpler! The function definition consists of
documentation, an ‘interactive’ expression, an ‘or’ expression, a ‘let’
expression, and ‘while’ loops.
Let’s look at each of these parts in turn.
We note that the documentation is thorough and understandable.
The function has an ‘interactive "p"’ declaration. This means that
the processed prefix argument, if any, is passed to the function as its
argument. (This will be a number.) If the function is not passed an
argument (it is optional) then the argument ‘arg’ will be bound to 1.
When ‘forward-sentence’ is called non-interactively without an
argument, ‘arg’ is bound to ‘nil’. The ‘or’ expression handles this.
What it does is either leave the value of ‘arg’ as it is, but only if
‘arg’ is bound to a value; or it sets the value of ‘arg’ to 1, in the
case when ‘arg’ is bound to ‘nil’.
Next is a ‘let’. That specifies the values of two local variables,
‘opoint’ and ‘sentence-end’. The local value of point, from before the
search, is used in the ‘constrain-to-field’ function which handles forms
and equivalents. The ‘sentence-end’ variable is set by the
‘sentence-end’ function.