9595 " Face used to font-lock interop method names (camelCase)."
9696 :package-version '(clojure-mode . " 3.0.0" ))
9797
98- (defcustom clojure-defun-style-default-indent nil
99- " When non-nil, use default indenting for functions and macros.
100- Otherwise check `define-clojure-indent' and `put-clojure-indent' ."
101- :type 'boolean
102- :safe 'booleanp )
98+ (defcustom clojure-indent-style :always-align
99+ " Indentation style to use for function forms and macro forms.
100+ There are two cases of interest configured by this variable.
101+
102+ - Case (A) is when at least one function argument is on the same
103+ line as the function name.
104+ - Case (B) is the opposite (no arguments are on the same line as
105+ the function name). Note that the body of macros is not
106+ affected by this variable, it is always indented by
107+ `lisp-body-indent' (default 2) spaces.
108+
109+ Note that this variable configures the indentation of function
110+ forms (and function-like macros), it does not affect macros that
111+ already use special indentation rules.
112+
113+ The possible values for this variable are keywords indicating how
114+ to indent function forms.
115+
116+ `:always-align' - Follow the same rules as `lisp-mode' . All
117+ args are vertically aligned with the first arg in case (A),
118+ and vertically aligned with the function name in case (B).
119+ For instance:
120+ (reduce merge
121+ some-coll)
122+ (reduce
123+ merge
124+ some-coll)
125+
126+ `:always-indent' - All args are indented like a macro body.
127+ (reduce merge
128+ some-coll)
129+ (reduce
130+ merge
131+ some-coll)
132+
133+ `:align-arguments' - Case (A) is indented like `lisp' , and
134+ case (B) is indented like a macro body.
135+ (reduce merge
136+ some-coll)
137+ (reduce
138+ merge
139+ some-coll)"
140+ :type '(choice (const :tag " Same as `lisp-mode' " lisp)
141+ (const :tag " Indent like a macro body" always-body)
142+ (const :tag " Indent like a macro body unless first arg is on the same line"
143+ body-unless-same-line))
144+ :package-version '(clojure-mode . " 5.2.0" ))
145+
146+ (define-obsolete-variable-alias 'clojure-defun-style-default-indent
147+ 'clojure-indent-style " 5.2.0" )
103148
104149(defcustom clojure-use-backtracking-indent t
105150 " When non-nil, enable context sensitive indentation."
@@ -950,25 +995,47 @@ spec."
950995 (let ((function (thing-at-point 'symbol )))
951996 (clojure--get-indent-method function))))
952997
953- (defun clojure--normal-indent (last-sexp )
998+ (defun clojure--normal-indent (last-sexp indent-mode )
954999 " Return the normal indentation column for a sexp.
955- LAST-SEXP is the start of the previous sexp."
1000+ Point should be after the open paren of the _enclosing_ sexp, and
1001+ LAST-SEXP is the start of the previous sexp (immediately before
1002+ the sexp being indented). INDENT-MODE is any of the values
1003+ accepted by `clojure-indent-style' ."
9561004 (goto-char last-sexp)
9571005 (forward-sexp 1 )
9581006 (clojure-backward-logical-sexp 1 )
9591007 (let ((last-sexp-start nil ))
960- (unless (ignore-errors
961- (while (string-match
962- " [^[:blank:]]"
963- (buffer-substring (line-beginning-position ) (point )))
964- (setq last-sexp-start (prog1 (point )
965- (forward-sexp -1 ))))
966- t )
967- ; ; If the last sexp was on the same line.
968- (when (and last-sexp-start
969- (> (line-end-position ) last-sexp-start))
970- (goto-char last-sexp-start)))
971- (current-column )))
1008+ (if (ignore-errors
1009+ ; ; `backward-sexp' until we reach the start of a sexp that is the
1010+ ; ; first of its line (the start of the enclosing sexp).
1011+ (while (string-match
1012+ " [^[:blank:]]"
1013+ (buffer-substring (line-beginning-position ) (point )))
1014+ (setq last-sexp-start (prog1 (point )
1015+ (forward-sexp -1 ))))
1016+ t )
1017+ ; ; Here we have found an arg before the arg we're indenting which is at
1018+ ; ; the start of a line. Every mode simply aligns on this case.
1019+ (current-column )
1020+ ; ; Here we have reached the start of the enclosing sexp (point is now at
1021+ ; ; the function name), so the behaviour depends on INDENT-MODE and on
1022+ ; ; whether there's also an argument on this line (case A or B).
1023+ (let ((case-a ; The meaning of case-a is explained in `clojure-indent-style' .
1024+ (and last-sexp-start
1025+ (< last-sexp-start (line-end-position )))))
1026+ (cond
1027+ ; ; For compatibility with the old `clojure-defun-style-default-indent' , any
1028+ ; ; value other than these 3 is equivalent to `always-body' .
1029+ ((not (memq indent-mode '(:always-align :align-arguments nil )))
1030+ (+ (current-column ) lisp-body-indent -1 ))
1031+ ; ; There's an arg after the function name, so align with it.
1032+ (case-a (goto-char last-sexp-start)
1033+ (current-column ))
1034+ ; ; Not same line.
1035+ ((eq indent-mode :align-arguments )
1036+ (+ (current-column ) lisp-body-indent -1 ))
1037+ ; ; Finally, just align with the function name.
1038+ (t (current-column )))))))
9721039
9731040(defun clojure--not-function-form-p ()
9741041 " Non-nil if form at point doesn't represent a function call."
@@ -982,6 +1049,9 @@ LAST-SEXP is the start of the previous sexp."
9821049 ; ; Car of form is not a symbol.
9831050 (not (looking-at " .\\ (?:\\ sw\\ |\\ s_\\ )" ))))
9841051
1052+ ; ; Check the general context, and provide indentation for data structures and
1053+ ; ; special macros. If current form is a function (or non-special macro),
1054+ ; ; delegate indentation to `clojure--normal-indent' .
9851055(defun clojure-indent-function (indent-point state )
9861056 " When indenting a line within a function call, indent properly.
9871057
@@ -1013,6 +1083,7 @@ This function also returns nil meaning don't specify the indentation."
10131083 ; ; Function or macro call.
10141084 (forward-char 1 )
10151085 (let ((method (clojure--find-indent-spec))
1086+ (last-sexp calculate-lisp-indent-last-sexp)
10161087 (containing-form-column (1- (current-column ))))
10171088 (pcase method
10181089 ((or (pred integerp) `(, method ))
@@ -1028,26 +1099,35 @@ This function also returns nil meaning don't specify the indentation."
10281099 ; ; indentation as if there were an extra sexp at point.
10291100 (scan-error (cl-incf pos)))
10301101 (cond
1102+ ; ; The first non-special arg. Rigidly reduce indentation.
10311103 ((= pos (1+ method))
10321104 (+ lisp-body-indent containing-form-column))
1105+ ; ; Further non-special args, align with the arg above.
10331106 ((> pos (1+ method))
1034- (clojure--normal-indent calculate-lisp-indent-last-sexp))
1107+ (clojure--normal-indent last-sexp :always-align ))
1108+ ; ; Special arg. Rigidly indent with a large indentation.
10351109 (t
10361110 (+ (* 2 lisp-body-indent) containing-form-column)))))
10371111 (`:defn
10381112 (+ lisp-body-indent containing-form-column))
10391113 ((pred functionp)
10401114 (funcall method indent-point state))
1041- ((and `nil
1042- (guard (let ((function (thing-at-point 'sexp )))
1043- (or (and clojure-defun-style-default-indent
1044- ; ; largely to preserve useful alignment of :require, etc in ns
1045- (not (string-match " ^:" function)))
1046- (and (string-match " \\ `\\ (?:\\ S +/\\ )?\\ (def[a-z]*\\ |with-\\ )"
1047- function)
1048- (not (string-match " \\ `default" (match-string 1 function))))))))
1049- (+ lisp-body-indent containing-form-column))
1050- (_ (clojure--normal-indent calculate-lisp-indent-last-sexp))))))
1115+ ; ; No indent spec, do the default.
1116+ (`nil
1117+ (let ((function (thing-at-point 'symbol )))
1118+ (cond
1119+ ; ; Preserve useful alignment of :require (and friends) in `ns' forms.
1120+ ((and function (string-match " ^:" function))
1121+ (clojure--normal-indent last-sexp :align-arguments ))
1122+ ; ; This is should be identical to the :defn above.
1123+ ((and function
1124+ (string-match " \\ `\\ (?:\\ S +/\\ )?\\ (def[a-z]*\\ |with-\\ )"
1125+ function)
1126+ (not (string-match " \\ `default" (match-string 1 function))))
1127+ (+ lisp-body-indent containing-form-column))
1128+ ; ; Finally, nothing special here, just respect the user's
1129+ ; ; preference.
1130+ (t (clojure--normal-indent last-sexp clojure-indent-style)))))))))
10511131
10521132; ;; Setting indentation
10531133(defun put-clojure-indent (sym indent )
0 commit comments