From bf141b052d11bc3630ceca3cd57ce646eb6fc600 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Fri, 20 Feb 2026 17:10:55 +0200 Subject: [PATCH] [Fix #600] Accept nested list indent specs in validation clojure--valid-unquoted-indent-spec-p rejected specs with nested lists like letfn's (1 ((:defn)) nil), causing dir-locals eval to prompt unnecessarily. Now handles nested list specs and nil elements. --- CHANGELOG.md | 1 + clojure-mode.el | 9 ++++--- test/clojure-mode-indentation-test.el | 39 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24cb6fcf..9d58219f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### Bugs fixed +* [#600](https://github.com/clojure-emacs/clojure-mode/issues/600): Fix `clojure--valid-put-clojure-indent-call-p` rejecting valid indent specs with nested lists (e.g. `letfn`'s `(1 ((:defn)) nil)`). * Fix typos in `clojure-mode-extra-font-locking`: `halt-when?` -> `halt-when`, `simple-indent?` -> `simple-ident?`. * Fix `doc` and `find-doc` misplaced under `clojure.core` instead of `clojure.repl` in extra font-locking. diff --git a/clojure-mode.el b/clojure-mode.el index 27347286..85080690 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -1870,13 +1870,14 @@ This function also returns nil meaning don't specify the indentation." Validate it with respect to https://docs.cider.mx/cider/indent_spec.html e.g. (2 :form :form (1)))." - (or (integerp spec) + (or (null spec) + (integerp spec) (memq spec '(:form :defn)) (and (listp spec) - (not (null spec)) (or (integerp (car spec)) - (memq (car spec) '(:form :defn))) - (cl-every 'clojure--valid-unquoted-indent-spec-p (cdr spec))))) + (memq (car spec) '(:form :defn)) + (listp (car spec))) + (cl-every 'clojure--valid-unquoted-indent-spec-p spec)))) (defun clojure--valid-indent-spec-p (spec) "Check that the indentation SPEC (quoted if a list) is valid. diff --git a/test/clojure-mode-indentation-test.el b/test/clojure-mode-indentation-test.el index 82314644..8ecafb13 100644 --- a/test/clojure-mode-indentation-test.el +++ b/test/clojure-mode-indentation-test.el @@ -834,6 +834,45 @@ x (call-interactively #'clojure-align) (expect (string= (buffer-string) "{:a 2, :c 4}"))))) +(describe "clojure--valid-indent-spec-p" + (it "should accept integers" + (expect (clojure--valid-indent-spec-p '1) :to-be-truthy)) + + (it "should accept :defn and :form keywords" + (expect (clojure--valid-indent-spec-p ':defn) :to-be-truthy) + (expect (clojure--valid-indent-spec-p ':form) :to-be-truthy)) + + (it "should accept quoted list specs" + (expect (clojure--valid-indent-spec-p '(quote (2 :form :form (1)))) :to-be-truthy)) + + (it "should accept nested specs like letfn's ((:defn))" + (expect (clojure--valid-indent-spec-p '(quote (1 ((:defn)) nil))) :to-be-truthy)) + + (it "should accept nil as a valid spec element" + (expect (clojure--valid-indent-spec-p '(quote (1))) :to-be-truthy) + (expect (clojure--valid-indent-spec-p '(quote (:defn))) :to-be-truthy))) + +(describe "clojure--valid-put-clojure-indent-call-p" + (it "should accept letfn-style indent spec" + (expect (clojure--valid-put-clojure-indent-call-p + '(put-clojure-indent 'letfn '(1 ((:defn)) nil))) + :to-be-truthy)) + + (it "should accept simple indent specs" + (expect (clojure--valid-put-clojure-indent-call-p + '(put-clojure-indent 'defrecord '(2 :form :form (1)))) + :to-be-truthy)) + + (it "should accept keyword indent specs" + (expect (clojure--valid-put-clojure-indent-call-p + '(put-clojure-indent 'fn :defn)) + :to-be-truthy)) + + (it "should reject invalid specs" + (expect (clojure--valid-put-clojure-indent-call-p + '(put-clojure-indent 'foo "bar")) + :to-throw))) + (provide 'clojure-mode-indentation-test) ;;; clojure-mode-indentation-test.el ends here