Skip to content

Commit aab92b9

Browse files
committed
Fix indentation of function calls when treesit node is nil
Previously indenting 2 spaces for function calls only worked when we were indenting where some node was after the point. Indentation fell back to picking up the "parent 'list_lit' then indent 1 rule" because node can sometime be nil and there was nothing to capture in the query. Queries cannot bind nil to a captured var, simply not possible. We don't really care what the node at point is, instead we just want to know the parent of wherever the point is. A function is used to make the match instead of a query. The function can ignore node and focus only on the parent node. This will most likely be an important strategy in semantic indentation.
1 parent bf4a070 commit aab92b9

File tree

2 files changed

+82
-13
lines changed

2 files changed

+82
-13
lines changed

Diff for: clojure-ts-mode.el

+26-13
Original file line numberDiff line numberDiff line change
@@ -335,19 +335,6 @@
335335
'((derefing_lit
336336
marker: "@" @font-lock-warning-face))))
337337

338-
(defvar clojure-ts--fixed-indent-rules
339-
;; This is in contrast to semantic rules
340-
;; fixed-indent-rules come from https://tonsky.me/blog/clojurefmt/
341-
'((clojure
342-
((parent-is "source") parent-bol 0)
343-
;; Lists beginning with a symbol indent 2 spaces (usually a function/macro call)
344-
((query "(list_lit . (sym_lit) _* @indent)") parent 2)
345-
((or (parent-is "vec_lit")
346-
(parent-is "map_lit")
347-
(parent-is "list_lit")) parent 1)
348-
((parent-is "set_lit") parent 2))))
349-
350-
351338
;; Node predicates
352339

353340
(defun clojure-ts--list-node-p (node)
@@ -358,6 +345,10 @@
358345
"Return non-nil if NODE is a Clojure symbol."
359346
(string-equal "sym_lit" (treesit-node-type node)))
360347

348+
(defun clojure-ts--keyword-node-p (node)
349+
"Return non-nil if NODE is a Clojure keyword."
350+
(string-equal "kwd_lit" (treesit-node-type node)))
351+
361352
(defun clojure-ts--named-node-text (node)
362353
"Gets the name of a symbol or keyword NODE.
363354
This does not include the NODE's namespace."
@@ -479,6 +470,28 @@ Includes a dispatch value when applicable (defmethods)."
479470
By default `treesit-defun-name-function' is used to extract definition names.
480471
See `clojure-ts--standard-definition-node-name' for the implementation used.")
481472

473+
(defvar clojure-ts--fixed-indent-rules
474+
;; This is in contrast to semantic
475+
;; fixed-indent-rules come from https://tonsky.me/blog/clojurefmt/
476+
`((clojure
477+
((parent-is "source") parent-bol 0)
478+
;; ((query "(list_lit . [(sym_lit) (kwd_lit)] _* @node)") parent 2)
479+
;; Using the above `query' rule here doesn't always work because sometimes `node' is nil.
480+
;; `query' requires `node' to be matched.
481+
;; We really only care about the parent node being a function-call like list.
482+
;; with it's first named child being a symbol
483+
((lambda (node parent _)
484+
(and (clojure-ts--list-node-p parent)
485+
;; Should we also check for keyword first child, as in (:k map) calls?
486+
(let ((first-child (treesit-node-child parent 0 t)))
487+
(or (clojure-ts--symbol-node-p first-child)
488+
(clojure-ts--keyword-node-p first-child)))))
489+
parent 2)
490+
((parent-is "vec_lit") parent 1)
491+
((parent-is "map_lit") parent 1)
492+
((parent-is "list_lit") parent 1)
493+
((parent-is "set_lit") parent 2))))
494+
482495
(defvar clojure-ts-mode-map
483496
(let ((map (make-sparse-keymap)))
484497
;(set-keymap-parent map clojure-mode-map)

Diff for: indentation.clj

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; https://tonsky.me/blog/clojurefmt/#ok-what-do-we-do-then
2+
(when something
3+
body)
4+
5+
(defn f [x]
6+
body)
7+
8+
(defn f
9+
[x]
10+
body)
11+
12+
(defn many-args [a b c
13+
d e f]
14+
body)
15+
16+
(defn multi-arity
17+
([x]
18+
body)
19+
([x y]
20+
body))
21+
22+
(let [x 1
23+
y 2]
24+
body)
25+
26+
[1 2 3
27+
4 5 6]
28+
29+
{:key-1 v1
30+
:key-2 v2}
31+
32+
#{a b c
33+
d e f}
34+
35+
; second cond is not aligned
36+
(or (condition-a)
37+
(condition-b))
38+
39+
; or/and are the only forms where this looks not ideal
40+
; other forms don’t win/lose much because of this change
41+
(filter even?
42+
(range 1 10))
43+
44+
; my way is actually better if fn name is looooooooooong
45+
(clojure.core/filter even?
46+
(range 1 10))
47+
48+
; 1 additional space, no big deal
49+
(filter
50+
even?
51+
(range 1 10))
52+
53+
(:my/keyword
54+
{:my/keyword 1
55+
:another-keyword 2}
56+
"default value")

0 commit comments

Comments
 (0)