use crate::sessions::types::ScreenState;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct TerminalEmulator {
parser: Arc<RwLock<vt100::Parser>>,
cols: u16,
rows: u16,
}
impl TerminalEmulator {
pub fn new(cols: u16, rows: u16) -> Self {
let parser = vt100::Parser::new(rows, cols, 1000); Self {
parser: Arc::new(RwLock::new(parser)),
cols,
rows,
}
}
pub async fn process(&self, data: &[u8]) {
let mut parser = self.parser.write().await;
parser.process(data);
}
pub async fn screen_state(&self) -> ScreenState {
let parser = self.parser.read().await;
let screen = parser.screen();
let mut lines = Vec::with_capacity(self.rows as usize);
for row in 0..self.rows {
let row_text = screen.contents_between(
row,
0,
row,
self.cols,
);
lines.push(row_text.trim_end().to_string());
}
let cursor = (screen.cursor_position().0, screen.cursor_position().1);
let alternate_screen = screen.alternate_screen();
let title_str = screen.title();
let title = if title_str.is_empty() { None } else { Some(title_str.to_string()) };
ScreenState {
lines,
cursor,
size: (self.cols, self.rows),
alternate_screen,
title,
}
}
pub async fn resize(&mut self, cols: u16, rows: u16) {
self.cols = cols;
self.rows = rows;
let mut parser = self.parser.write().await;
parser.set_size(rows, cols);
}
pub fn size(&self) -> (u16, u16) {
(self.cols, self.rows)
}
}