Function: common-lisp-indent-function-1

common-lisp-indent-function-1 is a byte-compiled function defined in cl-indent.el.gz.

Signature

(common-lisp-indent-function-1 INDENT-POINT STATE)

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/cl-indent.el.gz
(defun common-lisp-indent-function-1 (indent-point state)
  (let ((normal-indent (current-column)))
    ;; Walk up list levels until we see something
    ;;  which does special things with subforms.
    (let ((depth 0)
          ;; Path describes the position of point in terms of
          ;;  list-structure with respect to containing lists.
          ;; `foo' has a path of (0 3 1) in `((a b c (d foo) f) g)'.
          (path ())
          ;; set non-nil when somebody works out the indentation to use
          calculated
	  ;; If non-nil, this is an indentation to use
	  ;; if nothing else specifies it more firmly.
	  tentative-calculated
          ;; the position of the open-paren of the innermost containing list
          (containing-form-start (elt state 1))
          ;; the column of the above
          sexp-column)
      ;; Move to start of innermost containing list
      (goto-char containing-form-start)
      (setq sexp-column (current-column))

      ;; Look over successively less-deep containing forms
      (while (and (not calculated)
                  (< depth lisp-indent-maximum-backtracking))
        (let ((containing-sexp (point)))
          (forward-char 1)
          (parse-partial-sexp (point) indent-point 1 t)
          ;; Move to the car of the relevant containing form
          (let (tem function method tentative-defun)
            (if (not (looking-at "\\sw\\|\\s_"))
                ;; This form doesn't seem to start with a symbol
                (setq function nil method nil)
              (setq tem (point))
              (forward-sexp 1)
              (setq function (downcase (buffer-substring-no-properties
                                        tem (point))))
              (goto-char tem)
              ;; Elisp generally provides CL functionality with a CL
              ;; prefix, so if we have a special indenter for the
              ;; unprefixed version, prefer it over whatever's defined
              ;; for the cl- version.  Users can override this
              ;; heuristic by defining a
              ;; common-lisp-indent-function-for-elisp property on the
              ;; cl- version.
              (when (and (derived-mode-p 'emacs-lisp-mode)
                         (not (lisp-indent-find-method
                               (intern-soft function) t))
                         (string-match "\\`cl-" function)
                         (setf tem (intern-soft
                                    (substring function (match-end 0))))
                         (lisp-indent-find-method tem t))
                (setf function (symbol-name tem)))
              (setq tem (intern-soft function)
                    method (lisp-indent-find-method tem))
              ;; The pleblisp package feature
              (when (and (null tem)
                         (string-match ":[^:]+" function))
                (setq function (substring function (1+ (match-beginning 0)))
                      tem (intern-soft function)
                      method (lisp-indent-find-method tem))))
            (let ((n 0))
              ;; How far into the containing form is the current form?
              (if (< (point) indent-point)
                  (while (condition-case ()
                             (progn
                               (forward-sexp 1)
                               (if (>= (point) indent-point)
                                   nil
                                 (parse-partial-sexp (point)
                                                     indent-point 1 t)
                                 (setq n (1+ n))
                                 t))
                           (error nil))))
              (setq path (cons n path)))

            ;; backwards compatibility.
            (cond ((null function))
                  ((null method)
                   (when (null (cdr path))
		     ;; (package prefix was stripped off above)
		     (cond ((string-match "\\`def"
					  function)
			    (setq tentative-defun t))
			   ((string-match
                             (eval-when-compile
                              (concat "\\`\\("
                                      (regexp-opt '("with" "without" "do"))
                                      "\\)-"))
                             function)
			    (setq method '(&lambda &body))))))
                  ;; backwards compatibility.  Bletch.
                  ((eq method 'defun)
                   (setq method lisp-indent-defun-method)))

            (cond ((and (or (eq (char-after (1- containing-sexp)) ?\')
			    (and (not lisp-backquote-indentation)
				 (eq (char-after (1- containing-sexp)) ?\`)))
                        (not (eq (char-after (- containing-sexp 2)) ?\#)))
                   ;; No indentation for "'(...)" elements
                   (setq calculated (1+ sexp-column)))
                  ((when
                       (or (eq (char-after (1- containing-sexp)) ?\,)
                           (and (eq (char-after (1- containing-sexp)) ?\@)
                                (eq (char-after (- containing-sexp 2)) ?\,)))
                     ;; ",(...)" or ",@(...)"
                     (when (eq lisp-indent-backquote-substitution-mode
                               'corrected)
                       (cl-incf sexp-column -1)
                       (when (eq (char-after (1- containing-sexp)) ?\@)
                         (cl-incf sexp-column -1)))
                     (cond (lisp-indent-backquote-substitution-mode
                            (setf tentative-calculated normal-indent)
                            (setq depth lisp-indent-maximum-backtracking)
                            nil)
                           (t (setq calculated normal-indent)))))
                  ((eq (char-after (1- containing-sexp)) ?\#)
                   ;; "#(...)"
                   (setq calculated (1+ sexp-column)))
                  ((null method)
		   ;; If this looks like a call to a `def...' form,
		   ;; think about indenting it as one, but do it
		   ;; tentatively for cases like
		   ;; (flet ((defunp ()
		   ;;          nil)))
		   ;; Set both normal-indent and tentative-calculated.
		   ;; The latter ensures this value gets used
		   ;; if there are no relevant containing constructs.
		   ;; The former ensures this value gets used
		   ;; if there is a relevant containing construct
		   ;; but we are nested within the structure levels
		   ;; that it specifies indentation for.
		   (if tentative-defun
		       (setq tentative-calculated
			     (common-lisp-indent-call-method
			      function lisp-indent-defun-method
			      path state indent-point
			      sexp-column normal-indent)
			     normal-indent tentative-calculated)))
                  ((integerp method)
                   ;; convenient top-level hack.
                   ;;  (also compatible with lisp-indent-function)
                   ;; The number specifies how many `distinguished'
                   ;;  forms there are before the body starts
                   ;; Equivalent to (4 4 ... &body)
                   (setq calculated (cond ((cdr path)
                                           normal-indent)
                                          ((<= (car path) method)
                                           ;; `distinguished' form
                                           (list (+ sexp-column 4)
                                                 containing-form-start))
                                          ((= (car path) (1+ method))
                                           ;; first body form.
                                           (+ sexp-column lisp-body-indent))
                                          (t
                                           ;; other body form
                                           normal-indent))))
		  (t
		   (setq calculated
			 (common-lisp-indent-call-method
			  function method path state indent-point
			  sexp-column normal-indent)))))
          (goto-char containing-sexp)
          (unless calculated
	    (condition-case ()
		(progn (backward-up-list 1)
		       (setq depth (1+ depth)))
	      (error (setq depth lisp-indent-maximum-backtracking))))))
      (or calculated tentative-calculated))))