pub struct PaneSnapshot {Show 13 fields
pub rows: usize,
pub cols: usize,
pub cells: Vec<Vec<Cell>>,
pub cursor_row: usize,
pub cursor_col: usize,
pub alt_screen_active: bool,
pub cursor_visible: bool,
pub title: Option<String>,
pub cursor_keys_mode: bool,
pub scrollback: Vec<Vec<Cell>>,
pub combining: Vec<Vec<char>>,
pub modes: ModeSet,
pub graphics: Vec<Graphic>,
}Expand description
Serializable snapshot of one pane’s visible grid + cursor. Sent over the tear-daemon ↔ tear-client wire so consumers can render without holding a reference into the live parser state.
Fields§
§rows: usize§cols: usize§cells: Vec<Vec<Cell>>§cursor_row: usize§cursor_col: usize§alt_screen_active: boolTrue when the alternate screen buffer is active (vim, less, htop, btop, etc. all enter this). Consumers may want to suppress scrollback rendering when alt-screen is on.
cursor_visible: boolCursor visibility (DEC mode 25). When false, renderers should not draw the cursor cell. Defaults to true (cursor shows by default per xterm semantics).
title: Option<String>Window/tab title set via OSC 0 / OSC 2. None until first title set; clears to None on RIS.
cursor_keys_mode: boolDECCKM (DEC mode 1) — cursor-keys application mode.
When true, the running program has requested application- mode cursor keys (ESC O A/B/C/D) instead of normal-mode (ESC [ A/B/C/D). Mado’s input encoder (and any other consumer that translates host keystrokes to PTY bytes) reads this to pick the right sequence so editors and pagers (vim, less, htop, …) receive the cursor keys they expect.
Resets to false on RIS (ESC c), DECSTR (ESC [ ! p), and when DECCKM is explicitly reset (ESC [ ? 1 l).
Serde default is false so wire payloads from older
daemons that don’t emit this field deserialize cleanly.
scrollback: Vec<Vec<Cell>>Bounded scrollback rows that have rolled off the top of the
primary screen, oldest first. Carried in the snapshot so a
consumer re-attaching to (or switching back to) a pane restores
its full history — without this, a session switch replays only
the visible grid and the scrollback is lost. Empty on the
alternate screen (vim/htop/less have no meaningful scrollback to
restore). #[serde(default)] so older wire payloads that omit
it deserialize cleanly to no scrollback.
combining: Vec<Vec<char>>Combining-mark table. Cell::combining indexes this 1-based
(0 = no marks), so entry n is at index n - 1.
Resolve through Cell::marks rather than indexing directly — it
handles the empty case and a short table without panicking.
Growth is bounded by history, not by time: entries accumulate as
marks are printed and are carried whole in the snapshot. For an
unbounded scrollback (tear’s default) that is the same order as the
text itself. For a bounded scrollback, entries belonging to
evicted rows are not reclaimed — a named follow-up
(pending-combining-gc), and the reason mado’s style/link tables
carry a gc that remaps live ids.
modes: ModeSetEvery terminal mode this pane was in at the instant these cells were taken.
Carried here rather than fetched separately, and that is the point:
a client that could ask for modes independently could render frame
N’s cells while encoding a keystroke under frame N+1’s modes —
bracketed paste toggling in the gap between the grid you drew and
the key you sent. Because a ModeSet is only obtainable from the
snapshot it came from, that skew has no representation.
See crate::modes for why each mode is its own type.
graphics: Vec<Graphic>Images transmitted into this pane, undecoded, in arrival order.
Carrying them is what makes the authority lossless: before this,
GridState implemented no DCS hook/put/unhook and vte
swallows APC in its SosPmApcString state, so every sixel and every
kitty image disappeared with no error and no flag — a renderer could
not even know content had been dropped.
Bytes, not pixels: see crate::graphics for why decoding stays
with the renderer and the daemon needs no image crate.
Implementations§
Source§impl PaneSnapshot
impl PaneSnapshot
Sourcepub fn to_text_rows(&self) -> Vec<String>
pub fn to_text_rows(&self) -> Vec<String>
Project to plain text — one String per row, blanks rendered as ASCII spaces. Drops color/attr information; useful for assertions and grep-style introspection.
Sourcepub fn to_ansi(&self) -> Vec<u8> ⓘ
pub fn to_ansi(&self) -> Vec<u8> ⓘ
Serialize the snapshot as a stream of ANSI bytes that, when fed into a fresh VT parser, reproduces the snapshot state (cells, colors, attrs, cursor, alt-screen, cursor-visibility).
The bug class this kills: a producer (tear pane) starts
emitting before a consumer (mado terminal model) attaches via
subscribe_pane_bytes. The early bytes (shell prompt, vim
initial frame) reach tear’s grid but never the consumer; the
consumer’s local model stays empty even though tear’s snapshot
shows the right content. Calling to_ansi() and feeding the
result into the consumer’s VT parser BEFORE the live byte
stream begins guarantees the consumer’s model matches the
producer’s grid at attach time.
Long-term home: this lives in engate as the canonical
“history replay” operation in the typed attach protocol —
EngateAttach<Synced> is constructed by feeding to_ansi()
bytes through the consumer’s parser, then subscribing to the
live stream.
Trait Implementations§
Source§impl Clone for PaneSnapshot
impl Clone for PaneSnapshot
Source§fn clone(&self) -> PaneSnapshot
fn clone(&self) -> PaneSnapshot
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for PaneSnapshot
impl Debug for PaneSnapshot
Source§impl<'de> Deserialize<'de> for PaneSnapshot
impl<'de> Deserialize<'de> for PaneSnapshot
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<PaneSnapshot, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<PaneSnapshot, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Serialize for PaneSnapshot
impl Serialize for PaneSnapshot
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for PaneSnapshot
impl RefUnwindSafe for PaneSnapshot
impl Send for PaneSnapshot
impl Sync for PaneSnapshot
impl Unpin for PaneSnapshot
impl UnsafeUnpin for PaneSnapshot
impl UnwindSafe for PaneSnapshot
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.