use alacritty_terminal::event::VoidListener; use alacritty_terminal::grid::Dimensions; use alacritty_terminal::index::{Column, Line, Point}; use alacritty_terminal::term::{Config, Term}; use alacritty_terminal::vte::ansi::Processor; /// Fixed-size terminal dimensions for the daemon-side grid. #[derive(Clone, Copy)] pub struct GridSize { pub cols: usize, pub lines: usize, } impl Dimensions for GridSize { fn total_lines(&self) -> usize { self.lines } fn screen_lines(&self) -> usize { self.lines } fn columns(&self) -> usize { self.cols } } /// Owns an alacritty terminal model and feeds raw PTY bytes into it. pub struct GridSurface { term: Term, parser: Processor, size: GridSize, } impl GridSurface { pub fn new(cols: u16, rows: u16) -> Self { let size = GridSize { cols: cols as usize, lines: rows as usize }; let term = Term::new(Config::default(), &size, VoidListener); Self { term, parser: Processor::new(), size } } pub fn feed(&mut self, bytes: &[u8]) { self.parser.advance(&mut self.term, bytes); } pub fn resize(&mut self, cols: u16, rows: u16) { self.size = GridSize { cols: cols as usize, lines: rows as usize }; self.term.resize(self.size); } pub fn size(&self) -> GridSize { self.size } /// Read the visible character at (line, col) — used by tests and the snapshot writer. pub fn char_at(&self, line: usize, col: usize) -> char { let point = Point::new(Line(line as i32), Column(col)); self.term.grid()[point].c } pub fn term(&self) -> &Term { &self.term } } #[cfg(test)] mod tests { use super::*; #[test] fn feeding_plain_text_lands_in_the_grid() { let mut g = GridSurface::new(20, 5); g.feed(b"hello"); assert_eq!(g.char_at(0, 0), 'h'); assert_eq!(g.char_at(0, 4), 'o'); } #[test] fn carriage_return_and_newline_move_the_cursor() { let mut g = GridSurface::new(20, 5); g.feed(b"ab\r\ncd"); assert_eq!(g.char_at(0, 0), 'a'); assert_eq!(g.char_at(1, 0), 'c'); } }