This function executes the tab function once. Here is its prologue, and its Cleanroom intended function. “Point” means the cursor's position within the emacs buffer.
(defun ibp-tab-once () "Tab function for IBP data entry. [ if (line containing point does not have a tail) or (point is beyond the end of the tail) -> signal an error and terminate else if both point and the end of the line are within the same field -> buffer := buffer with filler appended from the element of ibp-field-list corresponding to that field, so as to bring the end of line to the end of that field point := point advanced past that field else -> point := point advanced past the field containing point ]"
The “buffer” referred to above is the current editing buffer.
The next step is to start a
which creates a local scope in which we can manipulate two
line will hold a
ibp-line-object representing the current line.
field will hold an
ibp-field-object representing the last field
currently existing on the current line.
(let (line ;; ibp-line-object for the line containing point field) ;; ibp-field-object for field containing end of line
We call the
ibp-analyze-line function to look
at the line and return a
tells us the position of the major parts of the current
;; [ line := ibp-line-object for the line containing point ] (setq line (ibp-analyze-line))
The tab function works only within the tail portion of
the line. If the current line has no tail, we must
report an error. For the function that tests whether a
line has a tail, see Section 5.17, “
ibp-line-has-tail-p: Does this line have
;; [ if line has a tail -> I ;; else -> error/exit ] (if (not (ibp-line-has-tail-p line)) (error "Tab is valid only on transaction lines with a tail."))
Next we need to figure out which field contains the cursor.
If the cursor is before the tail, we set
field to an
representing the head of the line.
If the cursor is in some field within the tail, we
field to an
ibp-field-object describing that field.
If the cursor is beyond the tail, that's an error.
The work of locating the field is done by Section 5.9, “
ibp-bracket-field: What field contains a
given position?”, which returns
null if the cursor is past the tail, or an
;; [ if line has a tail -> ;; if point is in the head of line -> ;; field := an ibp-field-object representing the head, with ;; nil filler ;; if point is in a tail field -> ;; field := an ibp-field-object representing that field and ;; its filler from ibp-field-list ;; if point is beyond the tail fields -> ;; error/exit ] (setq field (ibp-bracket-field line (point))) (if (null field) (error "You are beyond the fields we know."))
If the end of the line is inside
have to fill out the field from the default content. In
any case, we leave the cursor at the end of the field.
This logic is handled by Section 5.11, “
ibp-field-fill: Move to the end of a
(ibp-field-fill field line)))