diff options
author | Christian Duerr <contact@christianduerr.com> | 2024-11-22 01:07:08 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-22 01:07:08 +0000 |
commit | 3ac4904eb5a1cc15cc02b077c118f1ffcb9e6916 (patch) | |
tree | 73106c776b9796d4712fa22de356ef9725e2b1c0 | |
parent | 4f739a7e2b933f6828ebf64654c8a8c573bf0ec1 (diff) | |
download | alacritty-3ac4904eb5a1cc15cc02b077c118f1ffcb9e6916.tar.gz alacritty-3ac4904eb5a1cc15cc02b077c118f1ffcb9e6916.zip |
Fix vi motion with wide semantic escape chars
This patch fixes an issue where the semantic vi motion commands
`SemanticRight` and `SemanticLeft` were not behaving as expected when a
fullwidth character was used as a semantic character.
Closes #8314.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | alacritty_terminal/src/term/mod.rs | 5 | ||||
-rw-r--r-- | alacritty_terminal/src/vi_mode.rs | 49 |
3 files changed, 52 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index bbe0d2f4..c9faa35c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Mouse/Vi cursor hint highlighting broken on the terminal cursor line - Hint launcher opening arbitrary text, when terminal content changed while opening +- `SemanticRight`/`SemanticLeft` vi motions breaking with wide semantic escape characters ## 0.14.0 diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 1f1e52c1..c2d77ec7 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -930,6 +930,11 @@ impl<T> Term<T> { &self.config.semantic_escape_chars } + #[cfg(test)] + pub(crate) fn set_semantic_escape_chars(&mut self, semantic_escape_chars: &str) { + self.config.semantic_escape_chars = semantic_escape_chars.into(); + } + /// Active terminal cursor style. /// /// While vi mode is active, this will automatically return the vi mode cursor style. diff --git a/alacritty_terminal/src/vi_mode.rs b/alacritty_terminal/src/vi_mode.rs index 7065544e..e23e9b80 100644 --- a/alacritty_terminal/src/vi_mode.rs +++ b/alacritty_terminal/src/vi_mode.rs @@ -265,14 +265,14 @@ fn semantic<T: EventListener>( } }; - // Make sure we jump above wide chars. - point = term.expand_wide(point, direction); - // Move to word boundary. if direction != side && !is_boundary(term, point, direction) { point = expand_semantic(point); } + // Make sure we jump above wide chars. + point = term.expand_wide(point, direction); + // Skip whitespace. let mut next_point = advance(term, point, direction); while !is_boundary(term, point, direction) && is_space(term, next_point) { @@ -283,6 +283,11 @@ fn semantic<T: EventListener>( // Assure minimum movement of one cell. if !is_boundary(term, point, direction) { point = advance(term, point, direction); + + // Skip over wide cell spacers. + if direction == Direction::Left { + point = term.expand_wide(point, direction); + } } // Move to word boundary. @@ -820,4 +825,42 @@ mod tests { cursor = cursor.scroll(&term, -20); assert_eq!(cursor.point, Point::new(Line(19), Column(0))); } + + #[test] + fn wide_semantic_char() { + let mut term = term(); + term.set_semantic_escape_chars("-"); + term.grid_mut()[Line(0)][Column(0)].c = 'x'; + term.grid_mut()[Line(0)][Column(1)].c = 'x'; + term.grid_mut()[Line(0)][Column(2)].c = '-'; + term.grid_mut()[Line(0)][Column(2)].flags.insert(Flags::WIDE_CHAR); + term.grid_mut()[Line(0)][Column(3)].c = ' '; + term.grid_mut()[Line(0)][Column(3)].flags.insert(Flags::WIDE_CHAR_SPACER); + term.grid_mut()[Line(0)][Column(4)].c = 'x'; + term.grid_mut()[Line(0)][Column(5)].c = 'x'; + + // Test motion to the right. + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(0))); + cursor = cursor.motion(&mut term, ViMotion::SemanticRight); + assert_eq!(cursor.point, Point::new(Line(0), Column(2))); + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(2))); + cursor = cursor.motion(&mut term, ViMotion::SemanticRight); + assert_eq!(cursor.point, Point::new(Line(0), Column(4))); + + // Test motion to the left. + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(5))); + cursor = cursor.motion(&mut term, ViMotion::SemanticLeft); + assert_eq!(cursor.point, Point::new(Line(0), Column(4))); + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(4))); + cursor = cursor.motion(&mut term, ViMotion::SemanticLeft); + assert_eq!(cursor.point, Point::new(Line(0), Column(2))); + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(2))); + cursor = cursor.motion(&mut term, ViMotion::SemanticLeft); + assert_eq!(cursor.point, Point::new(Line(0), Column(0))); + } } |