Next / Previous / Contents / Shipman's homepage

5.14. ibp-find-prev-trans: Find the last preceding line with a tail

This function searches backwards from the current line until it finds another encounter line.

ibp.el
;; - - -   i b p - f i n d - p r e v - t r a n s   - - -

(defun ibp-find-prev-trans ()
  "Search backward from the current line to find the last line with a tail.

    [ if there is at least one line with a tail preceding the line
      containing point ->
        prev  :=  an ibp-line-object representing that line
      else -> return nil ]"

Local variables include:

line

An ibp-line-object pointing to the line currently being inspected.

flag

Initially set to 'scanning, this variable is set to 'found when the search is successful, so that the loop terminates. If the search terminates because we backed up all the way to the start of the buffer, it is set to 'not-found.

ibp.el
  (let (line        ;; ibp-line-object for each line we search
        flag)       ;; Set to 'found or 'not-found to terminate the loop

The emacs save-excursion function creates a block in which we can move the cursor around arbitrarily, but its original position is restored when the block exits.

ibp.el
    (save-excursion           ;; Save point while executing this block

Set the initial value of flag, and then jump the cursor to the beginning of the current line.

ibp.el
      ;; [ flag   :=  'scanning
      ;;   point  :=  beginning of line containing point ]
      (setq flag 'scanning)
      (beginning-of-line)

This while loop searches backwards until the flag is set to 'found.

ibp.el
      ;; [ if there is a line before point that has a tail ->
      ;;     flag   :=  'found
      ;;     point  :=  the beginning of the last such line
      ;;     line   :=  an ibp-line-object representing that line
      ;;   else ->
      ;;     flag   :=  'not-found
      ;;     point  :=  anything
      ;;     line   :=  anything ]
      (while (eq flag 'scanning)

In the body of the loop, we first test to see if we are all the way back to the beginning of the buffer. If so, it's an error.

ibp.el
        ;; [ if point is at the start of the buffer ->
        ;;     flag  :=  'not-found
        ;;   else if the line before point has no tail ->
        ;;     point  :=  beginning of line before line containing point
        ;;   else ->
        ;;     flag  :=  'found
        ;;     line  :=  an ibp-line-object representing the line before
        ;;               the line containing point ]
        (if (= (point) (point-min))        ;; Beginning of buffer?
            (setq flag 'not-found)         ;; Yes, fail

The beginning-of-line function with argument 0 backs up one line.

ibp.el
          (progn
            (beginning-of-line 0)          ;; Move to previous line

See what kind of line we're sitting on now by calling Section 5.6, “ibp-analyze-line: Where are the parts of the current line?”.

ibp.el
            (setq line (ibp-analyze-line)) ;; Make ibp-line-object

If the line has a tail, we're done. This check is performed by the predicate Section 5.17, “ibp-line-has-tail-p: Does this line have a tail?”.

ibp.el
            (if (ibp-line-has-tail-p line)     ;; Does it have a tail?
                (setq flag 'found))))))    ;; Yes, succeed

That completes the while loop. We examine flag to see if the search was successful. If it has the value 'found, we return line to signify success. If flag is 'not-found, we return nil to signify failure.

ibp.el
    ;; [ if flag is 'not-found ->
    ;;     return nil
    ;;   else ->
    ;;     return line ]
    (if (eq flag 'not-found)
        nil
      line)))