Function: opascal-enclosing-indent-of
opascal-enclosing-indent-of is a byte-compiled function defined in
opascal.el.gz.
Signature
(opascal-enclosing-indent-of FROM-TOKEN)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/opascal.el.gz
(defun opascal-enclosing-indent-of (from-token)
;; Returns the indentation offset from the enclosing statement of the token.
(let ((token from-token)
(from-kind (opascal-token-kind from-token))
(stmt-start nil)
(last-token nil)
(equals-encountered nil)
(before-equals nil)
(expr-delimited nil))
(catch 'done
(opascal--scan-non-whitespace-backward token last-token
;; An open ( or [ always is an indent point.
('open-group
(throw 'done
(opascal-open-group-indent
token last-token
(if (memq from-kind opascal-binary-ops)
;; Keep binary operations aligned with the open group.
0
opascal-indent-level))))
;; Skip over any ()/[] groups.
('close-group (setq token (opascal-group-start token)))
;; Skip over any nested blocks.
((opascal--in opascal-end-block-statements)
(setq token (opascal-block-start token)))
;; An expression delimiter affects indentation depending on whether
;; the point is before or after it. Remember that we encountered one.
;; Also remember the last encountered token, since if it exists it
;; should be the actual indent point.
((opascal--in opascal-expr-delimiters)
(setq expr-delimited token stmt-start last-token))
;; With a non-delimited expression statement we indent after the
;; statement's keyword, unless we are on the delimiter itself.
((and (guard (not expr-delimited))
(opascal--in opascal-expr-statements))
(throw 'done
(cond
((memq from-kind opascal-expr-delimiters)
;; We are indenting a delimiter. Indent to the statement.
(opascal-stmt-line-indent-of token 0))
((and last-token (memq from-kind opascal-binary-ops))
;; Align binary ops with the expression.
(opascal-indent-of last-token))
(last-token
;; Indent in from the expression.
(opascal-indent-of last-token opascal-indent-level))
;; Indent in from the statement's keyword.
((opascal-indent-of token opascal-indent-level)))))
;; A delimited case statement indents the label according to
;; a special rule.
('case
(throw 'done
(if stmt-start
;; We are not actually indenting to the case statement,
;; but are within a label expression.
(opascal-stmt-line-indent-of
stmt-start opascal-indent-level)
;; Indent from the case keyword.
(opascal-stmt-line-indent-of
token opascal-case-label-indent))))
;; Body expression statements are enclosing. Indent from the
;; statement's keyword, unless we have a non-block statement following
;; it.
((opascal--in opascal-body-expr-statements)
(throw 'done (opascal-stmt-line-indent-of
(or stmt-start token) opascal-indent-level)))
;; An else statement is enclosing, but it doesn't have an expression.
;; Thus we take into account last-token instead of stmt-start.
('else
(throw 'done (opascal-stmt-line-indent-of
(or last-token token) opascal-indent-level)))
;; We indent relative to an enclosing declaration section,
;; unless this is within the a delimited expression
;; (bug#36348).
((and (guard (not expr-delimited))
(opascal--in opascal-decl-sections))
(throw 'done (opascal-indent-of (if last-token last-token token)
opascal-indent-level)))
;; In unit sections we indent right to the left.
;; Handle specially the case of "interface", which can be used
;; to start either a unit section or an interface definition.
('interface ;FIXME: Generalize to all `opascal-interface-types'?
(throw 'done
(let (token-kind)
;; Find the previous non-whitespace token.
(while (progn
(setq last-token token
token (opascal-previous-token token)
token-kind (opascal-token-kind token))
(and token
(memq token-kind
opascal-whitespace))))
;; If this token is an equals sign, "interface" is being
;; used to start an interface definition and we should
;; treat it as a composite type; otherwise, we should
;; consider it the start of a unit section.
(if (and token (eq token-kind 'equals))
(opascal-line-indent-of last-token
opascal-indent-level)
0))))
;; In unit sections we indent right to the left.
((opascal--in opascal-unit-sections)
;; Note: The `interface' case is handled specially above.
(throw 'done 0))
;; A previous terminator means we can stop.
((and (opascal--in opascal-previous-terminators) token-kind)
(throw 'done
(cond ((and last-token
(eq 'comma token-kind)
(memq from-kind opascal-binary-ops))
;; Align binary ops with the expression.
(opascal-indent-of last-token))
(last-token
;; Indent in from the expression.
(opascal-indent-of last-token opascal-indent-level))
;; No enclosing expression; use the previous statement's
;; indent.
((opascal-previous-indent-of token)))))
;; A block statement after an expression delimiter has its start
;; column as the expression statement. E.g.
;; if (a = b)
;; and (a != c) then begin
;; //...
;; end;
;; Remember it for when we encounter the expression statement start.
((guard (opascal-is-block-after-expr-statement token))
(throw 'done
(cond (last-token
(opascal-indent-of last-token opascal-indent-level))
(t (+ (opascal-section-indent-of token)
opascal-indent-level)))))
;; Assembly sections always indent in from the asm keyword.
('asm
(throw 'done (opascal-stmt-line-indent-of token opascal-indent-level)))
;; Stop at an enclosing statement and indent from it.
((opascal--in opascal-enclosing-statements)
(throw 'done (opascal-stmt-line-indent-of
(or last-token token) opascal-indent-level)))
;; A class/record declaration is also enclosing.
((guard (opascal-composite-type-start token last-token))
(throw 'done
(opascal-line-indent-of last-token opascal-indent-level)))
;; A ":" we indent relative to its line beginning. If we are in a
;; parameter list, then stop also if we hit a ";".
((and 'colon
(guard (not (or expr-delimited
(memq from-kind opascal-expr-delimiters)
equals-encountered
(eq from-kind 'equals)))))
(throw 'done
(if last-token
(opascal-indent-of last-token opascal-indent-level)
(opascal-line-indent-of token opascal-indent-level
'semicolon))))
;; If the ":" was not processed above and we have token after the "=",
;; then indent from the "=". Ignore :=, however.
((and 'colon (guard (and equals-encountered before-equals)))
(cond
;; Ignore binary ops for now. It would do, for example:
;; val := 1 + 2
;; + 3;
;; which is good, but also
;; val := Foo
;; (foo, args)
;; + 2;
;; which doesn't look right.
;; ;; Align binary ops with the before token.
;;((memq from-kind opascal-binary-ops)
;;(throw 'done (opascal-indent-of before-equals 0)))
;; Assignments (:=) we skip over to get a normal indent.
((eq (opascal-token-kind last-token) 'equals))
;; Otherwise indent in from the equals.
(t (throw 'done
(opascal-indent-of before-equals opascal-indent-level)))))
;; Remember any "=" we encounter if it has not already been processed.
('equals
(setq equals-encountered token
before-equals last-token))
)
;; We ran out of tokens. Indent to column 0.
0)))