perf: avoid repeated scrollback page lookups (#4553)

refs #4506
This commit is contained in:
JJ Liebig
2026-09-24 21:22:51 +02:00
committed by GitHub
parent afd9e19893
commit 8d64c344db
+23 -9
View File
@@ -2946,12 +2946,12 @@ fn ghostty_recent_text_for_terminal(
terminal: &crate::ghostty::Terminal,
lines: usize,
) -> Result<String, crate::ghostty::Error> {
let Some((start, end, cols)) = ghostty_recent_read_range(terminal, lines)? else {
let Some((start, end, _)) = ghostty_recent_read_range(terminal, lines)? else {
return Ok(String::new());
};
let mut rows = Vec::with_capacity(end.saturating_sub(start).saturating_add(1));
for y in start..=end {
rows.push(ghostty_screen_row(terminal, cols, y as u32)?);
rows.push(ghostty_screen_row(terminal, y as u32)?);
}
trim_trailing_blank_rows(&mut rows);
Ok(recent_text_from_rows(&rows, lines))
@@ -3013,10 +3013,7 @@ fn ghostty_recent_read_range(
.min(total_rows.saturating_sub(1));
let mut last_content_row = None;
for row in (viewport_start..total_rows).rev() {
if !ghostty_screen_row(terminal, cols, row as u32)?
.trim()
.is_empty()
{
if !ghostty_screen_row(terminal, row as u32)?.trim().is_empty() {
last_content_row = Some(row);
break;
}
@@ -3056,12 +3053,15 @@ fn ghostty_extract_selection(
fn ghostty_screen_row(
terminal: &crate::ghostty::Terminal,
cols: u16,
y: u32,
) -> Result<String, crate::ghostty::Error> {
let mut line = String::new();
for x in 0..cols {
let (wide, graphemes) = terminal.screen_cell(x, y)?;
// Resolve the scrollback page once per row rather than once per column.
for crate::ghostty::ScreenTextCell { wide, graphemes } in terminal
.screen_text_rows_range(y as usize, y as usize + 1)?
.into_iter()
.flat_map(|row| row.cells)
{
if wide == crate::ghostty::CellWide::SpacerTail {
continue;
}
@@ -5807,6 +5807,20 @@ mod tests {
assert_eq!(pane.detection_text(), "日本語テスト ABC 123\n");
}
#[test]
fn recent_rows_preserve_combining_text_and_hide_image_placeholders() {
let (tx, _rx) = mpsc::channel(4);
let mut terminal = crate::ghostty::Terminal::new(40, 3, 1024 * 1024).unwrap();
terminal.write("old\r\n".repeat(100).as_bytes());
terminal.write("界 e\u{301} \u{10eeee} tail ".as_bytes());
let pane = GhosttyPaneTerminal::new(terminal, tx).unwrap();
assert_eq!(pane.recent_text(1), "界 e\u{301} tail\n");
let detection = pane.detection_text();
assert_eq!(detection, "old\nold\n界 e\u{301} tail\n");
pane.set_scroll_offset_from_bottom(100);
assert_eq!(pane.detection_text(), detection);
}
#[test]
fn visible_ansi_preserves_cell_style_sequences() {
let (tx, _rx) = mpsc::channel(4);