aboutsummaryrefslogtreecommitdiff
path: root/src/pane
diff options
context:
space:
mode:
authorAkira TSURUDA <jas39.gripen@gmail.com>2026-08-01 22:40:57 +0900
committerGitHub <noreply@github.com>2026-08-01 16:40:57 +0300
commitf459a0df315e0963aec5e4dcf2fc394a252ea320 (patch)
treed355041531395cdb0325b2fa5311d00fa2e45d32 /src/pane
parentf99647b2c2d7fbfd11269330a25ea4f9be59bafa (diff)
fix: expand copy-mode word-end window past a final wide glyph (#2145)
point_is_final_atom compared an atom's terminating column against a word-motion target's starting column. The two are equal for narrow cells but never for wide ones, so the read window stopped expanding and copy-mode `e` halted at the soft-wrap boundary on CJK text. Co-authored-by: Can Celik <ogulcancelik@gmail.com>
Diffstat (limited to 'src/pane')
-rw-r--r--src/pane/terminal.rs32
1 files changed, 28 insertions, 4 deletions
diff --git a/src/pane/terminal.rs b/src/pane/terminal.rs
index 3f8d8aea..e464554c 100644
--- a/src/pane/terminal.rs
+++ b/src/pane/terminal.rs
@@ -855,14 +855,14 @@ impl RetainedTextBuffer {
}
fn point_is_final_atom(&self, point: TerminalTextPoint) -> bool {
+ // Word motion targets are atom start points, so compare against the
+ // final atom's start point. Comparing against `end_col` would never
+ // match a wide glyph, whose end column is one past its start.
self.atoms
.iter()
.rev()
.find(|atom| atom.point.is_some())
- .is_some_and(|atom| {
- atom.point
- .is_some_and(|start| start.row == point.row && atom.end_col == point.col)
- })
+ .is_some_and(|atom| atom.point == Some(point))
}
}
@@ -3291,6 +3291,30 @@ mod tests {
);
}
+ #[test]
+ fn live_terminal_word_end_expands_through_a_long_wide_soft_wrap() {
+ let (tx, _rx) = mpsc::channel(4);
+ let mut terminal = crate::ghostty::Terminal::new(2, 3, 200).unwrap();
+ let word = "界".repeat(66);
+ terminal.write(word.as_bytes());
+ let pane = PaneTerminal::new(GhosttyPaneTerminal::new(terminal, tx).unwrap());
+ let text_match = pane.search_text_matches(&word, true)[0];
+
+ // The word end sits on the head cell of the final wide glyph, past the
+ // initial read window, so the window has to expand to reach it.
+ assert_eq!(
+ pane.word_motion_target(
+ text_match.start.row,
+ text_match.start.col,
+ TerminalWordMotion::NextEnd,
+ ),
+ Some(TerminalTextPoint {
+ row: text_match.end.row,
+ col: 0,
+ })
+ );
+ }
+
fn current_palette_color(pane: &GhosttyPaneTerminal, index: u8) -> crate::ghostty::RgbColor {
let mut core = pane.core.lock().unwrap();
let GhosttyPaneCore {