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.