Skip to content

Commit

Permalink
Make it possible to get uniform indentation
Browse files Browse the repository at this point in the history
While Emacs and clojure-mode have good support for "lisp-style" indentation, and
provided fine-grained customization via indent-specs, some prefer "dumb"
indentation where every single form gets the same level of indent, regardless of
whether it's a macro, whether there are arguments on the same line as the
function name, etc.

Currently this is not possible without redefining certain functions because of
hard-coded values that handle specific cases, namely the indent-spec case, and
the keyword invocation case (`(:require ...)`).

This introduces two new defcustoms, one allows completely disabling the
indent-spec handling, so the first hard-coded case is skipped, the second allows
specifically customizing the second case.

This should allow "tonsky style" formatting with

```
(setq clojure-indent-style 'always-indent
      clojure-indent-keyword-style 'always-indent
      clojure-enable-indent-specs nil)
```
  • Loading branch information
plexus authored and bbatsov committed Feb 13, 2024
1 parent c66ada8 commit e201ed6
Showing 1 changed file with 58 additions and 2 deletions.
60 changes: 58 additions & 2 deletions clojure-mode.el
Expand Up @@ -100,6 +100,8 @@

(defcustom clojure-indent-style 'always-align
"Indentation style to use for function forms and macro forms.
For forms that start with a keyword see `clojure-indent-keyword-style'.
There are two cases of interest configured by this variable.
- Case (A) is when at least one function argument is on the same
Expand Down Expand Up @@ -147,6 +149,51 @@ to indent function forms.
align-arguments))
:package-version '(clojure-mode . "5.2.0"))

(defcustom clojure-indent-keyword-style 'always-align
"Indentation style to use for forms that start with a keyword.
For function/macro forms, see `clojure-indent-style'.
There are two cases of interest configured by this variable.
- Case (A) is when at least one argument following the keyword is
on the same line as the keyword.
- Case (B) is the opposite (no arguments are on the same line as
the keyword).
The possible values for this variable are keywords indicating how
to indent keyword invocation forms.
`always-align' - Follow the same rules as `lisp-mode'. All
args are vertically aligned with the first arg in case (A),
and vertically aligned with the function name in case (B).
For instance:
(:require [foo.bar]
[bar.baz])
(:require
[foo.bar]
[bar.baz])
`always-indent' - All args are indented like a macro body.
(:require [foo.bar]
[bar.baz])
(:x
location
0)
`align-arguments' - Case (A) is indented like `lisp', and
case (B) is indented like a macro body.
(:require [foo.bar]
[bar.baz])
(:x
location
0)
"
:safe #'symbolp
:type '(choice (const :tag "Same as `lisp-mode'" 'always-align)
(const :tag "Indent like a macro body" 'always-indent)
(const :tag "Indent like a macro body unless first arg is on the same line"
'align-arguments))
:package-version '(clojure-mode . "5.14.0"))

(defcustom clojure-use-backtracking-indent t
"When non-nil, enable context sensitive indentation."
:type 'boolean
Expand Down Expand Up @@ -1686,7 +1733,8 @@ This function also returns nil meaning don't specify the indentation."
(1+ (current-column))
;; Function or macro call.
(forward-char 1)
(let ((method (clojure--find-indent-spec))
(let ((method (and clojure-enable-indent-specs
(clojure--find-indent-spec)))
(last-sexp calculate-lisp-indent-last-sexp)
(containing-form-column (1- (current-column))))
(pcase method
Expand Down Expand Up @@ -1723,7 +1771,7 @@ This function also returns nil meaning don't specify the indentation."
(cond
;; Preserve useful alignment of :require (and friends) in `ns' forms.
((and function (string-match "^:" function))
(clojure--normal-indent last-sexp 'always-align))
(clojure--normal-indent last-sexp clojure-indent-keyword-style))
;; This should be identical to the :defn above.
((and function
(string-match "\\`\\(?:\\S +/\\)?\\(def[a-z]*\\|with-\\)"
Expand Down Expand Up @@ -1802,6 +1850,14 @@ Requires the macro's NAME and a VALUE."
(put-clojure-indent x 'defun))
value))

(defcustom clojure-enable-indent-specs t
"Honor indent specs, either set via metadata on the
function/macro, or via `define-clojure-indent'. Set this to `nil'
to get uniform formatting of all forms."
:type 'boolean
:safe #'booleanp
:package-version '(clojure-mode . "5.14.0"))

(defcustom clojure-defun-indents nil
"List of additional symbols with defun-style indentation in Clojure.
Expand Down

0 comments on commit e201ed6

Please sign in to comment.