Skip to main content

rmux_core/
terminal_passthrough.rs

1use std::sync::Arc;
2
3/// Opaque terminal command that must be forwarded to a capable outer terminal.
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct TerminalPassthrough {
6    kind: TerminalPassthroughKind,
7    cursor_x: u32,
8    cursor_y: u32,
9    payload: Arc<[u8]>,
10}
11
12/// Supported terminal passthrough protocol families.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum TerminalPassthroughKind {
15    /// Kitty terminal graphics protocol, encoded as an APC payload.
16    KittyGraphics,
17}
18
19impl TerminalPassthrough {
20    /// Creates a Kitty graphics passthrough event at a pane-local cursor position.
21    #[must_use]
22    pub fn kitty_graphics(cursor_x: u32, cursor_y: u32, payload: impl Into<Vec<u8>>) -> Self {
23        Self {
24            kind: TerminalPassthroughKind::KittyGraphics,
25            cursor_x,
26            cursor_y,
27            payload: Arc::from(payload.into()),
28        }
29    }
30
31    /// Returns the passthrough protocol family.
32    #[must_use]
33    pub const fn kind(&self) -> TerminalPassthroughKind {
34        self.kind
35    }
36
37    /// Returns the pane-local cursor column captured when the sequence arrived.
38    #[must_use]
39    pub const fn cursor_x(&self) -> u32 {
40        self.cursor_x
41    }
42
43    /// Returns the pane-local cursor row captured when the sequence arrived.
44    #[must_use]
45    pub const fn cursor_y(&self) -> u32 {
46        self.cursor_y
47    }
48
49    /// Returns the opaque protocol payload without escape framing.
50    #[must_use]
51    pub fn payload(&self) -> &[u8] {
52        &self.payload
53    }
54
55    /// Renders the passthrough as an outer-terminal escape sequence.
56    #[must_use]
57    pub fn render_sequence(&self) -> Vec<u8> {
58        match self.kind {
59            TerminalPassthroughKind::KittyGraphics => {
60                let mut sequence = Vec::with_capacity(self.payload.len() + 4);
61                sequence.extend_from_slice(b"\x1b_");
62                sequence.extend_from_slice(&self.payload);
63                sequence.extend_from_slice(b"\x1b\\");
64                sequence
65            }
66        }
67    }
68}