Skip to content

Commit 59decee

Browse files
committed
Extend clojure--normal-indent to allow 3 indent styles
Also move a bit more logic from clojure-indent-function to clojure--normal-indent, and better define the role of each of these two functions.
1 parent 6fbc706 commit 59decee

File tree

1 file changed

+55
-23
lines changed

1 file changed

+55
-23
lines changed

clojure-mode.el

+55-23
Original file line numberDiff line numberDiff line change
@@ -950,25 +950,47 @@ spec."
950950
(let ((function (thing-at-point 'symbol)))
951951
(clojure--get-indent-method function))))
952952

953-
(defun clojure--normal-indent (last-sexp)
953+
(defun clojure--normal-indent (last-sexp indent-mode)
954954
"Return the normal indentation column for a sexp.
955-
LAST-SEXP is the start of the previous sexp."
955+
Point should be after the open paren of the _enclosing_ sexp, and
956+
LAST-SEXP is the start of the previous sexp (immediately before
957+
the sexp being indented). INDENT-MODE is any of the values
958+
accepted by `clojure-indent-style'."
956959
(goto-char last-sexp)
957960
(forward-sexp 1)
958961
(clojure-backward-logical-sexp 1)
959962
(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)))
963+
(if (ignore-errors
964+
;; `backward-sexp' until we reach the start of a sexp that is the
965+
;; first of its line (the start of the enclosing sexp).
966+
(while (string-match
967+
"[^[:blank:]]"
968+
(buffer-substring (line-beginning-position) (point)))
969+
(setq last-sexp-start (prog1 (point)
970+
(forward-sexp -1))))
971+
t)
972+
;; Here we have found an arg before the arg we're indenting which is at
973+
;; the start of a line. Every mode simply aligns on this case.
974+
(current-column)
975+
;; Here we have reached the start of the enclosing sexp (point is now at
976+
;; the function name), so the behaviour depends on INDENT-MODE and on
977+
;; whether there's also an argument on this line (case A or B).
978+
(let ((case-a ; The meaning of case-a is explained in `clojure-indent-style'.
979+
(and last-sexp-start
980+
(< last-sexp-start (line-end-position)))))
981+
(cond
982+
;; For compatibility with the old `clojure-defun-style-default-indent', any
983+
;; value other than these 3 is equivalent to `always-body'.
984+
((not (memq indent-mode '(:lisp :body-unless-same-line nil)))
985+
(+ (current-column) lisp-body-indent -1))
986+
;; There's an arg after the function name, so align with it.
987+
(case-a (goto-char last-sexp-start)
988+
(current-column))
989+
;; Not same line.
990+
((eq indent-mode :body-unless-same-line)
991+
(+ (current-column) lisp-body-indent -1))
992+
;; Finally, just align with the function name.
993+
(t (current-column)))))))
972994

973995
(defun clojure--not-function-form-p ()
974996
"Non-nil if form at point doesn't represent a function call."
@@ -982,6 +1004,9 @@ LAST-SEXP is the start of the previous sexp."
9821004
;; Car of form is not a symbol.
9831005
(not (looking-at ".\\(?:\\sw\\|\\s_\\)"))))
9841006

1007+
;; Check the general context, and provide indentation for data structures and
1008+
;; special macros. If current form is a function (or non-special macro),
1009+
;; delegate indentation to `clojure--normal-indent'.
9851010
(defun clojure-indent-function (indent-point state)
9861011
"When indenting a line within a function call, indent properly.
9871012
@@ -1013,6 +1038,7 @@ This function also returns nil meaning don't specify the indentation."
10131038
;; Function or macro call.
10141039
(forward-char 1)
10151040
(let ((method (clojure--find-indent-spec))
1041+
(last-sexp calculate-lisp-indent-last-sexp)
10161042
(containing-form-column (1- (current-column))))
10171043
(pcase method
10181044
((or (pred integerp) `(,method))
@@ -1028,10 +1054,13 @@ This function also returns nil meaning don't specify the indentation."
10281054
;; indentation as if there were an extra sexp at point.
10291055
(scan-error (cl-incf pos)))
10301056
(cond
1057+
;; The first non-special arg. Rigidly reduce indentation.
10311058
((= pos (1+ method))
10321059
(+ lisp-body-indent containing-form-column))
1060+
;; Further non-special args, align with the arg above.
10331061
((> pos (1+ method))
1034-
(clojure--normal-indent calculate-lisp-indent-last-sexp))
1062+
(clojure--normal-indent last-sexp :lisp))
1063+
;; Special arg. Rigidly indent with a large indentation.
10351064
(t
10361065
(+ (* 2 lisp-body-indent) containing-form-column)))))
10371066
(`:defn
@@ -1044,15 +1073,18 @@ This function also returns nil meaning don't specify the indentation."
10441073
(cond
10451074
;; largely to preserve useful alignment of :require, etc in ns
10461075
((and function (string-match "^:" function))
1047-
(let ((clojure-defun-style-default-indent nil))
1048-
(clojure--normal-indent calculate-lisp-indent-last-sexp)))
1049-
((or clojure-defun-style-default-indent
1050-
(and function
1051-
(string-match "\\`\\(?:\\S +/\\)?\\(def[a-z]*\\|with-\\)"
1052-
function)
1053-
(not (string-match "\\`default" (match-string 1 function)))))
1076+
(clojure--normal-indent last-sexp :body-unless-same-line))
1077+
;; This is should be identical to the :defn above.
1078+
((and function
1079+
(string-match "\\`\\(?:\\S +/\\)?\\(def[a-z]*\\|with-\\)"
1080+
function)
1081+
(not (string-match "\\`default" (match-string 1 function))))
10541082
(+ lisp-body-indent containing-form-column))
1055-
(t (clojure--normal-indent calculate-lisp-indent-last-sexp)))))))))
1083+
;; Finally, nothing special here, just respect the user's
1084+
;; preference.
1085+
(t (clojure--normal-indent last-sexp (if clojure-defun-style-default-indent
1086+
:always-body
1087+
:lisp))))))))))
10561088

10571089
;;; Setting indentation
10581090
(defun put-clojure-indent (sym indent)

0 commit comments

Comments
 (0)