summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2024-09-22 16:58:16 +0200
committerGitHub <noreply@github.com>2024-09-22 17:58:16 +0300
commit4a7728bf7fac06a35f27f6c4f31e0d9214e5152b (patch)
treea708d7c05e007b4abd07421afbda1f64caf0bb47
parentc74b5fa857a133298f0207c499c47cb95b27c78c (diff)
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.md1
-rw-r--r--alacritty_terminal/src/term/search.rs29
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)));
+ }
}