Skip to content

Commit c173149

Browse files
authored
new post about tree-sitter (#37)
* new post about tree-sitter * fix frontmatter/preview lines
1 parent 07387cc commit c173149

File tree

4 files changed

+93
-4
lines changed

4 files changed

+93
-4
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
name: Custom Syntax Highlighting in (Neo)Vim
3+
slug: custom-highlighting
4+
published: 2026-01-17
5+
labels:
6+
- vim
7+
- rust
8+
previewLines: 22
9+
---
10+
11+
*Hopefully this post can be found by someone trying to answer the same questions I was, and maybe save some time.*
12+
13+
Recently while working on closer integration between [Rust and WGSL shader code](/generating-shader-code-1), I looked into what it would take to get syntax highlighting working seamlessly. With a snippet like this:
14+
15+
```rust
16+
fn do_something() -> Option<()> {
17+
// something
18+
None
19+
}
20+
21+
const SHADER_SOURCE: &'static Shader = wgsl!(r#"
22+
struct VertexOutput {
23+
@builtin(position) clip_position: vec4<f32>,
24+
}
25+
26+
@vertex
27+
fn vs_main(
28+
vertex: ModelVertexData,
29+
instance: InstanceDataWithNormalMatrix,
30+
) -> VertexOutput {
31+
// ...
32+
}
33+
");
34+
```
35+
36+
...we want to be able to edit the "embedded" shader code as seamlessly as possible - it should look like this:
37+
38+
```wgsl
39+
struct VertexOutput {
40+
@builtin(position) clip_position: vec4<f32>,
41+
}
42+
43+
@vertex
44+
fn vs_main(
45+
vertex: ModelVertexData,
46+
instance: InstanceDataWithNormalMatrix,
47+
) -> VertexOutput {
48+
// ...
49+
}
50+
```
51+
52+
You may have seen this (multiple syntax highlighting languages used in the same file) for things like JSX or HTML with `<style>` tags. One way to accomplish this in modern editors is with [tree-sitter](https://github.com/tree-sitter/tree-sitter), a parser generator library built-in to Neovim and usable in others like VSCode via extensions. Tree-sitter parses the syntax tree of the code in the document, providing a structure for syntax highlighting rules (and others) to operate on.
53+
54+
In this case we want to query for a macro invocation with a particular name (`wgsl`), capturing the string literal argument's contents, and marking them as WGSL for the sake of syntax highlighting. Tree-sitter in Neovim exposes a way to add these custom rules, "injections" ([`:help treesitter-language-injections`](https://neovim.io/doc/user/treesitter.html#_treesitter-language-injections)). There are a number of examples online of setting these up, but I couldn't seem to get the expected results from them and needed to combine details from each:
55+
56+
This [Youtube video from TJ DeVries](https://www.youtube.com/watch?v=v3o9YaHBM4Q) explains the concept well, shows using the tree-sitter playground, and how to operate on Rust - but it's a little outdated now. On my current version of Neovim (v0.11.5), the usage of `:TSPlaygroundToggle` has been replaced with `:InspectTree`. I tested a query in the playground and got the results I wanted, but couldn't get it to load from an injection file `$NVIM_CONFIG_DIR/after/queries/rust/injections.scm` until I added a special comment to the top of the file:
57+
58+
```scheme
59+
;extends
60+
61+
((macro_invocation
62+
macro: [
63+
(scoped_identifier name: (_) @_macro_name)
64+
(identifier) @_macro_name
65+
]
66+
(#eq? @_macro_name "wgsl")
67+
(token_tree (raw_string_literal (string_content) @injection.content))
68+
(#set! injection.language "wgsl"))
69+
)
70+
```
71+
72+
*~/.config/nvim/after/queries/rust/injections.scm*
73+
74+
[This blog post](https://www.josean.com/posts/nvim-treesitter-and-textobjects) has a lot of great information, and mentions the special `; extends` comment. At this point, I have the intended effect when first editing a file that has the matching syntax! ...until it re-parses and is overwritten for some reason, reverting to being treated as a normal Rust string literal. Many examples show setting a "priority" property for injections which seems like exactly what we need, but I couldn't get it to do anything meaningful - nor could I find many people talking about it.
75+
76+
Finally I stumbled on [this Reddit comment](https://www.reddit.com/r/neovim/comments/1iiqwb1/comment/mbg6ivp/) on a post describing my exact problem! As mentioned in the parent comment, `:Inspect` shows two rules matching the node marking it as a string type, which seems to be the issue. The reverting behavior goes away when I add to my Neovim configuration (in this case `after/ftplugin/rust.lua`):
77+
78+
```lua
79+
vim.api.nvim_set_hl(0, '@lsp.type.string.rust', {})
80+
```
81+
82+
Why? It's unsatisfying, but I don't know at this point. I'm just happy to see the expected result, now no longer fleeting.
83+
84+
![A screenshot of code with both Rust and WGSL highlighted](/static/images/blog/custom-syntax-highlighting/success.png)
85+
The fruits of our "labor".
86+
87+
As a cool side effect, this behavior also takes effect when highlighting Rust in other contexts - like the Markdown source for this post.
88+
89+
![A screenshot of Markdown with a Rust code block highlighted, and WGSL properly highlighted within that.](/static/images/blog/custom-syntax-highlighting/markdown.png)

src/blog/top-albums-2025.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ I would challenge anyone not to find something unique and compelling here, and i
7676

7777
## [*See You In Heaven*](https://softcult.bandcamp.com/album/see-you-in-heaven) by Softcult
7878

79-
Ok so listen, this is technically an LP re-release of two EPs that came out in 2023 & 2024 - is that against the rules? Probably, but I'm including it anyway so that I can mention *Spoiled* which has been literally on repeat for me, writing this sentence I have to put it on again.
79+
Ok so listen, this is technically an LP re-release of two EPs that came out in 2023 & 2024 - is that against the rules? Probably, but I'm including it anyway so that I can mention *Spoiled* which has been literally on repeat for me, writing this sentence I have to put it on again.
8080

8181
*I'm water, I'm oil, I'm rotten, I'm spoiled*
8282

@@ -89,7 +89,7 @@ Ok so listen, this is technically an LP re-release of two EPs that came out in 2
8989

9090
<div class="wrapper">
9191

92-
## [*K-Pop Demon Hunters Soundtrack*](https://music.youtube.com/playlist?list=OLAK5uy_mvB1b-5JvguorHZ7EsoKx3jYDq4VDvt04) by... various artists
92+
## [*K-Pop Demon Hunters Soundtrack*](https://music.youtube.com/playlist?list=OLAK5uy_mvB1b-5JvguorHZ7EsoKx3jYDq4VDvt04) by... various artists
9393

9494
The movie slaps and the soundtrack is basically unassailable. Don't @ me (does anyone still say that?)
9595

@@ -102,7 +102,7 @@ The movie slaps and the soundtrack is basically unassailable. Don't @ me (does a
102102

103103
<div class="wrapper">
104104

105-
## [*2000: In Search Of The Endless Sky*](https://fleshwater.bandcamp.com/album/2000-in-search-of-the-endless-sky) by Fleshwater
105+
## [*2000: In Search Of The Endless Sky*](https://fleshwater.bandcamp.com/album/2000-in-search-of-the-endless-sky) by Fleshwater
106106

107107
I stumbled onto this during a grunge/noise/shoegaze arc that I'm still riding. I can't describe the feeling that *Last Escape* evokes, but it's perfect to me.
108108

@@ -117,7 +117,7 @@ I stumbled onto this during a grunge/noise/shoegaze arc that I'm still riding. I
117117

118118
<div class="wrapper">
119119

120-
## [*Vaxis - Act III: The Father of Make Believe (New Entities Edition)*](https://music.youtube.com/playlist?list=OLAK5uy_kn6U1AqiBglyYzNbOt2wEqNikOITkT2ss) by Coheed and Cambria
120+
## [*Vaxis - Act III: The Father of Make Believe (New Entities Edition)*](https://music.youtube.com/playlist?list=OLAK5uy_kn6U1AqiBglyYzNbOt2wEqNikOITkT2ss) by Coheed and Cambria
121121

122122
This didn't initially hit me as hard as 2022's [*Vaxis II: A Window of the Waking Mind*](https://music.youtube.com/playlist?list=OLAK5uy_mv2ulNXLwW--0lUT8Iw57XjmlSp55UVSs), but it has definitely grown on me - especially with the added *New Entities* tracks. Coheed and Cambria have been one of my favorite bands for well over a decade and I'm happy to see them continuing to evolve creatively.
123123

74.5 KB
Loading
103 KB
Loading

0 commit comments

Comments
 (0)