Add 2010 to copyright years.
[bpt/emacs.git] / lisp / emacs-lisp / cl-indent.el
index 2ed8109..e4f605d 100644 (file)
@@ -1,6 +1,7 @@
 ;;; cl-indent.el --- enhanced lisp-indent mode
 
-;; Copyright (C) 1987, 2000, 2001, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+;;   2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Richard Mlynarik <mly@eddie.mit.edu>
 ;; Created: July 1987
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,9 +21,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 ;;; Code:
 
 (defgroup lisp-indent nil
-  "Indentation in Lisp"
+  "Indentation in Lisp."
   :group 'lisp)
 
 
 (defcustom lisp-indent-maximum-backtracking 3
-  "*Maximum depth to backtrack out from a sublist for structured indentation.
-If this variable is  0, no backtracking will occur and forms such as flet
+  "Maximum depth to backtrack out from a sublist for structured indentation.
+If this variable is 0, no backtracking will occur and forms such as `flet'
 may not be correctly indented."
   :type 'integer
   :group 'lisp-indent)
 
 (defcustom lisp-tag-indentation 1
-  "*Indentation of tags relative to containing list.
+  "Indentation of tags relative to containing list.
 This variable is used by the function `lisp-indent-tagbody'."
   :type 'integer
   :group 'lisp-indent)
 
 (defcustom lisp-tag-body-indentation 3
-  "*Indentation of non-tagged lines relative to containing list.
+  "Indentation of non-tagged lines relative to containing list.
 This variable is used by the function `lisp-indent-tagbody' to indent normal
 lines (lines without tags).
 The indentation is relative to the indentation of the parenthesis enclosing
@@ -79,36 +78,36 @@ by `lisp-body-indent'."
   :group 'lisp-indent)
 
 (defcustom lisp-backquote-indentation t
-  "*Whether or not to indent backquoted lists as code.
+  "Whether or not to indent backquoted lists as code.
 If nil, indent backquoted lists as data, i.e., like quoted lists."
   :type 'boolean
   :group 'lisp-indent)
 
 
 (defcustom lisp-loop-keyword-indentation 3
-  "*Indentation of loop keywords in extended loop forms."
+  "Indentation of loop keywords in extended loop forms."
   :type 'integer
   :group 'lisp-indent)
 
 
 (defcustom lisp-loop-forms-indentation 5
-  "*Indentation of forms in extended loop forms."
+  "Indentation of forms in extended loop forms."
   :type 'integer
   :group 'lisp-indent)
 
 
 (defcustom lisp-simple-loop-indentation 3
-  "*Indentation of forms in simple loop forms."
+  "Indentation of forms in simple loop forms."
   :type 'integer
   :group 'lisp-indent)
 
 \f
-(defvar lisp-indent-error-function)
-(defvar lisp-indent-defun-method '(4 &lambda &body))
+(defvar lisp-indent-defun-method '(4 &lambda &body)
+  "Indentation for function with `common-lisp-indent-function' property `defun'.")
 
 
 (defun extended-loop-p (loop-start)
-  "True if an extended loop form starta at LOOP-START."
+  "True if an extended loop form starts at LOOP-START."
   (condition-case ()
       (save-excursion
        (goto-char loop-start)
@@ -132,16 +131,85 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
           (+ loop-indentation lisp-loop-keyword-indentation))
          (t
           (+ loop-indentation lisp-loop-forms-indentation)))))
-  
+
 
 ;;;###autoload
 (defun common-lisp-indent-function (indent-point state)
+  "Function to indent the arguments of a Lisp function call.
+This is suitable for use as the value of the variable
+`lisp-indent-function'.  INDENT-POINT is the point at which the
+indentation function is called, and STATE is the
+`parse-partial-sexp' state at that position.  Browse the
+`lisp-indent' customize group for options affecting the behavior
+of this function.
+
+If the indentation point is in a call to a Lisp function, that
+function's common-lisp-indent-function property specifies how
+this function should indent it.  Possible values for this
+property are:
+
+* defun, meaning indent according to `lisp-indent-defun-method';
+  i.e., like (4 &lambda &body), as explained below.
+
+* any other symbol, meaning a function to call.  The function should
+  take the arguments: PATH STATE INDENT-POINT SEXP-COLUMN NORMAL-INDENT.
+  PATH is a list of integers describing the position of point in terms of
+  list-structure with respect to the containing lists.  For example, in
+  ((a b c (d foo) f) g), foo has a path of (0 3 1).  In other words,
+  to reach foo take the 0th element of the outermost list, then
+  the 3rd element of the next list, and finally the 1st element.
+  STATE and INDENT-POINT are as in the arguments to
+  `common-lisp-indent-function'.  SEXP-COLUMN is the column of
+  the open parenthesis of the innermost containing list.
+  NORMAL-INDENT is the column the indentation point was
+  originally in.  This function should behave like `lisp-indent-259'.
+
+* an integer N, meaning indent the first N arguments like
+  function arguments, and any further arguments like a body.
+  This is equivalent to (4 4 ... &body).
+
+* a list.  The list element in position M specifies how to indent the Mth
+  function argument.  If there are fewer elements than function arguments,
+  the last list element applies to all remaining arguments.  The accepted
+  list elements are:
+
+  * nil, meaning the default indentation.
+
+  * an integer, specifying an explicit indentation.
+
+  * &lambda.  Indent the argument (which may be a list) by 4.
+
+  * &rest.  When used, this must be the penultimate element.  The
+    element after this one applies to all remaining arguments.
+
+  * &body.  This is equivalent to &rest lisp-body-indent, i.e., indent
+    all remaining elements by `lisp-body-indent'.
+
+  * &whole.  This must be followed by nil, an integer, or a
+    function symbol.  This indentation is applied to the
+    associated argument, and as a base indent for all remaining
+    arguments.  For example, an integer P means indent this
+    argument by P, and all remaining arguments by P, plus the
+    value specified by their associated list element.
+
+  * a symbol.  A function to call, with the 6 arguments specified above.
+
+  * a list, with elements as described above.  This applies when the
+    associated function argument is itself a list.  Each element of the list
+    specifies how to indent the associated argument.
+
+For example, the function `case' has an indent property
+\(4 &rest (&whole 2 &rest 1)), meaning:
+  * 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."
   (if (save-excursion (goto-char (elt state 1))
                      (looking-at "([Ll][Oo][Oo][Pp]"))
       (common-lisp-loop-part-indentation indent-point state)
     (common-lisp-indent-function-1 indent-point state)))
-      
-  
+
+
 (defun common-lisp-indent-function-1 (indent-point state)
   (let ((normal-indent (current-column)))
     ;; Walk up list levels until we see something
@@ -150,6 +218,7 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
           ;; Path describes the position of point in terms of
           ;;  list-structure with respect to containing lists.
           ;; `foo' has a path of (0 4 1) in `((a b c (d foo) f) g)'
+          ;; (Surely (0 3 1)?).
           (path ())
           ;; set non-nil when somebody works out the indentation to use
           calculated
@@ -216,8 +285,12 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
                     (cond ((string-match "\\`def"
                                          function)
                            (setq tentative-defun t))
-                          ((string-match "\\`\\(with\\|do\\)-"
-                                         function)
+                          ((string-match
+                             (eval-when-compile
+                              (concat "\\`\\("
+                                      (regexp-opt '("with" "without" "do"))
+                                      "\\)-"))
+                             function)
                            (setq method '(&lambda &body))))))
                   ;; backwards compatibility.  Bletch.
                   ((eq method 'defun)
@@ -300,6 +373,9 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
       (lisp-indent-259 method path state indent-point
                       sexp-column normal-indent))))
 
+;; Dynamically bound in common-lisp-indent-call-method.
+(defvar lisp-indent-error-function)
+
 (defun lisp-indent-report-bad-format (m)
   (error "%s has a badly-formed %s property: %s"
          ;; Love those free variable references!!
@@ -368,14 +444,16 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
                      ;; Too few elements in pattern.
                      (throw 'exit normal-indent)))
                 ((eq tem 'nil)
-                 (throw 'exit (list normal-indent containing-form-start)))
-          ((eq tem '&lambda)
-           (throw 'exit
-             (cond ((null p)
-                    (list (+ sexp-column 4) containing-form-start))
-                   ((null (cdr p))
-                    (+ sexp-column 1))
-                   (t normal-indent))))
+                (throw 'exit (if (consp normal-indent)
+                                 normal-indent
+                               (list normal-indent containing-form-start))))
+               ((eq tem '&lambda)
+                (throw 'exit
+                       (cond ((null p)
+                              (list (+ sexp-column 4) containing-form-start))
+                             ((null (cdr p))
+                              (+ sexp-column 1))
+                             (t normal-indent))))
                 ((integerp tem)
                  (throw 'exit
                    (if (null p)         ;not in subforms
@@ -454,7 +532,7 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
                                            (forward-char 1)
                                             (forward-sexp 3)
                                             (backward-sexp)
-                                           (looking-at ":")))
+                                           (looking-at ":\\|\\sw+")))
                       '(4 4 (&whole 4 &rest 4) &body)
                     (get 'defun 'common-lisp-indent-function))
                   path state indent-point sexp-column normal-indent))
@@ -482,8 +560,11 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
 \f
 (let ((l '((block 1)
            (case        (4 &rest (&whole 2 &rest 1)))
-           (ccase . case) (ecase . case)
-           (typecase . case) (etypecase . case) (ctypecase . case)
+           (ccase . case)
+           (ecase . case)
+           (typecase . case)
+           (etypecase . case)
+           (ctypecase . case)
            (catch 1)
            (cond        (&rest (&whole 2 &rest 1)))
            (defvar      (4 2 2))
@@ -498,7 +579,9 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
            (defun       (4 &lambda &body))
            (define-setf-method . defun)
            (define-setf-expander . defun)
-           (defmacro . defun) (defsubst . defun) (deftype . defun)
+           (defmacro . defun)
+           (defsubst . defun)
+           (deftype . defun)
           (defmethod   lisp-indent-defmethod)
            (defpackage  (4 2))
            (defstruct   ((&whole 4 &rest (&whole 2 &rest 1))
@@ -513,7 +596,8 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
            (flet        ((&whole 4 &rest (&whole 1 &lambda &body)) &body))
            (labels . flet)
            (macrolet . flet)
-           (generic-flet . flet) (generic-labels . flet)
+           (generic-flet . flet)
+           (generic-labels . flet)
            (handler-case (4 &rest (&whole 2 &lambda &body)))
            (restart-case . handler-case)
            ;; `else-body' style
@@ -524,7 +608,8 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
            (let         ((&whole 4 &rest (&whole 1 1 2)) &body))
            (let* . let)
            (compiler-let . let) ;barf
-           (handler-bind . let) (restart-bind . let)
+           (handler-bind . let)
+           (restart-bind . let)
            (locally 1)
            ;(loop         lisp-indent-loop)
            (:method (&lambda &body)) ; in `defgeneric'
@@ -544,7 +629,7 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
            (progv       (4 4 &body))
            (return 0)
            (return-from (nil &body))
-           (symbol-macrolet . multiple-value-bind)
+           (symbol-macrolet . let)
            (tagbody     lisp-indent-tagbody)
            (throw 1)
            (unless 1)
@@ -605,4 +690,5 @@ If nil, indent backquoted lists as data, i.e., like quoted lists."
 ;(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)
 
+;; arch-tag: 7914d50f-92ec-4476-93fc-0f043a380e03
 ;;; cl-indent.el ends here