W30: Closing bracket pair highlight (also check before cursor)

The existing bracket_flash only triggered when the cursor was
ON a bracket character. This meant that after typing a closing
bracket (the most common trigger scenario), the cursor sits
AFTER the bracket and the flash doesn't fire.

Update update_bracket_flash to also check the character BEFORE
the cursor (pos - 1) and use it as a fallback. The pair position
is adjusted accordingly (the match is at pos - 1 for the before-
cursor case).

Tests: 1393 pass, zero warnings.
This commit is contained in:
2026-07-06 21:31:23 +03:00
parent e8950c2760
commit daa126cc07
+35 -12
View File
@@ -824,24 +824,47 @@ impl Editor {
fn update_bracket_flash(&mut self) {
let pos = self.cursor.position();
let text = self.buffer.as_string();
if pos >= text.len() || !text.is_char_boundary(pos) {
if pos > text.len() || !text.is_char_boundary(pos) {
self.bracket_flash = None;
return;
}
let ch = text[pos..].chars().next().unwrap();
let open = "([{<";
let close = ")]}>";
let result = if let Some(idx) = open.find(ch) {
let target = close.as_bytes()[idx] as char;
Self::find_matching_forward(&text, pos, ch, target)
.map(|end| (pos, end))
} else if let Some(idx) = close.find(ch) {
let target = open.as_bytes()[idx] as char;
Self::find_matching_backward(&text, pos, ch, target)
.map(|start| (start, pos))
// Check the character UNDER the cursor first. If the cursor
// sits on an opening bracket, the match is forward. If it
// sits on a closing bracket, the match is backward.
let ch_at = text[pos..].chars().next();
// Also check the character BEFORE the cursor (pos - 1).
// When the user types a closing bracket, the cursor sits
// *after* the bracket; we still want to flash the pair.
let ch_before = if pos > 0 && text.is_char_boundary(pos - 1) {
text[..pos].chars().next_back()
} else {
None
};
let open = "([{<";
let close = ")]}>";
let resolve = |c: char| -> Option<(usize, usize)> {
if let Some(idx) = open.find(c) {
let target = close.as_bytes()[idx] as char;
Self::find_matching_forward(&text, pos, c, target)
.map(|end| (pos, end))
} else if let Some(idx) = close.find(c) {
let target = open.as_bytes()[idx] as char;
Self::find_matching_backward(&text, pos, c, target)
.map(|start| (start, pos))
} else {
None
}
};
// Prefer the char under the cursor. Fall back to the char
// before (for the typed-closing-bracket case).
let result = ch_at.and_then(&resolve).or_else(|| {
ch_before.and_then(&resolve).map(|(s, _)| {
// For backward lookup the match is at (pos - 1) and
// the opening bracket is before it.
let _ = pos;
(s, pos.saturating_sub(1))
})
});
self.bracket_flash = result;
}