Skip to content

Commit a7102be

Browse files
committed
[#11] Add regex syntax highlighting
1 parent cec1d32 commit a7102be

File tree

4 files changed

+107
-19
lines changed

4 files changed

+107
-19
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## main (unreleased)
44

5+
- [#11](https://github.com/clojure-emacs/clojure-ts-mode/issues/11): Enable regex syntax highlighting.
6+
57
## 0.3.0 (2025-04-15)
68

79
- [#62](https://github.com/clojure-emacs/clojure-ts-mode/issues/62): Define `list` "thing" to improve navigation in Emacs 31.

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,21 @@ highlighted like regular clojure code.
261261
### Highlight markdown syntax in docstrings
262262

263263
By default markdown syntax is highlighted in the docstrings using
264-
`markdown_inline` grammar. To disable this feature set
264+
`markdown-inline` grammar. To disable this feature set
265265

266266
``` emacs-lisp
267267
(setopt clojure-ts-use-markdown-inline nil)
268268
```
269269

270+
### Highlight regex syntax
271+
272+
By default syntax inside regex literals is highlighted using [regex](https://github.com/tree-sitter/tree-sitter-regex) grammar. To
273+
disable this feature set
274+
275+
```emacs-lisp
276+
(setopt clojure-ts-use-regex-parser nil)
277+
```
278+
270279
### Navigation and Evaluation
271280

272281
To make forms inside of `(comment ...)` forms appear as top-level forms for evaluation and navigation, set

clojure-ts-mode.el

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ double quotes on the third column."
120120
:safe #'booleanp
121121
:package-version '(clojure-ts-mode . "0.2.3"))
122122

123+
(defcustom clojure-ts-use-regex-parser t
124+
"When non-nil, use separate grammar to highlight regex syntax."
125+
:type 'boolean
126+
:safe #'booleanp
127+
:package-version '(clojure-ts-mode . "0.4"))
128+
123129
(defcustom clojure-ts-auto-remap t
124130
"When non-nil, redirect all `clojure-mode' buffers to `clojure-ts-mode'."
125131
:safe #'booleanp
@@ -342,17 +348,37 @@ if a third argument (the value) is provided.
342348
:*)
343349
(:match ,clojure-ts--interface-def-symbol-regexp @_def_symbol))))
344350

345-
(defvar clojure-ts--treesit-range-settings
346-
(treesit-range-rules
347-
:embed 'markdown-inline
348-
:host 'clojure
349-
:local t
350-
(clojure-ts--docstring-query '@capture)))
351+
(defun clojure-ts--treesit-range-settings (use-markdown-inline use-regex)
352+
"Return value for `treesit-range-settings' for `clojure-ts-mode'.
351353
352-
(defun clojure-ts--font-lock-settings (markdown-available)
354+
When USE-MARKDOWN-INLINE is non-nil, include range settings for
355+
markdown-inline parser.
356+
357+
When USE-REGEX is non-nil, include range settings for regex parser."
358+
(append
359+
(when use-markdown-inline
360+
(treesit-range-rules
361+
:embed 'markdown-inline
362+
:host 'clojure
363+
:offset '(1 . -1)
364+
:local t
365+
(clojure-ts--docstring-query '@capture)))
366+
(when use-regex
367+
(treesit-range-rules
368+
:embed 'regex
369+
:host 'clojure
370+
:offset '(2 . -1)
371+
:local t
372+
'((regex_lit) @capture)))))
373+
374+
(defun clojure-ts--font-lock-settings (markdown-available regex-available)
353375
"Return font lock settings suitable for use in `treesit-font-lock-settings'.
376+
354377
When MARKDOWN-AVAILABLE is non-nil, includes rules for highlighting docstrings
355-
with the markdown-inline grammar."
378+
with the markdown-inline grammar.
379+
380+
When REGEX-AVAILABLE is non-nil, includes rules for highlighting regex
381+
literals with regex grammar."
356382
(append
357383
(treesit-font-lock-rules
358384
:feature 'string
@@ -525,6 +551,44 @@ with the markdown-inline grammar."
525551
(inline_link (link_destination) @font-lock-constant-face)
526552
(shortcut_link (link_text) @link)])))
527553

554+
(when regex-available
555+
;; Queries are adapted from
556+
;; https://github.com/tree-sitter/tree-sitter-regex/blob/v0.24.3/queries/highlights.scm.
557+
(treesit-font-lock-rules
558+
:feature 'regex
559+
:language 'regex
560+
:override t
561+
'((["("
562+
")"
563+
"(?"
564+
"(?:"
565+
"(?<"
566+
"(?P<"
567+
"(?P="
568+
">"
569+
"["
570+
"]"
571+
"{"
572+
"}"
573+
"[:"
574+
":]"] @font-lock-regexp-grouping-construct)
575+
(["*"
576+
"+"
577+
"?"
578+
"|"
579+
"="
580+
"!"] @font-lock-property-name-face)
581+
((group_name) @font-lock-variable-name-face)
582+
((count_quantifier
583+
[(decimal_digits) @font-lock-number-face
584+
"," @font-lock-delimiter-face]))
585+
((flags) @font-lock-constant-face)
586+
((character_class
587+
["^" @font-lock-escape-face
588+
(class_range "-" @font-lock-escape-face)]))
589+
((identity_escape) @font-lock-builtin-face)
590+
([(start_assertion) (end_assertion)] @font-lock-constant-face))))
591+
528592
(treesit-font-lock-rules
529593
:feature 'quote
530594
:language 'clojure
@@ -1315,7 +1379,9 @@ If JUSTIFY is non-nil, justify as well as fill the paragraph."
13151379
"v0.0.13")
13161380
(markdown-inline "https://github.com/MDeiml/tree-sitter-markdown"
13171381
"v0.4.1"
1318-
"tree-sitter-markdown-inline/src"))
1382+
"tree-sitter-markdown-inline/src")
1383+
(regex "https://github.com/tree-sitter/tree-sitter-regex"
1384+
"v0.24.3"))
13191385
"Intended to be used as the value for `treesit-language-source-alist'.")
13201386

13211387
(defun clojure-ts--ensure-grammars ()
@@ -1344,19 +1410,20 @@ function can also be used to upgrade the grammars if they are outdated."
13441410
(let ((treesit-language-source-alist clojure-ts-grammar-recipes))
13451411
(treesit-install-language-grammar grammar)))))
13461412

1347-
(defun clojure-ts-mode-variables (&optional markdown-available)
1413+
(defun clojure-ts-mode-variables (&optional markdown-available regex-available)
13481414
"Initialize buffer-local variables for `clojure-ts-mode'.
1349-
See `clojure-ts--font-lock-settings' for usage of MARKDOWN-AVAILABLE."
1415+
See `clojure-ts--font-lock-settings' for usage of MARKDOWN-AVAILABLE and
1416+
REGEX-AVAILABLE."
13501417
(setq-local comment-add 1)
13511418
(setq-local comment-start ";")
13521419

13531420
(setq-local treesit-font-lock-settings
1354-
(clojure-ts--font-lock-settings markdown-available))
1421+
(clojure-ts--font-lock-settings markdown-available regex-available))
13551422
(setq-local treesit-font-lock-feature-list
13561423
'((comment definition variable)
13571424
(keyword string char symbol builtin type)
1358-
(constant number quote metadata doc)
1359-
(bracket deref function regex tagged-literals)))
1425+
(constant number quote metadata doc regex)
1426+
(bracket deref function tagged-literals)))
13601427

13611428
(setq-local treesit-defun-prefer-top-level t)
13621429
(setq-local treesit-defun-tactic 'top-level)
@@ -1389,13 +1456,16 @@ See `clojure-ts--font-lock-settings' for usage of MARKDOWN-AVAILABLE."
13891456
:syntax-table clojure-ts-mode-syntax-table
13901457
(clojure-ts--ensure-grammars)
13911458
(let ((use-markdown-inline (and clojure-ts-use-markdown-inline
1392-
(treesit-ready-p 'markdown-inline t))))
1393-
(when use-markdown-inline
1394-
(setq-local treesit-range-settings clojure-ts--treesit-range-settings))
1459+
(treesit-ready-p 'markdown-inline t)))
1460+
(use-regex (and clojure-ts-use-regex-parser
1461+
(treesit-ready-p 'regex t))))
1462+
(setq-local treesit-range-settings
1463+
(clojure-ts--treesit-range-settings use-markdown-inline
1464+
use-regex))
13951465

13961466
(when (treesit-ready-p 'clojure)
13971467
(treesit-parser-create 'clojure)
1398-
(clojure-ts-mode-variables use-markdown-inline)
1468+
(clojure-ts-mode-variables use-markdown-inline use-regex)
13991469

14001470
(when clojure-ts--debug
14011471
(setq-local treesit--indent-verbose t)

test/samples/regex.clj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(ns regex)
2+
3+
(def email-pattern
4+
#"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")
5+
6+
(def simple-regex
7+
#"^(\\d+).*[a|b|c|d].*[a-z0-9!#]$")

0 commit comments

Comments
 (0)