]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/cl-indent.el
Merge from emacs-24; up to 2014-06-03T06:51:18Z!eliz@gnu.org
[gnu-emacs] / lisp / emacs-lisp / cl-indent.el
index 01bdfbf4bf2d872605deb70445c49c64ca20f88d..2d8a1c4c1c25b2ece44309709f2fd3638e99839d 100644 (file)
@@ -1,10 +1,10 @@
 ;;; cl-indent.el --- enhanced lisp-indent mode
 
-;; Copyright (C) 1987, 2000-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2000-2014 Free Software Foundation, Inc.
 
 ;; Author: Richard Mlynarik <mly@eddie.mit.edu>
 ;; Created: July 1987
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: lisp, tools
 ;; Package: emacs
 
@@ -27,6 +27,8 @@
 
 ;; This package supplies a single entry point, common-lisp-indent-function,
 ;; which performs indentation in the preferred style for Common Lisp code.
+;; It is also a suitable function for indenting Emacs lisp code.
+;;
 ;; To enable it:
 ;;
 ;; (setq lisp-indent-function 'common-lisp-indent-function)
@@ -154,6 +156,15 @@ is set to `defun'.")
        (looking-at "\\sw"))
     (error t)))
 
+(defun lisp-indent-find-method (symbol &optional no-compat)
+  "Find the lisp indentation function for SYMBOL.
+If NO-COMPAT is non-nil, do not retrieve indenters intended for
+the standard lisp indent package."
+  (or (and (derived-mode-p 'emacs-lisp-mode)
+           (get symbol 'common-lisp-indent-function-for-elisp))
+      (get symbol 'common-lisp-indent-function)
+      (and (not no-compat)
+           (get symbol 'lisp-indent-function))))
 
 (defun common-lisp-loop-part-indentation (indent-point state)
   "Compute the indentation of loop form constituents."
@@ -245,9 +256,17 @@ For example, the function `case' has an indent property
   * indent the first argument by 4.
   * arguments after the first should be lists, and there may be any number
     of them.  The first list element has an offset of 2, all the rest
-    have an offset of 2+1=3."
+    have an offset of 2+1=3.
+
+If the current mode is actually `emacs-lisp-mode', look for a
+`common-lisp-indent-function-for-elisp' property before looking
+at `common-lisp-indent-function' and, if set, use its value
+instead."
+  ;; FIXME: why do we need to special-case loop?
   (if (save-excursion (goto-char (elt state 1))
-                     (looking-at "([Ll][Oo][Oo][Pp]"))
+                     (looking-at (if (derived-mode-p 'emacs-lisp-mode)
+                                      "(\\(cl-\\)?[Ll][Oo][Oo][Pp]"
+                                    "([Ll][Oo][Oo][Pp]")))
       (common-lisp-loop-part-indentation indent-point state)
     (common-lisp-indent-function-1 indent-point state)))
 
@@ -291,18 +310,29 @@ For example, the function `case' has an indent property
               (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 (get tem 'common-lisp-indent-function))
-              (cond ((and (null method)
-                          (string-match ":[^:]+" function))
-                     ;; The pleblisp package feature
-                     (setq function (substring function
-                                               (1+ (match-beginning 0)))
-                           method (get (intern-soft function)
-                                       'common-lisp-indent-function)))
-                    ((and (null method))
-                     ;; backwards compatibility
-                     (setq method (get tem 'lisp-indent-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)
@@ -756,6 +786,7 @@ optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\
            (when 1)
            (with-accessors . multiple-value-bind)
            (with-condition-restarts . multiple-value-bind)
+          (with-compilation-unit (&lambda &body))
            (with-output-to-string (4 2))
            (with-slots . multiple-value-bind)
            (with-standard-io-syntax (2)))))
@@ -763,7 +794,11 @@ optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\
     (put (car el) 'common-lisp-indent-function
          (if (symbolp (cdr el))
              (get (cdr el) 'common-lisp-indent-function)
-             (car (cdr el))))))
+           (car (cdr el))))))
+
+;; In elisp, the else part of `if' is in an implicit progn, so indent
+;; it more.
+(put 'if 'common-lisp-indent-function-for-elisp 2)
 
 \f
 ;(defun foo (x)
@@ -809,4 +844,6 @@ optional\\|rest\\|key\\|allow-other-keys\\|aux\\|whole\\|body\\|environment\
 ;(put 'defclass 'common-lisp-indent-function '((&whole 2 &rest (&whole 2 &rest 1) &rest (&whole 2 &rest 1)))
 ;(put 'defgeneric 'common-lisp-indent-function 'defun)
 
+(provide 'cl-indent)
+
 ;;; cl-indent.el ends here