Next / Previous / Contents / Shipman's homepage

4.10. bracket-tail-field: What tail field contains the cursor?

This function tries to find which tail field contains the cursor, and returns a field-object if successful. If the cursor is not within any tail field, it returns nil.

This function assumes that field-def-list is globally defined as a list of field-def objects that describe the format of the tail fields.

ibp.el
;; - - -   b r a c k e t - t a i l - f i e l d   - - -

(defun bracket-tail-field (line)
  "Finds the tail field containing point, if any.

    [ if (line is a line-object for the line containing point)
      and (line is a type that has a tail) ->
        if point is within a tail field ->
          return a field-object describing that field
        else ->
          return nil ]
----------------------------------------------------------------"

First we open a let scope, and define some local variables:

flag

Set initially to 'scanning, this variable is changed to 'found if we found the correct field, or 'not-found if we go past the end of the line.

fieldx

Points to the current element of field-def-list.

n-fields

Points to the last+1 element of field-def-list.

field-def

Holds the current field-def object from field-def-list.

f-beg

Holds the position of the beginning of the current field.

f-end

Holds the last+1 position of the current field.

f-len

Holds the length of the current field.

ibp.el
  (let (flag                 ;; Changing this value exits the while loop
        fieldx               ;; Indexes field-def-list
        n-fields             ;; Index of last element of field-def-list
        field-def            ;; Holds each field-def object in turn
        f-beg                ;; Walks the start columns of each field
        f-end                ;; End of the current field
        f-len)               ;; Length of the current field

We set up initial values before walking the record.

ibp.el
    ;; [ flag      :=  'scanning
    ;;   fieldx    :=  0
    ;;   n-fields  :=  index of last element of field-def-list
    ;;   f-beg     :=  location of tail of line ]
    (setq flag 'scanning)
    (setq fieldx 0)
    (setq n-fields (length field-def-list))
    (setq f-beg (line-tail line))

The while loop runs until the value of flag is changed to something other than 'scanning.

ibp.el
    ;; [ if point is within a field whose length is given in
    ;;   elements fieldx through (n-fields - 1) of field-def-list ->
    ;;     flag   :=  'found
    ;;     f-beg  :=  position of the start of that field
    ;;     f-end  :=  position of the end of that field
    ;;   else ->
    ;;     flag   :=  'not-found
    ;;     f-beg  :=  anything
    ;;     f-end  :=  anything ]
    (while (eq flag 'scanning)

Here is the intended function for the body of this loop:

ibp.el
      ;; [ if fieldx >= n-fields ->
      ;;     flag  :=  'not-found
      ;;   else if point is within a field starting at f-beg and having
      ;;   length field-lengths[fieldx] ->
      ;;     flag  :=  'found
      ;;   else ->
      ;;     f-beg   :=  f-beg + field-def-list[fieldx].len
      ;;     fieldx  :=  fieldx + 1 ]

If fieldx has exceeded the number of fields in field-def-list, set flag to 'not-found, and we are done.

ibp.el
      (if (>= fieldx n-fields)
          (setq flag 'not-found)

The progn construct executes all the functions inside it, and returns the value of the last one. First we set up the values of the loop variables by extracting them from the fieldxth element of field-def-list.

ibp.el
        (progn         ;; The field exists, is point in it?
          (setq field-def (elt field-def-list fieldx))
          (setq f-len (field-def-len field-def))   ;; Get the length...
          (setq f-end (+ f-beg f-len))             ;; ...and end of next field

If the cursor is at or beyond f-beg, and it is before f-end, we have found the field containing the cursor; we set flag to 'found so the loop will terminate successfully.

ibp.el
          (if (and (>= (point) f-beg)    ;; Is f-beg <= point < f-end?
                  (< (point) f-end))
              (setq flag 'found)         ;; Yes, found it

If the cursor isn't in the current field, move f-beg to the end of the field, increment fieldx, and go around the loop again.

ibp.el
            (progn                       ;; No, keep looking
              (setq f-beg f-end)
              (setq fieldx (1+ fieldx)))))))

If the loop terminated unsuccessfully, flag will now be 'not-found, so we should return nil to signify that we couldn't find the cursor's field. If it was successful, we package up a field-object made from the current field beginning and end positions, along with the default field content from field-def-list, and return that to the caller.

ibp.el
    ;; [ if flag is 'not-found ->
    ;;     return nil
    ;;   else ->
    ;;     return a field-object whose .beg=f-beg, .end=f-end, and
    ;;     .filler=field-def-list[fieldx].filler ]
    (if (eq flag 'not-found)
        nil
      (field-object f-beg f-end
                    (field-def-filler (elt field-def-list fieldx))))))