changeset 6789:8923fd2fae2a

feat: Highlight Rust String interpolation macros Fixes #5845
author Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com>
date Tue, 04 Feb 2025 03:31:04 +0000
parents 609d6c4223f6
children c5a08bc07dc8
files book/src/generated/lang-support.md languages.toml runtime/queries/rust/injections.scm runtime/queries/rustfmt/highlights.scm
diffstat 4 files changed, 141 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/book/src/generated/lang-support.md	Tue Feb 25 11:57:27 2025 -0500
+++ b/book/src/generated/lang-support.md	Tue Feb 04 03:31:04 2025 +0000
@@ -199,6 +199,7 @@
 | rst | ✓ |  |  |  |
 | ruby | ✓ | ✓ | ✓ | `ruby-lsp`, `solargraph` |
 | rust | ✓ | ✓ | ✓ | `rust-analyzer` |
+| rustfmt | ✓ |  |  |  |
 | sage | ✓ | ✓ |  |  |
 | scala | ✓ | ✓ | ✓ | `metals` |
 | scheme | ✓ |  | ✓ |  |
--- a/languages.toml	Tue Feb 25 11:57:27 2025 -0500
+++ b/languages.toml	Tue Feb 04 03:31:04 2025 +0000
@@ -4360,3 +4360,13 @@
 [[grammar]]
 name = "dunstrc"
 source = { git = "https://github.com/rotmh/tree-sitter-dunstrc", rev = "9cb9d5cc51cf5e2a47bb2a0e2f2e519ff11c1431" }
+
+[[language]]
+name = "rustfmt"
+scope = "source.rustfmt"
+file-types = []
+injection-regex = "rustfmt"
+
+[[grammar]]
+name = "rustfmt"
+source = { git = "https://github.com/nik-rev/tree-sitter-rustfmt", rev = "d8e517d9aca1905261a378b25688e4500ae4dd22" }
--- a/runtime/queries/rust/injections.scm	Tue Feb 25 11:57:27 2025 -0500
+++ b/runtime/queries/rust/injections.scm	Tue Feb 04 03:31:04 2025 +0000
@@ -97,3 +97,104 @@
     ]
   )
   (#set! injection.language "sql"))
+
+; std::fmt
+
+; For these, only the first argument is format_args!
+((macro_invocation
+   macro:
+     [
+       (scoped_identifier
+         name: (_) @_macro_name)
+       (identifier) @_macro_name
+     ]
+   (token_tree . (string_literal) @injection.content))
+ (#any-of? @_macro_name
+  ; std
+  "format"
+  "print"
+  "println"
+  "eprint"
+  "eprintln"
+  "format_args"
+  "todo"
+  "unreachable"
+  "unimplemented"
+  "compile_error"
+  ; log
+  "crit"
+  "trace"
+  "debug"
+  "info"
+  "warn"
+  "error"
+  ; anyhow
+  "anyhow"
+  "bail"
+  ; syn
+  "format_ident"
+  ; indoc
+  "formatdoc"
+  "printdoc"
+  "eprintdoc"
+  "writedoc")
+ (#set! injection.language "rustfmt")
+ (#set! injection.include-children))
+
+; For these, only the second argument is format_args!
+((macro_invocation
+   macro:
+     [
+       (scoped_identifier
+         name: (_) @_macro_name)
+       (identifier) @_macro_name
+     ]
+   (token_tree . (_) . (string_literal) @injection.content))
+ (#any-of? @_macro_name
+  ; std
+  "write"
+  "writeln"
+  "assert"
+  "debug_assert")
+ (#set! injection.language "rustfmt")
+ (#set! injection.include-children))
+
+; For these, only the third argument is format_args!
+((macro_invocation
+   macro:
+     [
+       (scoped_identifier
+         name: (_) @_macro_name)
+       (identifier) @_macro_name
+     ]
+   (token_tree . (_) . (_) . (string_literal) @injection.content))
+ (#any-of? @_macro_name
+  ; std
+  "assert_eq"
+  "debug_assert_eq"
+  "assert_ne"
+  "debug_assert_ne")
+ (#set! injection.language "rustfmt")
+ (#set! injection.include-children))
+
+; Dioxus' "rsx!" macro relies heavily on string interpolation as well. The strings can be nested very deeply
+((macro_invocation
+   macro:
+     [
+       (scoped_identifier
+         name: (_) @_macro_name)
+       (identifier) @_macro_name
+     ]
+    ; TODO: This only captures 1 level of string literals. But in dioxus you can have
+    ; nested string literals. For instance:
+    ;
+    ; rsx! { "{hello} world" }:
+    ; -> (token_tree (string_literal))
+    ; rsx! { div { "{hello} world" } }
+    ; -> (token_tree (token_tree (string_literal)))
+    ; rsx! { div { div { "{hello} world" } } }
+    ; -> (token_tree (token_tree (token_tree (string_literal))))
+   (token_tree (string_literal) @injection.content))
+ (#eq? @_macro_name "rsx")
+ (#set! injection.language "rustfmt")
+ (#set! injection.include-children))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/queries/rustfmt/highlights.scm	Tue Feb 04 03:31:04 2025 +0000
@@ -0,0 +1,29 @@
+; (format_string) @string
+
+(escaped) @constant.character.escape
+
+[
+  "#"
+  (type)
+] @special
+
+[
+  (sign)
+  (fill)
+  (align)
+  (width)
+] @operator
+
+(number) @constant.numeric
+
+(colon) @punctuation
+
+(identifier) @variable
+
+((identifier) @constant
+ (#match? @constant "^[A-Z_]+$"))
+
+[
+  "{"
+  "}"
+] @punctuation.special