aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-24 04:00:13 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-24 04:00:13 +0300
commitc0fb777ed7c7950c6a2f397113c1842c2e679306 (patch)
tree56a1b58314e292433946c1eed5c025abb832595f /src
parente608a75159fc5cca70485d83ffb8ee681c9da385 (diff)
fix: report truncated pane reads
refs #1717
Diffstat (limited to 'src')
-rw-r--r--src/app/api/agents.rs6
-rw-r--r--src/app/api/panes.rs28
-rw-r--r--src/app/api_helpers.rs83
-rw-r--r--src/pane.rs20
-rw-r--r--src/pane/terminal.rs136
-rw-r--r--src/pane/terminal/windows_recent_fallback.rs50
-rw-r--r--src/terminal/runtime.rs25
7 files changed, 248 insertions, 100 deletions
diff --git a/src/app/api/agents.rs b/src/app/api/agents.rs
index ffb9cb63..f1977ce4 100644
--- a/src/app/api/agents.rs
+++ b/src/app/api/agents.rs
@@ -117,7 +117,7 @@ impl App {
else {
return agent_not_found(id, &params.target);
};
- let text = crate::app::api_helpers::read_terminal_snapshot(
+ let snapshot = crate::app::api_helpers::read_terminal_snapshot(
pane,
params.source,
params.format,
@@ -137,9 +137,9 @@ impl App {
.unwrap(),
source: params.source,
format: params.format,
- text,
+ text: snapshot.text,
revision: 0,
- truncated: false,
+ truncated: snapshot.truncated,
},
},
)
diff --git a/src/app/api/panes.rs b/src/app/api/panes.rs
index 43206d1e..253fd627 100644
--- a/src/app/api/panes.rs
+++ b/src/app/api/panes.rs
@@ -1179,7 +1179,7 @@ impl App {
else {
return pane_not_found(id, &params.pane_id);
};
- let text = crate::app::api_helpers::read_terminal_snapshot(
+ let snapshot = crate::app::api_helpers::read_terminal_snapshot(
pane,
params.source,
params.format,
@@ -1195,9 +1195,9 @@ impl App {
tab_id: self.public_tab_id(ws_idx, tab_idx).unwrap(),
source: params.source,
format: params.format,
- text,
+ text: snapshot.text,
revision: 0,
- truncated: false,
+ truncated: snapshot.truncated,
},
},
)
@@ -2002,6 +2002,28 @@ mod tests {
}
#[tokio::test]
+ async fn api_pane_read_reports_when_older_rows_are_omitted() {
+ let (mut app, public_pane_id, _pane_id) = app_with_scrollback_runtime();
+
+ let response = app.handle_pane_read(
+ "req".into(),
+ PaneReadParams {
+ pane_id: public_pane_id,
+ source: crate::api::schema::ReadSource::Recent,
+ lines: Some(2),
+ format: crate::api::schema::ReadFormat::Text,
+ strip_ansi: true,
+ },
+ );
+ let success: SuccessResponse = serde_json::from_str(&response).unwrap();
+ let ResponseResult::PaneRead { read } = success.result else {
+ panic!("expected pane read response");
+ };
+ assert!(read.text.contains("line 19"));
+ assert!(read.truncated);
+ }
+
+ #[tokio::test]
async fn api_pane_send_keys_preserves_legacy_control_c_aliases() {
let (mut app, pane_id, mut rx) = app_with_send_key_runtime(3);
diff --git a/src/app/api_helpers.rs b/src/app/api_helpers.rs
index 6c393dac..e0091b39 100644
--- a/src/app/api_helpers.rs
+++ b/src/app/api_helpers.rs
@@ -106,50 +106,77 @@ pub(super) fn read_terminal_snapshot(
source: crate::api::schema::ReadSource,
format: crate::api::schema::ReadFormat,
lines: Option<u32>,
-) -> String {
+) -> crate::pane::TerminalReadSnapshot {
use crate::api::schema::{ReadFormat, ReadSource};
- let requested_lines = lines.unwrap_or(80).min(1000) as usize;
- let text = match (format, source) {
- (ReadFormat::Text, ReadSource::Visible) => terminal.visible_text(),
- (ReadFormat::Text, ReadSource::Recent) => terminal.recent_text(requested_lines),
+ let line_limit = lines.map(|lines| lines.min(1000) as usize);
+ let recent_lines = line_limit.unwrap_or(80);
+ match (format, source) {
+ (ReadFormat::Text, ReadSource::Visible) => {
+ limit_snapshot_lines(terminal.visible_text(), line_limit)
+ }
+ (ReadFormat::Text, ReadSource::Recent) => terminal.recent_text_snapshot(recent_lines),
(ReadFormat::Text, ReadSource::RecentUnwrapped) => {
- terminal.recent_unwrapped_text(requested_lines)
+ terminal.recent_unwrapped_text_snapshot(recent_lines)
+ }
+ (ReadFormat::Text, ReadSource::Detection) => {
+ limit_snapshot_lines(terminal.detection_text(), line_limit)
+ }
+ (ReadFormat::Ansi, ReadSource::Visible) => {
+ limit_snapshot_lines(terminal.visible_ansi(), line_limit)
}
- (ReadFormat::Text, ReadSource::Detection) => terminal.detection_text(),
- (ReadFormat::Ansi, ReadSource::Visible) => terminal.visible_ansi(),
- (ReadFormat::Ansi, ReadSource::Recent) => terminal.recent_ansi(requested_lines),
+ (ReadFormat::Ansi, ReadSource::Recent) => terminal.recent_ansi_snapshot(recent_lines),
(ReadFormat::Ansi, ReadSource::RecentUnwrapped) => {
- terminal.recent_unwrapped_ansi(requested_lines)
+ terminal.recent_unwrapped_ansi_snapshot(recent_lines)
+ }
+ (ReadFormat::Ansi, ReadSource::Detection) => {
+ limit_snapshot_lines(terminal.detection_text(), line_limit)
}
- (ReadFormat::Ansi, ReadSource::Detection) => terminal.detection_text(),
- };
-
- if lines.is_some() && matches!(source, ReadSource::Visible | ReadSource::Detection) {
- last_lines(&text, requested_lines)
- } else {
- text
}
}
-fn last_lines(text: &str, count: usize) -> String {
- if text.is_empty() || count == 0 {
- return String::new();
- }
+fn limit_snapshot_lines(text: String, limit: Option<usize>) -> crate::pane::TerminalReadSnapshot {
+ let Some(limit) = limit else {
+ return crate::pane::TerminalReadSnapshot {
+ text,
+ truncated: false,
+ };
+ };
let lines: Vec<_> = text.split_inclusive('\n').collect();
- lines[lines.len().saturating_sub(count)..].concat()
+ crate::pane::TerminalReadSnapshot {
+ text: lines[lines.len().saturating_sub(limit)..].concat(),
+ truncated: lines.len() > limit,
+ }
}
#[cfg(test)]
mod read_snapshot_tests {
- use super::last_lines;
+ use super::limit_snapshot_lines;
+
+ #[test]
+ fn line_limit_preserves_endings_and_reports_omitted_lines() {
+ let snapshot = limit_snapshot_lines("one\ntwø\n三\n".into(), Some(2));
+ assert_eq!(snapshot.text, "twø\n三\n");
+ assert!(snapshot.truncated);
+
+ let snapshot = limit_snapshot_lines("one\ntwo\nthree".into(), Some(1));
+ assert_eq!(snapshot.text, "three");
+ assert!(snapshot.truncated);
+
+ let snapshot = limit_snapshot_lines("one\ntwo".into(), Some(0));
+ assert_eq!(snapshot.text, "");
+ assert!(snapshot.truncated);
+
+ let snapshot = limit_snapshot_lines("".into(), Some(2));
+ assert_eq!(snapshot.text, "");
+ assert!(!snapshot.truncated);
+ }
#[test]
- fn last_lines_preserves_real_line_endings_and_unicode() {
- assert_eq!(last_lines("one\ntwø\n三\n", 2), "twø\n三\n");
- assert_eq!(last_lines("one\ntwo\nthree", 1), "three");
- assert_eq!(last_lines("one\ntwo", 0), "");
- assert_eq!(last_lines("", 2), "");
+ fn omitted_line_limit_returns_the_complete_snapshot() {
+ let snapshot = limit_snapshot_lines("one\ntwo\n".into(), None);
+ assert_eq!(snapshot.text, "one\ntwo\n");
+ assert!(!snapshot.truncated);
}
}
diff --git a/src/pane.rs b/src/pane.rs
index ea6a13fd..45f4f720 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -41,8 +41,8 @@ use self::agent_detection::{
};
use self::terminal::{GhosttyPaneTerminal, PaneTerminal};
pub(crate) use self::terminal::{
- TerminalDirtyPatch, TerminalDirtyPatchOutcome, TerminalTextMatch, TerminalTextPoint,
- TerminalWordMotion,
+ TerminalDirtyPatch, TerminalDirtyPatchOutcome, TerminalReadSnapshot, TerminalTextMatch,
+ TerminalTextPoint, TerminalWordMotion,
};
pub use self::{
state::PaneState,
@@ -2552,18 +2552,26 @@ impl PaneRuntime {
self.terminal.recent_text(lines)
}
- pub fn recent_ansi(&self, lines: usize) -> String {
- self.terminal.recent_ansi(lines)
+ pub(crate) fn recent_text_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.terminal.recent_text_snapshot(lines)
}
- pub fn recent_unwrapped_text(&self, lines: usize) -> String {
- self.terminal.recent_unwrapped_text(lines)
+ pub(crate) fn recent_ansi_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.terminal.recent_ansi_snapshot(lines)
+ }
+
+ pub(crate) fn recent_unwrapped_text_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.terminal.recent_unwrapped_text_snapshot(lines)
}
pub fn recent_unwrapped_ansi(&self, lines: usize) -> String {
self.terminal.recent_unwrapped_ansi(lines)
}
+ pub(crate) fn recent_unwrapped_ansi_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.terminal.recent_unwrapped_ansi_snapshot(lines)
+ }
+
pub fn snapshot_history(&self) -> Option<String> {
let ansi = self.recent_unwrapped_ansi(usize::MAX);
(!ansi.trim().is_empty()).then_some(ansi)
diff --git a/src/pane/terminal.rs b/src/pane/terminal.rs
index 81c57ef9..d5070b9b 100644
--- a/src/pane/terminal.rs
+++ b/src/pane/terminal.rs
@@ -141,6 +141,12 @@ pub(crate) struct ProcessBytesResult {
pub terminal_responses: Vec<Bytes>,
}
+#[derive(Debug, Clone, PartialEq, Eq, Default)]
+pub(crate) struct TerminalReadSnapshot {
+ pub text: String,
+ pub truncated: bool,
+}
+
pub(crate) struct GhosttyPaneTerminal {
pub core: Mutex<GhosttyPaneCore>,
key_encoder: Mutex<crate::ghostty::KeyEncoder>,
@@ -387,18 +393,26 @@ impl PaneTerminal {
self.ghostty.recent_text(lines)
}
- pub fn recent_ansi(&self, lines: usize) -> String {
- self.ghostty.recent_ansi(lines)
+ pub(crate) fn recent_text_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.ghostty.recent_text_snapshot(lines)
}
- pub fn recent_unwrapped_text(&self, lines: usize) -> String {
- self.ghostty.recent_unwrapped_text(lines)
+ pub(crate) fn recent_ansi_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.ghostty.recent_ansi_snapshot(lines)
+ }
+
+ pub(crate) fn recent_unwrapped_text_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.ghostty.recent_unwrapped_text_snapshot(lines)
}
pub fn recent_unwrapped_ansi(&self, lines: usize) -> String {
self.ghostty.recent_unwrapped_ansi(lines)
}
+ pub(crate) fn recent_unwrapped_ansi_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
+ self.ghostty.recent_unwrapped_ansi_snapshot(lines)
+ }
+
pub fn extract_selection(&self, selection: &crate::selection::Selection) -> Option<String> {
self.ghostty.extract_selection(selection)
}
@@ -1708,34 +1722,52 @@ impl GhosttyPaneTerminal {
}
pub fn recent_text(&self, lines: usize) -> String {
+ self.recent_text_snapshot(lines).text
+ }
+
+ pub(crate) fn recent_text_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
self.core
.lock()
.ok()
- .and_then(|core| ghostty_recent_text(&core, lines).ok())
+ .and_then(|core| ghostty_recent_text_snapshot(&core, lines).ok())
.unwrap_or_default()
}
+ #[cfg(test)]
pub fn recent_ansi(&self, lines: usize) -> String {
+ self.recent_ansi_snapshot(lines).text
+ }
+
+ pub(crate) fn recent_ansi_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
self.core
.lock()
.ok()
- .and_then(|core| ghostty_recent_ansi(&core, lines, false).ok())
+ .and_then(|core| ghostty_recent_ansi_snapshot(&core, lines, false).ok())
.unwrap_or_default()
}
+ #[cfg(test)]
pub fn recent_unwrapped_text(&self, lines: usize) -> String {
+ self.recent_unwrapped_text_snapshot(lines).text
+ }
+
+ pub(crate) fn recent_unwrapped_text_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
self.core
.lock()
.ok()
- .and_then(|core| ghostty_recent_text_unwrapped(&core, lines).ok())
+ .and_then(|core| ghostty_recent_text_unwrapped_snapshot(&core, lines).ok())
.unwrap_or_default()
}
pub fn recent_unwrapped_ansi(&self, lines: usize) -> String {
+ self.recent_unwrapped_ansi_snapshot(lines).text
+ }
+
+ pub(crate) fn recent_unwrapped_ansi_snapshot(&self, lines: usize) -> TerminalReadSnapshot {
self.core
.lock()
.ok()
- .and_then(|core| ghostty_recent_ansi(&core, lines, true).ok())
+ .and_then(|core| ghostty_recent_ansi_snapshot(&core, lines, true).ok())
.unwrap_or_default()
}
@@ -2289,34 +2321,23 @@ fn ghostty_recent_text(
core: &GhosttyPaneCore,
lines: usize,
) -> Result<String, crate::ghostty::Error> {
+ ghostty_recent_text_snapshot(core, lines).map(|snapshot| snapshot.text)
+}
+
+fn ghostty_recent_text_snapshot(
+ core: &GhosttyPaneCore,
+ lines: usize,
+) -> Result<TerminalReadSnapshot, crate::ghostty::Error> {
let text = ghostty_recent_text_for_terminal(&core.terminal, lines)?;
- #[cfg(windows)]
- {
- if text.trim().is_empty() {
- let fallback = windows_recent_fallback::recent_text(core, lines, false);
- if !fallback.trim().is_empty() {
- return Ok(fallback);
- }
- }
- }
- Ok(text)
+ Ok(finish_recent_snapshot(core, text, lines, false))
}
-fn ghostty_recent_text_unwrapped(
+fn ghostty_recent_text_unwrapped_snapshot(
core: &GhosttyPaneCore,
lines: usize,
-) -> Result<String, crate::ghostty::Error> {
+) -> Result<TerminalReadSnapshot, crate::ghostty::Error> {
let text = ghostty_recent_text_unwrapped_for_terminal(&core.terminal, lines)?;
- #[cfg(windows)]
- {
- if text.trim().is_empty() {
- let fallback = windows_recent_fallback::recent_text(core, lines, true);
- if !fallback.trim().is_empty() {
- return Ok(fallback);
- }
- }
- }
- Ok(text)
+ Ok(finish_recent_snapshot(core, text, lines, true))
}
fn ghostty_recent_ansi(
@@ -2324,17 +2345,42 @@ fn ghostty_recent_ansi(
lines: usize,
unwrap: bool,
) -> Result<String, crate::ghostty::Error> {
- let ansi = ghostty_recent_ansi_for_terminal(&core.terminal, lines, unwrap)?;
+ ghostty_recent_ansi_snapshot(core, lines, unwrap).map(|snapshot| snapshot.text)
+}
+
+fn ghostty_recent_ansi_snapshot(
+ core: &GhosttyPaneCore,
+ lines: usize,
+ unwrap: bool,
+) -> Result<TerminalReadSnapshot, crate::ghostty::Error> {
+ let text = ghostty_recent_ansi_for_terminal(&core.terminal, lines, unwrap)?;
+ Ok(finish_recent_snapshot(core, text, lines, unwrap))
+}
+
+fn finish_recent_snapshot(
+ core: &GhosttyPaneCore,
+ text: String,
+ lines: usize,
+ unwrap: bool,
+) -> TerminalReadSnapshot {
+ #[cfg(not(windows))]
+ let _ = unwrap;
#[cfg(windows)]
- {
- if ansi.trim().is_empty() {
- let fallback = windows_recent_fallback::recent_text(core, lines, unwrap);
- if !fallback.trim().is_empty() {
- return Ok(fallback);
- }
+ if text.trim().is_empty() {
+ let fallback = windows_recent_fallback::recent_text(core, lines, unwrap);
+ if !fallback.text.trim().is_empty() {
+ return fallback;
}
}
- Ok(ansi)
+
+ // Recent read limits are measured in rendered rows, including blank or styled rows.
+ TerminalReadSnapshot {
+ text,
+ truncated: core
+ .terminal
+ .total_rows()
+ .is_ok_and(|total_rows| total_rows > lines),
+ }
}
fn ghostty_recent_text_for_terminal(
@@ -4342,6 +4388,20 @@ mod tests {
}
#[test]
+ fn recent_snapshots_report_omitted_rendered_rows() {
+ let (tx, _rx) = mpsc::channel(4);
+ let mut terminal = crate::ghostty::Terminal::new(20, 3, 100).unwrap();
+ terminal.write(b"one\r\ntwo\r\nthree\r\nfour");
+ let pane = GhosttyPaneTerminal::new(terminal, tx).unwrap();
+
+ assert!(pane.recent_text_snapshot(2).truncated);
+ assert!(pane.recent_ansi_snapshot(2).truncated);
+ assert!(pane.recent_unwrapped_text_snapshot(2).truncated);
+ assert!(pane.recent_unwrapped_ansi_snapshot(2).truncated);
+ assert!(!pane.recent_text_snapshot(100).truncated);
+ }
+
+ #[test]
fn plain_text_reads_skip_wide_character_spacer_cells() {
let (tx, _rx) = mpsc::channel(4);
let mut terminal = crate::ghostty::Terminal::new(40, 3, 100).unwrap();
diff --git a/src/pane/terminal/windows_recent_fallback.rs b/src/pane/terminal/windows_recent_fallback.rs
index c9a02f67..caa3b9f7 100644
--- a/src/pane/terminal/windows_recent_fallback.rs
+++ b/src/pane/terminal/windows_recent_fallback.rs
@@ -1,4 +1,4 @@
-use super::{ghostty_line_from_cells, GhosttyPaneCore};
+use super::{ghostty_line_from_cells, GhosttyPaneCore, TerminalReadSnapshot};
const CACHE_LINES: usize = 2000;
@@ -44,9 +44,13 @@ pub(super) fn update(core: &mut GhosttyPaneCore) {
core.recent_fallback.usable = true;
}
-pub(super) fn recent_text(core: &GhosttyPaneCore, lines: usize, unwrap: bool) -> String {
+pub(super) fn recent_text(
+ core: &GhosttyPaneCore,
+ lines: usize,
+ unwrap: bool,
+) -> TerminalReadSnapshot {
if !primary_screen_active(core) {
- return String::new();
+ return TerminalReadSnapshot::default();
}
if unwrap {
unwrapped_text(core, lines)
@@ -62,9 +66,9 @@ fn primary_screen_active(core: &GhosttyPaneCore) -> bool {
)
}
-fn wrapped_text(core: &GhosttyPaneCore, lines: usize) -> String {
+fn wrapped_text(core: &GhosttyPaneCore, lines: usize) -> TerminalReadSnapshot {
if !core.recent_fallback.usable {
- return String::new();
+ return TerminalReadSnapshot::default();
}
let rows: Vec<&str> = core
.recent_fallback
@@ -72,16 +76,24 @@ fn wrapped_text(core: &GhosttyPaneCore, lines: usize) -> String {
.iter()
.map(|line| line.text.as_str())
.collect();
- cache_text(&rows, lines)
+ TerminalReadSnapshot {
+ text: cache_text(&rows, lines),
+ truncated: rows.len() > lines,
+ }
}
-fn unwrapped_text(core: &GhosttyPaneCore, lines: usize) -> String {
+fn unwrapped_text(core: &GhosttyPaneCore, lines: usize) -> TerminalReadSnapshot {
if !core.recent_fallback.usable {
- return String::new();
+ return TerminalReadSnapshot::default();
}
- let unwrapped = unwrap_render_lines(&core.recent_fallback.rows);
+ let rendered_rows = &core.recent_fallback.rows;
+ let start = rendered_rows.len().saturating_sub(lines);
+ let unwrapped = unwrap_render_lines(&rendered_rows[start..]);
let rows: Vec<&str> = unwrapped.iter().map(String::as_str).collect();
- cache_text(&rows, lines)
+ TerminalReadSnapshot {
+ text: cache_text(&rows, rows.len()),
+ truncated: rendered_rows.len() > lines,
+ }
}
fn viewport_is_at_bottom(core: &GhosttyPaneCore) -> bool {
@@ -298,8 +310,8 @@ mod tests {
pane.process_pty_bytes(pane_id, 0, b"new output\r\n", &tx);
let core = pane.core.lock().unwrap();
- assert_eq!(recent_text(&core, 3, false), "");
- assert_eq!(recent_text(&core, 3, true), "");
+ assert_eq!(recent_text(&core, 3, false).text, "");
+ assert_eq!(recent_text(&core, 3, true).text, "");
}
#[test]
@@ -311,12 +323,12 @@ mod tests {
pane.seed_history_ansi("seeded history\r\n");
let core = pane.core.lock().unwrap();
- assert!(recent_text(&core, 3, false).contains("seeded history"));
- assert!(recent_text(&core, 3, true).contains("seeded history"));
+ assert!(recent_text(&core, 3, false).text.contains("seeded history"));
+ assert!(recent_text(&core, 3, true).text.contains("seeded history"));
}
#[test]
- fn recent_ansi_unwrapped_uses_unwrapped_render_cache() {
+ fn recent_ansi_unwrapped_limits_rendered_rows_before_unwrapping() {
let (tx, _rx) = mpsc::channel(4);
let terminal = crate::ghostty::Terminal::new(40, 3, 1024).unwrap();
let pane = GhosttyPaneTerminal::new(terminal, tx).unwrap();
@@ -324,13 +336,17 @@ mod tests {
{
let mut core = pane.core.lock().unwrap();
core.recent_fallback.rows = vec![
+ rendered_line("older", false, false),
rendered_line("wrapped", true, false),
rendered_line("rows", false, true),
+ rendered_line("last", false, false),
];
core.recent_fallback.usable = true;
}
- assert_eq!(pane.recent_ansi(2), "wrapped\nrows\n");
- assert_eq!(pane.recent_unwrapped_ansi(2), "wrappedrows\n");
+ let snapshot = pane.recent_unwrapped_ansi_snapshot(3);
+ assert_eq!(snapshot.text, "wrappedrows\nlast\n");
+ assert!(snapshot.truncated);
+ assert_eq!(pane.recent_ansi(3), "wrapped\nrows\nlast\n");
}
}
diff --git a/src/terminal/runtime.rs b/src/terminal/runtime.rs
index 0241f984..cd6f4211 100644
--- a/src/terminal/runtime.rs
+++ b/src/terminal/runtime.rs
@@ -334,16 +334,31 @@ impl TerminalRuntime {
self.0.recent_text(lines)
}
- pub fn recent_ansi(&self, lines: usize) -> String {
- self.0.recent_ansi(lines)
+ pub(crate) fn recent_text_snapshot(&self, lines: usize) -> crate::pane::TerminalReadSnapshot {
+ self.0.recent_text_snapshot(lines)
}
+ pub(crate) fn recent_ansi_snapshot(&self, lines: usize) -> crate::pane::TerminalReadSnapshot {
+ self.0.recent_ansi_snapshot(lines)
+ }
+
+ #[cfg(test)]
pub fn recent_unwrapped_text(&self, lines: usize) -> String {
- self.0.recent_unwrapped_text(lines)
+ self.0.recent_unwrapped_text_snapshot(lines).text
}
- pub fn recent_unwrapped_ansi(&self, lines: usize) -> String {
- self.0.recent_unwrapped_ansi(lines)
+ pub(crate) fn recent_unwrapped_text_snapshot(
+ &self,
+ lines: usize,
+ ) -> crate::pane::TerminalReadSnapshot {
+ self.0.recent_unwrapped_text_snapshot(lines)
+ }
+
+ pub(crate) fn recent_unwrapped_ansi_snapshot(
+ &self,
+ lines: usize,
+ ) -> crate::pane::TerminalReadSnapshot {
+ self.0.recent_unwrapped_ansi_snapshot(lines)
}
pub fn snapshot_history(&self) -> Option<String> {