diff --git a/helix-core/src/match_brackets.rs b/helix-core/src/match_brackets.rs index fd43a110e796..6a24a87b709d 100644 --- a/helix-core/src/match_brackets.rs +++ b/helix-core/src/match_brackets.rs @@ -51,11 +51,17 @@ fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) -> let pos = doc.char_to_byte(pos); let mut node = tree.root_node().named_descendant_for_byte_range(pos, pos)?; + let mut node_positions = get_node_positions(doc, &node); - loop { - let (start_byte, end_byte) = surrounding_bytes(doc, &node)?; - let (start_char, end_char) = (doc.byte_to_char(start_byte), doc.byte_to_char(end_byte)); + if is_valid_bracket(doc.char(pos)) { + if let Some((_, _, start_char, end_char)) = node_positions { + if !is_valid_pair(doc, start_char, end_char) { + return find_matching_bracket_plaintext(doc, pos); + } + } + } + while let Some((_, end_byte, start_char, end_char)) = node_positions { if is_valid_pair(doc, start_char, end_char) { if end_byte == pos { return Some(start_char); @@ -67,10 +73,19 @@ fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) -> if traverse_parents { node = node.parent()?; + node_positions = get_node_positions(doc, &node); } else { - return None; + break; } } + + None +} + +fn get_node_positions(doc: &Rope, node: &Node) -> Option<(usize, usize, usize, usize)> { + let (start_byte, end_byte) = surrounding_bytes(doc, node)?; + let (start_char, end_char) = (doc.byte_to_char(start_byte), doc.byte_to_char(end_byte)); + Some((start_byte, end_byte, start_char, end_char)) } /// Returns the position of the matching bracket under cursor. @@ -85,10 +100,7 @@ fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) -> /// /// If no matching bracket is found, `None` is returned. #[must_use] -pub fn find_matching_bracket_current_line_plaintext( - doc: &Rope, - cursor_pos: usize, -) -> Option { +pub fn find_matching_bracket_plaintext(doc: &Rope, cursor_pos: usize) -> Option { // Don't do anything when the cursor is not on top of a bracket. let bracket = doc.char(cursor_pos); if !is_valid_bracket(bracket) { @@ -169,10 +181,10 @@ mod tests { fn test_find_matching_bracket_current_line_plaintext() { let assert = |input: &str, pos, expected| { let input = &Rope::from(input); - let actual = find_matching_bracket_current_line_plaintext(input, pos); + let actual = find_matching_bracket_plaintext(input, pos); assert_eq!(expected, actual.unwrap()); - let actual = find_matching_bracket_current_line_plaintext(input, expected); + let actual = find_matching_bracket_plaintext(input, expected); assert_eq!(pos, actual.unwrap(), "expected symmetrical behaviour"); }; diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 1e89fe1cb69b..0ff31c578718 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -4535,7 +4535,7 @@ fn match_brackets(cx: &mut Context) { let selection = doc.selection(view.id).clone().transform(|range| { let pos = range.cursor(text_slice); if let Some(matched_pos) = doc.syntax().map_or_else( - || match_brackets::find_matching_bracket_current_line_plaintext(text, pos), + || match_brackets::find_matching_bracket_plaintext(text, pos), |syntax| match_brackets::find_matching_bracket_fuzzy(syntax, text, pos), ) { range.put_cursor(text_slice, matched_pos, is_select)