command_stream/terminal/
buffer.rs1use tokio::sync::broadcast;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct BufferFrame {
6 pub text: String,
7 pub ansi: Vec<u8>,
8 pub rows: u16,
9 pub cols: u16,
10 pub cursor: (u16, u16),
11 pub alternate: bool,
12}
13
14pub struct TerminalBuffer {
15 parser: vt100::Parser,
16 previous: BufferFrame,
17 frames: broadcast::Sender<BufferFrame>,
18}
19
20impl TerminalBuffer {
21 pub fn new(rows: u16, cols: u16) -> Self {
22 assert!(rows > 0 && cols > 0 && u32::from(rows) * u32::from(cols) <= 1_000_000);
23 let parser = vt100::Parser::new(rows, cols, 1000);
24 let previous = Self::frame(&parser);
25 let (frames, _) = broadcast::channel(16);
26 Self {
27 parser,
28 previous,
29 frames,
30 }
31 }
32 fn frame(parser: &vt100::Parser) -> BufferFrame {
33 let screen = parser.screen();
34 let (rows, cols) = screen.size();
35 BufferFrame {
36 text: screen.contents(),
37 ansi: screen.contents_formatted(),
38 rows,
39 cols,
40 cursor: screen.cursor_position(),
41 alternate: screen.alternate_screen(),
42 }
43 }
44 pub fn snapshot(&self) -> BufferFrame {
45 Self::frame(&self.parser)
46 }
47 pub fn text(&self, color: bool) -> String {
48 if color {
49 String::from_utf8_lossy(&self.parser.screen().contents_formatted()).into_owned()
50 } else {
51 self.parser.screen().contents()
52 }
53 }
54 pub fn subscribe(&self) -> broadcast::Receiver<BufferFrame> {
55 self.frames.subscribe()
56 }
57 pub fn write(&mut self, data: &[u8]) {
58 self.parser.process(data);
59 self.flush();
60 }
61 pub fn resize(&mut self, rows: u16, cols: u16) {
62 assert!(rows > 0 && cols > 0 && u32::from(rows) * u32::from(cols) <= 1_000_000);
63 self.parser.screen_mut().set_size(rows, cols);
64 self.flush();
65 }
66 pub fn flush(&mut self) {
67 let frame = self.snapshot();
68 if frame != self.previous {
69 self.previous = frame.clone();
70 let _ = self.frames.send(frame);
71 }
72 }
73}