diff options
author | Christian Duerr <contact@christianduerr.com> | 2024-09-22 16:58:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-22 17:58:16 +0300 |
commit | 4a7728bf7fac06a35f27f6c4f31e0d9214e5152b (patch) | |
tree | a708d7c05e007b4abd07421afbda1f64caf0bb47 | |
parent | c74b5fa857a133298f0207c499c47cb95b27c78c (diff) | |
download | alacritty-4a7728bf7fac06a35f27f6c4f31e0d9214e5152b.tar.gz alacritty-4a7728bf7fac06a35f27f6c4f31e0d9214e5152b.zip |
Fix fullwidth semantic escape characters
Semantic escape characters occupying two two grid cells were always
skipped over, making it impossible to have functional fullwidth
characters as part of semantic escape characters.
This patch fixes this by only skipping over fullwidth spacer cells,
rather than skipping those cells entirely.
Closes #8188.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | alacritty_terminal/src/term/search.rs | 29 |
2 files changed, 25 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 38584ca5..946f48ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Broken search with words broken across line boundary on the first character - Config import changes not being live reloaded - Cursor color requests with default cursor colors +- Fullwidth semantic escape characters ## 0.13.2 diff --git a/alacritty_terminal/src/term/search.rs b/alacritty_terminal/src/term/search.rs index a5ae9337..33f6ee05 100644 --- a/alacritty_terminal/src/term/search.rs +++ b/alacritty_terminal/src/term/search.rs @@ -516,7 +516,14 @@ impl<T> Term<T> { #[must_use] pub fn semantic_search_left(&self, point: Point) -> Point { match self.inline_search_left(point, self.semantic_escape_chars()) { - Ok(point) => self.grid.iter_from(point).next().map_or(point, |cell| cell.point), + // If we found a match, reverse for at least one cell, skipping over wide cell spacers. + Ok(point) => { + let wide_spacer = Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; + self.grid + .iter_from(point) + .find(|cell| !cell.flags.intersects(wide_spacer)) + .map_or(point, |cell| cell.point) + }, Err(point) => point, } } @@ -538,7 +545,7 @@ impl<T> Term<T> { let mut iter = self.grid.iter_from(point); let last_column = self.columns() - 1; - let wide = Flags::WIDE_CHAR | Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; + let wide_spacer = Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; while let Some(cell) = iter.prev() { if cell.point.column == last_column && !cell.flags.contains(Flags::WRAPLINE) { break; @@ -546,7 +553,7 @@ impl<T> Term<T> { point = cell.point; - if !cell.flags.intersects(wide) && needles.contains(cell.c) { + if !cell.flags.intersects(wide_spacer) && needles.contains(cell.c) { return Ok(point); } } @@ -559,7 +566,7 @@ impl<T> Term<T> { // Limit the starting point to the last line in the history point.line = max(point.line, self.topmost_line()); - let wide = Flags::WIDE_CHAR | Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; + let wide_spacer = Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; let last_column = self.columns() - 1; // Immediately stop if start point in on line break. @@ -570,7 +577,7 @@ impl<T> Term<T> { for cell in self.grid.iter_from(point) { point = cell.point; - if !cell.flags.intersects(wide) && needles.contains(cell.c) { + if !cell.flags.intersects(wide_spacer) && needles.contains(cell.c) { return Ok(point); } @@ -1171,4 +1178,16 @@ mod tests { let match_end = Point::new(Line(1), Column(2)); assert_eq!(term.regex_search_left(&mut regex, start, end), Some(match_start..=match_end)); } + + #[test] + fn fullwidth_semantic() { + #[rustfmt::skip] + let mut term = mock_term("test-x-test"); + term.config.semantic_escape_chars = "-".into(); + + let start = term.semantic_search_left(Point::new(Line(0), Column(6))); + let end = term.semantic_search_right(Point::new(Line(0), Column(6))); + assert_eq!(start, Point::new(Line(0), Column(6))); + assert_eq!(end, Point::new(Line(0), Column(6))); + } } |