Function: perl-calculate-indent

perl-calculate-indent is a byte-compiled function defined in perl-mode.el.gz.

Signature

(perl-calculate-indent)

Documentation

Return appropriate indentation for current line as Perl code.

In usual case returns an integer: the column to indent to. Returns (parse-state) if line starts inside a string.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/perl-mode.el.gz
(defun perl-calculate-indent ()
  "Return appropriate indentation for current line as Perl code.
In usual case returns an integer: the column to indent to.
Returns (parse-state) if line starts inside a string."
  (save-excursion
    (let* ((indent-point (point))
	   (case-fold-search nil)
	   (colon-line-end 0)
           prev-char
	   (state (syntax-ppss))
	   (containing-sexp (nth 1 state))
	   ;; Don't auto-indent in a quoted string or a here-document.
           (unindentable (or (nth 3 state) (eq 2 (nth 7 state))))
           (format (and (nth 3 state)
                        (char-equal (nth 3 state) ?\n))))
      (when (and (eq t (nth 3 state))
                 (save-excursion
                   (goto-char (nth 8 state))
                   (looking-back "qw[ \t]*" (- (point) 4))))
        ;; qw(...) is a list of words so the spacing is not meaningful,
        ;; and makes indentation possible (and desirable).
        (setq unindentable nil)
        (setq containing-sexp (nth 8 state)))
      (cond
       (unindentable (if format 0 'noindent))
       ((null containing-sexp)          ; Line is at top level.
        (skip-chars-forward " \t\f")
        (if (memq (following-char)
                  (if perl-indent-parens-as-block '(?\{ ?\( ?\[) '(?\{)))
            0          ; move to beginning of line if it starts a function body
          ;; indent a little if this is a continuation line
          (perl-backward-to-noncomment)
          (if (or (bobp)
                  (memq (preceding-char) '(?\; ?\}))
                  (perl--end-of-format-p))
              0 perl-continued-statement-offset)))
       ((/= (char-after containing-sexp) ?{)
        ;; line is expression, not statement:
        ;; indent to just after the surrounding open.
        (goto-char (1+ containing-sexp))
        (if (perl-hanging-paren-p)
            ;; We're indenting an arg of a call like:
            ;;    $a = foobarlongnamefun (
            ;;             arg1
            ;;             arg2
            ;;         );
            (progn
              ;; Go just before the open paren (don't rely on the
              ;; skip-syntax-backward to jump over it, because it could
              ;; have string-fence syntax instead!).
              (goto-char containing-sexp)
              (skip-syntax-backward "(") ;FIXME: Not sure if still want this.
              (condition-case nil
                  (while (save-excursion
                           (skip-syntax-backward " ") (not (bolp)))
                    (forward-sexp -1))
                (scan-error nil))
              (+ (current-column) perl-indent-level))
          (if perl-indent-continued-arguments
              (+ perl-indent-continued-arguments (current-indentation))
            (skip-chars-forward " \t")
            (current-column))))
       ;; Statement level.  Is it a continuation or a new statement?
       ((setq prev-char (perl-continuation-line-p))
        ;; This line is continuation of preceding line's statement;
        ;; indent  perl-continued-statement-offset  more than the
        ;; previous line of the statement.
        (perl-backward-to-start-of-continued-exp)
        (+ (if (or (save-excursion
                     (perl-continuation-line-p))
                   (and (eq prev-char ?\,)
                        (looking-at "[[:alnum:]_]+[ \t\n]*=>")))
               ;; If the continued line is itself a continuation
               ;; line, then align, otherwise add an offset.
               0 perl-continued-statement-offset)
           (current-column)
           (if (save-excursion (goto-char indent-point)
                               (looking-at
                                (if perl-indent-parens-as-block
                                    "[ \t]*[{([]" "[ \t]*{")))
               perl-continued-brace-offset 0)))
       (t
        ;; This line starts a new statement.
        ;; Position at last unclosed open.
        (goto-char containing-sexp)
        (or
         ;; Is line first statement after an open-brace?
         ;; If no, find that first statement and indent like it.
         (save-excursion
           (forward-char 1)
           ;; Skip over comments and labels following openbrace.
           (while (progn
                    (skip-chars-forward " \t\f\n")
                    (cond ((looking-at ";?#\\|^=\\w+")
                           (forward-comment 1) t)
                          ((looking-at "\\(\\w\\|\\s_\\)+:[^:]")
                           (setq colon-line-end (line-end-position))
                           (search-forward ":")))))
           ;; The first following code counts
           ;; if it is before the line we want to indent.
           (and (< (point) indent-point)
                (if (> colon-line-end (point))
                    (- (current-indentation) perl-label-offset)
                  (current-column))))
         ;; If no previous statement,
         ;; indent it relative to line brace is on.
         ;; For open paren in column zero, don't let statement
         ;; start there too.  If perl-indent-level is zero,
         ;; use perl-brace-offset + perl-continued-statement-offset
         ;; For open-braces not the first thing in a line,
         ;; add in perl-brace-imaginary-offset.
         (+ (if (and (bolp) (zerop perl-indent-level))
                (+ perl-brace-offset perl-continued-statement-offset)
              perl-indent-level)
            ;; Move back over whitespace before the openbrace.
            ;; If openbrace is not first nonwhite thing on the line,
            ;; add the perl-brace-imaginary-offset.
            (progn (skip-chars-backward " \t")
                   (if (bolp) 0 perl-brace-imaginary-offset))
            ;; If the openbrace is preceded by a parenthesized exp,
            ;; move to the beginning of that;
            ;; possibly a different line
            (progn
              (if (eq (preceding-char) ?\))
                  (forward-sexp -1))
              ;; Get initial indentation of the line we are on.
              (current-indentation)))))))))