fix: match brackets preceded by an empty node

`find_pair` looked up the node under the cursor with an empty byte
range. When a zero-width node starts at that position, tree-sitter
returns it, and since it is hidden the lookup resolves to its visible
parent instead. Typst emits such a token right before the `(` or `[`
of a call, so on those brackets `mm` either did nothing or jumped to
the closing bracket of an outer pair. `find_matching_bracket` had the
same problem.

Look up the byte under the cursor instead, like the plaintext fallback
at the end of `find_pair` already does.
This commit is contained in:
dualfroz committed 2026-10-17 03:51:18 +02:00
1 parent 90d0dfc263
commit 0f01568dd8
1 file changed
+26 -1
+26 -1
View File
@@ -83,7 +83,7 @@ fn find_pair(
let pos = doc.char_to_byte(pos_) as u32;
let root = syntax.tree_for_byte_range(pos, pos).root_node();
let mut node = root.descendant_for_byte_range(pos, pos)?;
let mut node = root.descendant_for_byte_range(pos, pos + 1)?;
loop {
if node.is_named() && node.child_count() >= 2 {
@@ -350,4 +350,29 @@ mod tests {
assert("(prev line\n ) (middle) ( \n next line)", 14, 21);
assert("(prev line\n ) (middle) ( \n next line)", 23, 36);
}
#[test]
fn test_find_matching_bracket_after_empty_node() {
// Typst emits a zero-width token right before the `(` or `[` of a call
let loader = crate::config::default_lang_loader();
let language = loader.language_for_name("typst").unwrap();
let doc = crate::Rope::from_str(
"#rect(width: 100%, stroke: stroke(dash: \"dash-dotted\", thickness: 2pt), radius: 5mm)[\n\n]\n",
);
let syntax = Syntax::new(doc.slice(..), language, &loader).unwrap();
let assert = |pos, expected| {
let actual = find_matching_bracket(&syntax, doc.slice(..), pos);
assert_eq!(Some(expected), actual);
let actual = find_matching_bracket_fuzzy(&syntax, doc.slice(..), pos);
assert_eq!(Some(expected), actual);
let actual = find_matching_bracket_fuzzy(&syntax, doc.slice(..), expected);
assert_eq!(Some(pos), actual, "expected symmetrical behaviour");
};
assert(5, 83);
assert(33, 69);
assert(84, 87);
}
}