aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-09-02 23:19:59 +0300
committerGitHub <noreply@github.com>2026-09-02 23:19:59 +0300
commit45484aab84430ac2b18c7bbf44aba15f2b039677 (patch)
tree58f289bf743ed3de0c2179e3d290b17e265e5372
parente22cba35ef7b405758097a5f9436aae8fb4caaf0 (diff)
fix: include short viewport output in recent reads (#3448)
refs #3444 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
-rw-r--r--src/ghostty/mod.rs4
-rw-r--r--src/pane/terminal.rs53
2 files changed, 56 insertions, 1 deletions
diff --git a/src/ghostty/mod.rs b/src/ghostty/mod.rs
index c044d3b0..261638af 100644
--- a/src/ghostty/mod.rs
+++ b/src/ghostty/mod.rs
@@ -1412,6 +1412,10 @@ impl Terminal {
self.get_u16(ffi::GhosttyTerminalData_GHOSTTY_TERMINAL_DATA_ROWS)
}
+ pub fn cursor_y(&self) -> Result<u16, Error> {
+ self.get_u16(ffi::GhosttyTerminalData_GHOSTTY_TERMINAL_DATA_CURSOR_Y)
+ }
+
pub fn effective_foreground_color(&self) -> Result<Option<RgbColor>, Error> {
self.get_optional_rgb_color(TERMINAL_DATA_COLOR_FOREGROUND)
}
diff --git a/src/pane/terminal.rs b/src/pane/terminal.rs
index df84e5cb..154a9539 100644
--- a/src/pane/terminal.rs
+++ b/src/pane/terminal.rs
@@ -2807,7 +2807,34 @@ fn ghostty_recent_read_range(
if total_rows == 0 || cols == 0 || lines == 0 {
return Ok(None);
}
- let end = total_rows.saturating_sub(1);
+
+ let physical_end = total_rows.saturating_sub(1);
+ if terminal.active_screen()? != crate::ghostty::ActiveScreen::Primary {
+ let start = physical_end.saturating_add(1).saturating_sub(lines);
+ return Ok(Some((start, physical_end, cols)));
+ }
+
+ let rows = usize::from(terminal.rows()?);
+ if rows == 0 {
+ return Ok(None);
+ }
+ let viewport_start = total_rows.saturating_sub(rows);
+ let cursor_row = viewport_start
+ .saturating_add(usize::from(terminal.cursor_y()?))
+ .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()
+ {
+ last_content_row = Some(row);
+ break;
+ }
+ }
+ let end = last_content_row
+ .map(|row| row.max(cursor_row))
+ .unwrap_or_else(|| total_rows.saturating_sub(1));
let start = end.saturating_add(1).saturating_sub(lines);
Ok(Some((start, end, cols)))
}
@@ -5243,6 +5270,30 @@ mod tests {
}
#[test]
+ fn recent_reads_include_viewport_before_scrollback_exists() {
+ let (tx, _rx) = mpsc::channel(4);
+ let mut terminal =
+ crate::ghostty::Terminal::new(20, 20, crate::config::DEFAULT_SCROLLBACK_LIMIT_BYTES)
+ .unwrap();
+ terminal.write(b"hello123");
+ let pane = GhosttyPaneTerminal::new(terminal, tx).unwrap();
+
+ assert_eq!(pane.recent_text(3), "hello123\n");
+ assert_eq!(pane.recent_unwrapped_text(3), "hello123");
+ }
+
+ #[test]
+ fn alternate_screen_recent_reads_keep_physical_row_ranges() {
+ let (tx, _rx) = mpsc::channel(4);
+ let mut terminal = crate::ghostty::Terminal::new(20, 20, 100).unwrap();
+ terminal.write(b"\x1b[?1049hhello123");
+ let pane = GhosttyPaneTerminal::new(terminal, tx).unwrap();
+
+ assert_eq!(pane.recent_text(3), "");
+ assert_eq!(pane.recent_unwrapped_text(3), "");
+ }
+
+ #[test]
fn recent_unwrapped_text_ignores_soft_wraps() {
let (tx, _rx) = mpsc::channel(4);
let mut terminal = crate::ghostty::Terminal::new(5, 3, 100).unwrap();