Skip to content

Commit cb2cb18

Browse files
rrudakovbbatsov
authored andcommitted
Update the design documentation
1 parent 7e359ed commit cb2cb18

File tree

2 files changed

+79
-51
lines changed

2 files changed

+79
-51
lines changed

clojure-ts-mode.el

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ Only intended for use at development time.")
306306
"Syntax table for `clojure-ts-mode'.")
307307

308308
(defconst clojure-ts--builtin-dynamic-var-regexp
309-
(eval-and-compile
309+
(eval-when-compile
310310
(concat "^"
311311
(regexp-opt
312312
'("*1" "*2" "*3" "*agent*"
@@ -323,7 +323,7 @@ Only intended for use at development time.")
323323
"$")))
324324

325325
(defconst clojure-ts--builtin-symbol-regexp
326-
(eval-and-compile
326+
(eval-when-compile
327327
(concat "^"
328328
(regexp-opt
329329
'("do" "if" "let*" "var"
@@ -372,52 +372,46 @@ Only intended for use at development time.")
372372
(concat "^" (regexp-opt symbols) "$"))
373373

374374
(defconst clojure-ts-function-docstring-symbols
375-
(eval-and-compile
376-
(rx line-start
377-
(or "definline"
378-
"defmulti"
379-
"defmacro"
380-
"defn"
381-
"defn-"
382-
"defprotocol"
383-
"ns")
384-
line-end))
375+
(rx line-start
376+
(or "definline"
377+
"defmulti"
378+
"defmacro"
379+
"defn"
380+
"defn-"
381+
"defprotocol"
382+
"ns")
383+
line-end)
385384
"Symbols that accept an optional docstring as their second argument.")
386385

387386
(defconst clojure-ts-definition-docstring-symbols
388-
(eval-and-compile
389-
(rx line-start "def" line-end))
387+
(rx line-start "def" line-end)
390388
"Symbols that accept an optional docstring as their second argument.
391389
Any symbols added here should only treat their second argument as a docstring
392390
if a third argument (the value) is provided.
393391
\"def\" is the only builtin Clojure symbol that behaves like this.")
394392

395393
(defconst clojure-ts--variable-definition-symbol-regexp
396-
(eval-and-compile
397-
(rx line-start (or "def" "defonce") line-end))
394+
(rx line-start (or "def" "defonce") line-end)
398395
"A regular expression matching a symbol used to define a variable.")
399396

400397
(defconst clojure-ts--typedef-symbol-regexp
401-
(eval-and-compile
402-
(rx line-start
403-
(or "defprotocol" "defmulti" "deftype" "defrecord"
404-
"definterface" "defmethod" "defstruct")
405-
line-end))
398+
(rx line-start
399+
(or "defprotocol" "defmulti" "deftype" "defrecord"
400+
"definterface" "defmethod" "defstruct")
401+
line-end)
406402
"A regular expression matching a symbol used to define a type.")
407403

408404
(defconst clojure-ts--type-symbol-regexp
409-
(eval-and-compile
410-
(rx line-start
411-
(or "deftype" "defrecord"
412-
;; While not reifying, helps with doc strings
413-
"defprotocol" "definterface"
414-
"reify" "proxy" "extend-type" "extend-protocol")
415-
line-end))
405+
(rx line-start
406+
(or "deftype" "defrecord"
407+
;; While not reifying, helps with doc strings
408+
"defprotocol" "definterface"
409+
"reify" "proxy" "extend-type" "extend-protocol")
410+
line-end)
416411
"A regular expression matching a symbol used to define or instantiate a type.")
417412

418413
(defconst clojure-ts--interface-def-symbol-regexp
419-
(eval-and-compile
420-
(rx line-start (or "defprotocol" "definterface") line-end))
414+
(rx line-start (or "defprotocol" "definterface") line-end)
421415
"A regular expression matching a symbol used to define an interface.")
422416

423417
(defun clojure-ts--docstring-query (capture-symbol)

doc/design.md

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,43 @@ In short:
3232

3333
## tree-sitter-clojure
3434

35-
Clojure-ts-mode uses the tree-sitter-clojure grammar, which can be found at <https://github.com/sogaiu/tree-sitter-clojure>
36-
The clojure-ts-mode grammar provides very basic, low level nodes that try to match Clojure's very light syntax.
35+
`clojure-ts-mode` uses the experimental version tree-sitter-clojure grammar, which
36+
can be found at
37+
<https://github.com/sogaiu/tree-sitter-clojure/tree/unstable-20250526>. The
38+
`clojure-ts-mode` grammar provides very basic, low level nodes that try to match
39+
Clojure's very light syntax.
3740

3841
There are nodes to represent:
3942

40-
- Symbols (sym_lit)
41-
- Contain (sym_ns) and (sym_name) nodes
42-
- Keywords (kwd_lit)
43-
- Contain (kwd_ns) and (kw_name) nodes
44-
- Strings (str_lit)
45-
- Chars (char_lit)
46-
- Nil (nil_lit)
47-
- Booleans (bool_lit)
48-
- Numbers (num_lit)
49-
- Comments (comment, dis_expr)
50-
- dis_expr is the `#_` discard expression
51-
- Lists (list_list)
52-
- Vectors (vec_lit)
53-
- Maps (map_lit)
54-
- Sets (set_lit)
55-
56-
There are also nodes to represent metadata, which appear on `meta:` child fields of the nodes the metadata is defined on.
57-
For example a simple vector with metadata defined on it like so
43+
- Symbols `(sym_lit)`
44+
- Contain `(sym_ns)` and `(sym_name)` nodes
45+
- Keywords `(kwd_lit)`
46+
- Contain `(kwd_ns)` and `(kw_name)` nodes
47+
- Strings `(str_lit)`
48+
- Contains `(str_content)` node
49+
- Chars `(char_lit)`
50+
- Nil `(nil_lit)`
51+
- Booleans `(bool_lit)`
52+
- Numbers `(num_lit)`
53+
- Comments `(comment, dis_expr)`
54+
- `dis_expr` is the `#_` discard expression
55+
- Lists `(list_list)`
56+
- Vectors `(vec_lit)`
57+
- Maps `(map_lit)`
58+
- Sets `(set_lit)`
59+
- Metadata nodes `(meta_lit)`
60+
- Regex content `(regex_content)`
61+
- Function literals `(anon_fn_lit)`
62+
63+
The best place to learn more about the tree-sitter-clojure grammar is to read
64+
the [grammar.js file from the tree-sitter-clojure repository](https://github.com/sogaiu/tree-sitter-clojure/blob/master/grammar.js "grammar.js").
65+
66+
### Difference between stable grammar and experimental
67+
68+
#### Standalone metadata nodes
69+
70+
Metadata nodes in stable grammar appear as child nodes of the nodes the metadata
71+
is defined on. For example a simple vector with metadata defined on it like so:
5872

5973
```clojure
6074
^:has-metadata [1]
@@ -69,7 +83,27 @@ will produce a parse tree like so
6983
value: (num_lit))
7084
```
7185

72-
The best place to learn more about the tree-sitter-clojure grammar is to read the [grammar.js file from the tree-sitter-clojure repository](https://github.com/sogaiu/tree-sitter-clojure/blob/master/grammar.js "grammar.js").
86+
Although it's somewhat closer to hoe Clojure treats metadata itself, in the
87+
context of a text editor it creates some problems, which were discussed [here](https://github.com/sogaiu/tree-sitter-clojure/issues/65). To
88+
name a few:
89+
- `forward-sexp` command would skip both, metadata and the node it's attached
90+
to. Called from an opening paren it would signal an error "No more sexp to
91+
move across".
92+
- `kill-sexp` command would kill both, metadata and the node it's attached to.
93+
- `backward-up-list` called from the inside of a list with metadata would move
94+
point to the beginning of metadata node.
95+
- Internally we had to introduce some workarounds to skip metadata nodes or
96+
figure out where the actual node starts.
97+
98+
#### Special nodes for string content and regex content
99+
100+
To parse the content of certain strings with a separate grammar, it is necessary
101+
to extract the string's content, excluding its opening and closing quotes. To
102+
achieve this, Emacs 31 allows specifying offsets for `treesit-range-settings`.
103+
However, in Emacs 30.1, this feature is broken due to bug [#77848](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=77848) (a fix is
104+
anticipated in Emacs 30.2). The presence of `str_content` and `regex_content` nodes
105+
allows us to support this feature across all Emacs versions without relying on
106+
offsets.
73107

74108
### Clojure Syntax, not Clojure Semantics
75109

0 commit comments

Comments
 (0)