diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ghostty/mod.rs | 4 | ||||
| -rw-r--r-- | src/pane/terminal.rs | 53 |
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(); |
