Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita16c6b4

Browse files
rrudakovbbatsov
authored andcommitted
[#23] Support syntax highlighting for embedded JS and C++
1 parent545991d commita16c6b4

File tree

5 files changed

+145
-6
lines changed

5 files changed

+145
-6
lines changed

‎CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
-[#99](https://github.com/clojure-emacs/clojure-ts-mode/pull/99): Fix bug in`clojure-ts-align` when nested form has extra spaces.
1212
-[#99](https://github.com/clojure-emacs/clojure-ts-mode/pull/99): Fix bug in`clojure-ts-unwind` when there is only one expression after
1313
threading symbol.
14+
- Introduce`clojure-ts-jank-use-cpp-parser` customization which allows
15+
highlighting C++ syntax in Jank`native/raw` forms.
16+
- Introduce`clojure-ts-clojurescript-use-js-parser` customization which allows
17+
highlighting JS syntax in ClojureScript`js*` forms.
18+
1419

1520
##0.4.0 (2025-05-15)
1621

‎README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ Once installed, evaluate `clojure-ts-mode.el` and you should be ready to go.
133133
-[tree-sitter-regex](https://github.com/tree-sitter/tree-sitter-regex/releases/tag/v0.24.3), which will be used for regex literals if available and if
134134
`clojure-ts-use-regex-parser` is not`nil`.
135135

136+
`clojure-ts-clojurescript-mode` can optionally use`tree-sitter-javascript` grammar
137+
to highlight JS syntax in`js*` forms. This is enabled by default and can be
138+
turned off by setting`clojure-ts-clojurescript-use-js-parser` to`nil`.
139+
140+
`clojure-ts-jank-mode` can optionally use`tree-sitter-cpp` grammar to highlight C++
141+
syntax in`native/raw` forms. This is enabled by default and can be turned off by
142+
setting`clojure-ts-jank-use-cpp-parser` to`nil`.
143+
136144
If you have`git` and a C compiler (`cc`) available on your system's`PATH`,
137145
`clojure-ts-mode` will install the
138146
grammars when you first open a Clojure file and`clojure-ts-ensure-grammars` is

‎clojure-ts-mode.el

Lines changed: 115 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ double quotes on the third column."
128128
:safe#'booleanp
129129
:package-version '(clojure-ts-mode."0.4"))
130130

131+
(defcustomclojure-ts-clojurescript-use-js-parsert
132+
"When non-nil, use JS grammar to highlight syntax in js* forms."
133+
:type'boolean
134+
:safe#'booleanp
135+
:package-version '(clojure-ts-mode."0.5"))
136+
137+
(defcustomclojure-ts-jank-use-cpp-parsert
138+
"When non-nil, use C++ grammar to highlight syntax in native/raw forms."
139+
:type'boolean
140+
:safe#'booleanp
141+
:package-version '(clojure-ts-mode."0.5"))
142+
131143
(defcustomclojure-ts-auto-remapt
132144
"When non-nil, redirect all`clojure-mode' buffers to`clojure-ts-mode'."
133145
:safe#'booleanp
@@ -489,6 +501,34 @@ When USE-REGEX is non-nil, include range settings for regex parser."
489501
:localt
490502
'((regex_content) @capture)))))
491503

504+
(defunclojure-ts--fontify-string (nodeoverride_start_end&optional_rest)
505+
"Fontify string content NODE with`font-lock-string-face'.
506+
507+
In order to support embedded syntax highlighting for JS in ClojureScript
508+
and C++ in Jank we need to avoid fontifying string content in some
509+
special forms, such as native/raw in Jank and js* in ClojureScript,
510+
otherwise string face will interfere with embedded parser's faces.
511+
512+
This function respects OVERRIDE argument by passing it to
513+
`treesit-fontify-with-override'.
514+
515+
START and END arguments that are passed to this function are not start
516+
and end of the NODE, so we ignore them."
517+
(let* ((prev (treesit-node-prev-sibling (treesit-node-parent node)))
518+
(jank-native-p (and (derived-mode-p'clojure-ts-jank-mode)
519+
clojure-ts-jank-use-cpp-parser
520+
(clojure-ts--symbol-node-p prev)
521+
(string= (treesit-node-text prev)"native/raw")))
522+
(js-interop-p (and (derived-mode-p'clojure-ts-clojurescript-mode)
523+
clojure-ts-clojurescript-use-js-parser
524+
(clojure-ts--symbol-node-p prev)
525+
(string= (treesit-node-text prev)"js*"))))
526+
(when (not (or jank-native-p js-interop-p))
527+
(treesit-fontify-with-override (treesit-node-start node)
528+
(treesit-node-end node)
529+
'font-lock-string-face
530+
override))))
531+
492532
(defunclojure-ts--font-lock-settings (markdown-availableregex-available)
493533
"Return font lock settings suitable for use in`treesit-font-lock-settings'.
494534
@@ -501,7 +541,9 @@ literals with regex grammar."
501541
(treesit-font-lock-rules
502542
:feature'string
503543
:language'clojure
504-
'((str_lit) @font-lock-string-face
544+
'((str_lit open: _ @font-lock-string-face
545+
(str_content) @clojure-ts--fontify-string
546+
close: _ @font-lock-string-face)
505547
(regex_lit) @font-lock-regexp-face)
506548

507549
:feature'regex
@@ -1400,7 +1442,6 @@ regexes with anchors matching the beginning and end of the line are
14001442
used."
14011443
`((clojure
14021444
((parent-is"^source$") parent-bol0)
1403-
(clojure-ts--match-docstring parent0)
14041445
;; Literal Sequences
14051446
((parent-is"^vec_lit$") parent1);; https://guide.clojure.style/#bindings-alignment
14061447
((parent-is"^map_lit$") parent1);; https://guide.clojure.style/#map-keys-alignment
@@ -1418,7 +1459,12 @@ used."
14181459
;; https://guide.clojure.style/#one-space-indent
14191460
((parent-is"^list_lit$") parent1)
14201461
((parent-is"^anon_fn_lit$") parent2)
1421-
(clojure-ts--match-with-metadata parent0))))
1462+
(clojure-ts--match-with-metadata parent0)
1463+
;; This is slow and only matches when point is inside of a docstring and
1464+
;; only when Markdown grammar is disabled.`indent-region' tries to match
1465+
;; all the rules from top to bottom, so order matters here (the slowest
1466+
;; rules should be at the bottom).
1467+
(clojure-ts--match-docstring parent0))))
14221468

14231469
(defunclojure-ts--configured-indent-rules ()
14241470
"Gets the configured choice of indent rules."
@@ -2518,6 +2564,44 @@ function can also be used to upgrade the grammars if they are outdated."
25182564
(let ((treesit-language-source-alist clojure-ts-grammar-recipes))
25192565
(treesit-install-language-grammar grammar)))))
25202566

2567+
(defsubstclojure-ts--font-lock-setting-update-override (setting)
2568+
"Return SETTING with override set to TRUE."
2569+
(let ((new-setting (copy-tree setting)))
2570+
(setf (nth3 new-setting)t)
2571+
new-setting))
2572+
2573+
(defunclojure-ts--harvest-treesit-configs (mode)
2574+
"Harvest tree-sitter configs from MODE.
2575+
Return a plist with the following keys and value:
2576+
2577+
:font-lock (from`treesit-font-lock-settings')
2578+
:simple-indent (from`treesit-simple-indent-rules')"
2579+
(with-temp-buffer
2580+
(funcall mode)
2581+
;; We need to set :override t for all external queries, otherwise new faces
2582+
;; won't be applied on top of the string face defined for`clojure-ts-mode'.
2583+
(list:font-lock (seq-map#'clojure-ts--font-lock-setting-update-override
2584+
treesit-font-lock-settings)
2585+
:simple-indent treesit-simple-indent-rules)))
2586+
2587+
(defunclojure-ts--add-config-for-mode (mode)
2588+
"Add configurations for MODE to current buffer.
2589+
2590+
Configuration includes font-lock and indent. For font-lock rules, use
2591+
the same features enabled in MODE."
2592+
(let ((configs (clojure-ts--harvest-treesit-configs mode)))
2593+
(setq treesit-font-lock-settings
2594+
(append treesit-font-lock-settings
2595+
(plist-get configs:font-lock)))
2596+
;; FIXME: This works a bit aggressively.`indent-region' always tries to
2597+
;; use rules for embedded parser. Without it users can format embedded code
2598+
;; in an arbitrary way.
2599+
;;
2600+
;; (setq treesit-simple-indent-rules
2601+
;; (append treesit-simple-indent-rules
2602+
;; (plist-get configs :simple-indent)))
2603+
))
2604+
25212605
(defunclojure-ts-mode-variables (&optionalmarkdown-availableregex-available)
25222606
"Initialize buffer-local variables for`clojure-ts-mode'.
25232607
@@ -2625,7 +2709,20 @@ REGEX-AVAILABLE."
26252709
(define-derived-mode clojure-ts-clojurescript-mode clojure-ts-mode"ClojureScript[TS]"
26262710
"Major mode for editing ClojureScript code.
26272711
2628-
\\{clojure-ts-clojurescript-mode-map}")
2712+
\\{clojure-ts-clojurescript-mode-map}"
2713+
(when (and clojure-ts-clojurescript-use-js-parser
2714+
(treesit-ready-p'javascriptt))
2715+
(setq-local treesit-range-settings
2716+
(append treesit-range-settings
2717+
(treesit-range-rules
2718+
:embed'javascript
2719+
:host'clojure
2720+
:localt
2721+
'(((list_lit (sym_lit) @_sym-name
2722+
:anchor (str_lit (str_content) @capture))
2723+
(:equal @_sym-name"js*"))))))
2724+
(clojure-ts--add-config-for-mode'js-ts-mode)
2725+
(treesit-major-mode-setup)))
26292726

26302727
;;;###autoload
26312728
(define-derived-mode clojure-ts-clojurec-mode clojure-ts-mode"ClojureC[TS]"
@@ -2643,7 +2740,20 @@ REGEX-AVAILABLE."
26432740
(define-derived-mode clojure-ts-jank-mode clojure-ts-mode"Jank[TS]"
26442741
"Major mode for editing Jank code.
26452742
2646-
\\{clojure-ts-jank-mode-map}")
2743+
\\{clojure-ts-jank-mode-map}"
2744+
(when (and clojure-ts-jank-use-cpp-parser
2745+
(treesit-ready-p'cppt))
2746+
(setq-local treesit-range-settings
2747+
(append treesit-range-settings
2748+
(treesit-range-rules
2749+
:embed'cpp
2750+
:host'clojure
2751+
:localt
2752+
'(((list_lit (sym_lit) @_sym-name
2753+
:anchor (str_lit (str_content) @capture))
2754+
(:equal @_sym-name"native/raw"))))))
2755+
(clojure-ts--add-config-for-mode'c++-ts-mode)
2756+
(treesit-major-mode-setup)))
26472757

26482758
(defunclojure-ts--register-novel-modes ()
26492759
"Set up Clojure modes not present in progenitor clojure-mode.el."

‎test/samples/embed.cljs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(nsembed)
2+
3+
(js*"var hello = console.log('hello'); const now = new Date();")
4+
5+
(js*"const hello = new Date();
6+
const someOtherVar = 'Just a string';")
7+
8+
(println"This is a normal string")
9+
10+
"Standalone string"
11+
12+
(js*"var hello = 'world';")

‎test/samples/native.jank

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
(defn set-shader-source! [shader source]
55
(native/raw "auto const shader(detail::to_int(~{ shader }));
66
auto const &source(detail::to_string(~{ source }));
7+
__value = make_box();
78
__value = make_box(glShaderSource(shader, 1, &source.data, nullptr));"))
89

910
(defn compile-shader! [shader]
10-
(native/raw "__value = make_box(glCompileShader(detail::to_int(~{ shader })));"))
11+
(native/raw "__value = make_box(glCompileShader(detail::to_int(~{ shader })));")
12+
"Normal string")
13+
14+
"Normal string"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp