Skip to content

Commit 83d1aed

Browse files
rrudakovbbatsov
authored andcommitted
Better handling of namespaced maps
1 parent 6db68e6 commit 83d1aed

File tree

4 files changed

+36
-18
lines changed

4 files changed

+36
-18
lines changed

CHANGELOG.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
- [#91](https://github.com/clojure-emacs/clojure-ts-mode/pull/91): Introduce `clojure-ts-cycle-keyword-string`.
1818
- [#92](https://github.com/clojure-emacs/clojure-ts-mode/pull/92): Add commands to convert between collections types.
1919
- [#93](https://github.com/clojure-emacs/clojure-ts-mode/pull/93): Introduce `clojure-ts-add-arity`.
20-
- Fix an issue where `clojure-ts-align` would hang when called within an
21-
expression containing ignored forms.
20+
- [#94](https://github.com/clojure-emacs/clojure-ts-mode/pull/94): Add indentation rules and `clojure-ts-align` support for namespaced maps.
2221

2322
## 0.3.0 (2025-04-15)
2423

clojure-ts-mode.el

+24-12
Original file line numberDiff line numberDiff line change
@@ -1410,38 +1410,45 @@ if NODE has metadata and its parent has type NODE-TYPE."
14101410
(clojure-ts--node-child-skip-metadata parent n))))
14111411

14121412
(defun clojure-ts--semantic-indent-rules ()
1413-
"Return a list of indentation rules for `treesit-simple-indent-rules'."
1413+
"Return a list of indentation rules for `treesit-simple-indent-rules'.
1414+
1415+
NOTE: All built-in matchers (such as `parent-is' etc) expect a node type
1416+
regex. Therefore, if the string map_lit is used, it will incorrectly
1417+
match both map_lit and ns_map_lit. To prevent this, more precise
1418+
regexes with anchors matching the beginning and end of the line are
1419+
used."
14141420
`((clojure
1415-
((parent-is "source") parent-bol 0)
1421+
((parent-is "^source$") parent-bol 0)
14161422
(clojure-ts--match-docstring parent 0)
14171423
;; Collections items with metadata.
14181424
;;
14191425
;; This should be before `clojure-ts--match-with-metadata', otherwise they
14201426
;; will never be matched.
1421-
(,(clojure-ts--match-collection-item-with-metadata "vec_lit") grand-parent 1)
1422-
(,(clojure-ts--match-collection-item-with-metadata "map_lit") grand-parent 1)
1423-
(,(clojure-ts--match-collection-item-with-metadata "set_lit") grand-parent 2)
1427+
(,(clojure-ts--match-collection-item-with-metadata "^vec_lit$") grand-parent 1)
1428+
(,(clojure-ts--match-collection-item-with-metadata "^map_lit$") grand-parent 1)
1429+
(,(clojure-ts--match-collection-item-with-metadata "^set_lit$") grand-parent 2)
14241430
;;
14251431
;; If we enable this rule for lists, it will break many things.
14261432
;; (,(clojure-ts--match-collection-item-with-metadata "list_lit") grand-parent 1)
14271433
;;
14281434
;; All other forms with metadata.
14291435
(clojure-ts--match-with-metadata parent 0)
14301436
;; Literal Sequences
1431-
((parent-is "vec_lit") parent 1) ;; https://guide.clojure.style/#bindings-alignment
1432-
((parent-is "map_lit") parent 1) ;; https://guide.clojure.style/#map-keys-alignment
1433-
((parent-is "set_lit") parent 2)
1434-
((parent-is "splicing_read_cond_lit") parent 4)
1435-
((parent-is "read_cond_lit") parent 3)
1436-
((parent-is "tagged_or_ctor_lit") parent 0)
1437+
((parent-is "^vec_lit$") parent 1) ;; https://guide.clojure.style/#bindings-alignment
1438+
((parent-is "^map_lit$") parent 1) ;; https://guide.clojure.style/#map-keys-alignment
1439+
((parent-is "^set_lit$") parent 2)
1440+
((parent-is "^splicing_read_cond_lit$") parent 4)
1441+
((parent-is "^read_cond_lit$") parent 3)
1442+
((parent-is "^tagged_or_ctor_lit$") parent 0)
1443+
((parent-is "^ns_map_lit$") (nth-sibling 2) 1)
14371444
;; https://guide.clojure.style/#body-indentation
14381445
(clojure-ts--match-form-body clojure-ts--anchor-parent-opening-paren 2)
14391446
;; https://guide.clojure.style/#threading-macros-alignment
14401447
(clojure-ts--match-threading-macro-arg prev-sibling 0)
14411448
;; https://guide.clojure.style/#vertically-align-fn-args
14421449
(clojure-ts--match-function-call-arg ,(clojure-ts--anchor-nth-sibling 1) 0)
14431450
;; https://guide.clojure.style/#one-space-indent
1444-
((parent-is "list_lit") parent 1))))
1451+
((parent-is "^list_lit$") parent 1))))
14451452

14461453
(defun clojure-ts--configured-indent-rules ()
14471454
"Gets the configured choice of indent rules."
@@ -1640,6 +1647,7 @@ have changed."
16401647
(query (treesit-query-compile 'clojure
16411648
(append
16421649
`(((map_lit) @map)
1650+
((ns_map_lit) @ns-map)
16431651
((list_lit
16441652
((sym_lit) @sym
16451653
(:match ,(clojure-ts-symbol-regexp clojure-ts-align-binding-forms) @sym))
@@ -1686,6 +1694,10 @@ subsequent special arguments based on block indentation rules."
16861694
(goto-char (treesit-node-start node))
16871695
(when-let* ((cur-sexp (treesit-node-first-child-for-pos node (point) t)))
16881696
(goto-char (treesit-node-start cur-sexp))
1697+
;; For namespaced maps we need to skip the namespace, which is the first
1698+
;; nested sexp.
1699+
(when (equal sexp-type 'ns-map)
1700+
(treesit-beginning-of-thing 'sexp -1 'nested))
16891701
;; For cond forms we need to skip first n + 1 nodes according to block
16901702
;; indentation rules. First node to skip is the symbol itself.
16911703
(when (equal sexp-type 'cond)

test/clojure-ts-mode-indentation-test.el

+6-1
Original file line numberDiff line numberDiff line change
@@ -604,4 +604,9 @@ b |20])"
604604

605605
"{:map \"with\"
606606
:multiple \"ignored\"
607-
#_#_:forms \"foo\"}"))
607+
#_#_:forms \"foo\"}")
608+
609+
(when-aligning-it "should support namespaced maps"
610+
"#:hello {:world true
611+
:foo \"bar\"
612+
:some-very-long \"value\"}"))

test/samples/refactoring.clj

+5-3
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@
8989

9090
[1 2 3]
9191

92-
;; TODO: Define indentation rule for `ns_map_lit`
93-
#:hello{:name "Roma"
94-
:world true}
92+
#:hello {:world true
93+
:foo "bar"
94+
:some-very-long "value"}
9595

96+
{:name "Roma"
97+
:foo true}
9698

9799
(reify
98100
java.io.FileFilter

0 commit comments

Comments
 (0)