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)))