Fix keyword highlighting to use word boundaries via context matching

This commit is contained in:
Michael Netshipise 2026-01-19 22:26:18 +02:00
parent 6c4e8d3d5e
commit eeb333acbd
3 changed files with 186 additions and 54 deletions

View File

@ -29,7 +29,7 @@ module.exports = grammar({
// Rust imports // Rust imports
use_statement: ($) => use_statement: ($) =>
seq("@use", $.rust_path, optional(seq("as", $.identifier))), seq(seq("@", "use"), $.rust_path, optional(seq("as", $.identifier))),
// Use token() to properly handle :: in paths // Use token() to properly handle :: in paths
rust_path: ($) => rust_path: ($) =>
@ -42,14 +42,14 @@ module.exports = grammar({
// Template imports - supports both quoted "path" and unquoted /path // Template imports - supports both quoted "path" and unquoted /path
import_statement: ($) => import_statement: ($) =>
seq("@import", choice($.string_literal, $.import_path), "as", $.identifier), seq(seq("@", "import"), choice($.string_literal, $.import_path), "as", $.identifier),
import_path: ($) => /\/[^\s]+/, import_path: ($) => /\/[^\s]+/,
// Struct definition // Struct definition
struct_definition: ($) => struct_definition: ($) =>
seq( seq(
"@struct", seq("@", "struct"),
optional($.attribute_list), optional($.attribute_list),
$.identifier, $.identifier,
optional($.generic_params), optional($.generic_params),
@ -70,7 +70,7 @@ module.exports = grammar({
// Enum definition // Enum definition
enum_definition: ($) => enum_definition: ($) =>
seq( seq(
"@enum", seq("@", "enum"),
optional($.attribute_list), optional($.attribute_list),
$.identifier, $.identifier,
optional($.generic_params), optional($.generic_params),
@ -102,7 +102,7 @@ module.exports = grammar({
// Function definition // Function definition
function_definition: ($) => function_definition: ($) =>
seq("@fn", $.identifier, $.parameter_list, $.content_block), seq(seq("@", "fn"), $.identifier, $.parameter_list, $.content_block),
parameter_list: ($) => parameter_list: ($) =>
seq( seq(
@ -173,7 +173,7 @@ module.exports = grammar({
attribute_if_statement: ($) => attribute_if_statement: ($) =>
seq( seq(
"@if", seq("@", "if"),
$.expression, $.expression,
"{", "{",
repeat($.attribute_or_control), repeat($.attribute_or_control),
@ -183,7 +183,7 @@ module.exports = grammar({
attribute_for_loop: ($) => attribute_for_loop: ($) =>
seq( seq(
"@for", seq("@", "for"),
$.simple_pattern, $.simple_pattern,
"in", "in",
$.expression, $.expression,
@ -251,11 +251,11 @@ module.exports = grammar({
// Let binding: @let name = expression // Let binding: @let name = expression
let_statement: ($) => let_statement: ($) =>
seq("@let", $.pattern, "=", $.expression), seq(seq("@", "let"), $.pattern, "=", $.expression),
if_statement: ($) => if_statement: ($) =>
seq( seq(
"@if", seq("@", "if"),
optional(seq("let", $.pattern, "=")), optional(seq("let", $.pattern, "=")),
$.expression, $.expression,
$.content_block, $.content_block,
@ -276,7 +276,7 @@ module.exports = grammar({
for_loop: ($) => for_loop: ($) =>
seq( seq(
"@for", seq("@", "for"),
optional(seq($.identifier, ":")), optional(seq($.identifier, ":")),
$.simple_pattern, $.simple_pattern,
"in", "in",
@ -285,7 +285,7 @@ module.exports = grammar({
), ),
match_statement: ($) => match_statement: ($) =>
seq("@match", $.expression, "{", repeat($.match_arm), "}"), seq(seq("@", "match"), $.expression, "{", repeat($.match_arm), "}"),
match_arm: ($) => match_arm: ($) =>
seq( seq(
@ -297,10 +297,10 @@ module.exports = grammar({
), ),
break_statement: ($) => break_statement: ($) =>
seq("@break", optional(seq(":", $.identifier)), optional(";")), seq(seq("@", "break"), optional(seq(":", $.identifier)), optional(";")),
continue_statement: ($) => continue_statement: ($) =>
seq("@continue", optional(seq(":", $.identifier)), optional(";")), seq(seq("@", "continue"), optional(seq(":", $.identifier)), optional(";")),
// Function tags // Function tags
function_tag: ($) => function_tag: ($) =>

View File

@ -7,21 +7,36 @@
; Raw blocks ; Raw blocks
(raw_block) @string.special (raw_block) @string.special
; Keywords ; Keywords - only in proper syntactic contexts
"@use" @keyword (use_statement "@" @keyword)
"@import" @keyword (use_statement "use" @keyword)
"@struct" @keyword (import_statement "@" @keyword)
"@enum" @keyword (import_statement "import" @keyword)
"@fn" @keyword (struct_definition "@" @keyword)
"@let" @keyword (struct_definition "struct" @keyword)
"@if" @keyword (enum_definition "@" @keyword)
"@for" @keyword (enum_definition "enum" @keyword)
"@match" @keyword (function_definition "@" @keyword)
"@break" @keyword (function_definition "fn" @keyword)
"@continue" @keyword (let_statement "@" @keyword)
"else" @keyword (let_statement "let" @keyword)
"if" @keyword (if_statement "@" @keyword)
"let" @keyword (if_statement "if" @keyword)
(for_loop "@" @keyword)
(for_loop "for" @keyword)
(match_statement "@" @keyword)
(match_statement "match" @keyword)
(break_statement "@" @keyword)
(break_statement "break" @keyword)
(continue_statement "@" @keyword)
(continue_statement "continue" @keyword)
(attribute_if_statement "@" @keyword)
(attribute_if_statement "if" @keyword)
(attribute_for_loop "@" @keyword)
(attribute_for_loop "for" @keyword)
(else_if_branch "else" @keyword)
(else_if_branch "if" @keyword)
(else_branch "else" @keyword)
"in" @keyword "in" @keyword
"as" @keyword "as" @keyword
"mut" @keyword "mut" @keyword

View File

@ -39,11 +39,20 @@
] ]
}, },
"use_statement": { "use_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@use" "value": "@"
},
{
"type": "STRING",
"value": "use"
}
]
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -101,11 +110,20 @@
} }
}, },
"import_statement": { "import_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@import" "value": "@"
},
{
"type": "STRING",
"value": "import"
}
]
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -135,11 +153,20 @@
"value": "\\/[^\\s]+" "value": "\\/[^\\s]+"
}, },
"struct_definition": { "struct_definition": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@struct" "value": "@"
},
{
"type": "STRING",
"value": "struct"
}
]
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -228,11 +255,20 @@
] ]
}, },
"enum_definition": { "enum_definition": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@enum" "value": "@"
},
{
"type": "STRING",
"value": "enum"
}
]
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -467,11 +503,20 @@
"name": "rust_type" "name": "rust_type"
}, },
"function_definition": { "function_definition": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@fn" "value": "@"
},
{
"type": "STRING",
"value": "fn"
}
]
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -775,11 +820,20 @@
] ]
}, },
"attribute_if_statement": { "attribute_if_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@if" "value": "@"
},
{
"type": "STRING",
"value": "if"
}
]
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -835,11 +889,20 @@
] ]
}, },
"attribute_for_loop": { "attribute_for_loop": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@for" "value": "@"
},
{
"type": "STRING",
"value": "for"
}
]
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -1153,11 +1216,20 @@
] ]
}, },
"let_statement": { "let_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@let" "value": "@"
},
{
"type": "STRING",
"value": "let"
}
]
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -1174,11 +1246,20 @@
] ]
}, },
"if_statement": { "if_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@if" "value": "@"
},
{
"type": "STRING",
"value": "if"
}
]
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -1294,11 +1375,20 @@
] ]
}, },
"for_loop": { "for_loop": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@for" "value": "@"
},
{
"type": "STRING",
"value": "for"
}
]
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -1340,11 +1430,20 @@
] ]
}, },
"match_statement": { "match_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@match" "value": "@"
},
{
"type": "STRING",
"value": "match"
}
]
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -1418,11 +1517,20 @@
] ]
}, },
"break_statement": { "break_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@break" "value": "@"
},
{
"type": "STRING",
"value": "break"
}
]
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -1460,11 +1568,20 @@
] ]
}, },
"continue_statement": { "continue_statement": {
"type": "SEQ",
"members": [
{
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "@continue" "value": "@"
},
{
"type": "STRING",
"value": "continue"
}
]
}, },
{ {
"type": "CHOICE", "type": "CHOICE",