small software-rendered rust tty
recognize DECSTBM
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/term.rs | 15 | ||||
| -rw-r--r-- | src/term/cells.rs | 80 |
3 files changed, 90 insertions, 6 deletions
diff --git a/src/main.rs b/src/main.rs index fadd92b..460616c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ #![feature( + debug_closure_helpers, const_trait_impl, generic_assert, deadline_api, diff --git a/src/term.rs b/src/term.rs index 6afd9b4..8e42781 100644 --- a/src/term.rs +++ b/src/term.rs @@ -259,6 +259,21 @@ impl Terminal { let count = p.value_or(1); self.cells.delete_chars(count, self.cursor); } + //decstbm + Control(ControlFunction { + start: b'[', + params: v, + end: b'r', + .. + }) => { + self.cells.margin = match v { + [t, b] => (t.value_or(1), b.value_or(self.cells.r())), + _ => (1, self.cells.r()), + }; + self.cursor = (1, 1); + assert!(self.cells.margin.0 < self.cells.margin.1); + } + Control(ControlFunction { start: b'[', params: [x], diff --git a/src/term/cells.rs b/src/term/cells.rs index 2bea8bb..26e56b7 100644 --- a/src/term/cells.rs +++ b/src/term/cells.rs @@ -2,6 +2,7 @@ pub struct Cells { pub size: (u16, u16), pub cells: Vec<Cell>, + pub margin: (u16, u16), pub row: u16, } #[derive(Clone, Copy, Debug)] @@ -11,6 +12,7 @@ pub struct Style { pub flags: u8, } use std::default::Default::default; +use std::fmt::Debug; use std::iter::{empty, repeat, repeat_n}; use crate::colors; @@ -24,17 +26,49 @@ impl std::default::Default for Style { } } -#[derive(Clone, Copy, Default, Debug)] +#[derive(Clone, Copy, Default)] pub struct Cell { pub style: Style, pub letter: Option<char>, } +impl Debug for Cell { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.letter.unwrap_or(' ')) + } +} +impl Debug for Cells { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Cells") + .field("size", &self.size) + .field("margin", &self.margin) + .field("row", &self.row) + .field_with("cells", |x| { + for r in self.cells + [{ self.row as usize * self.size.0 as usize }..] + .chunks_exact(self.size.0 as _) + { + writeln!(x, "{r:?}")?; + } + Ok(()) + }) + .finish() + } +} +impl Cell { + pub fn basic(c: char) -> Self { + Self { + letter: Some(c), + ..default() + } + } +} impl Cells { pub fn new((c, r): (u16, u16)) -> Self { let (c, r) = (c + 1, r + 1); Self { size: (c, r), + margin: (1, r), cells: vec![Cell::default(); (c as usize) * (r as usize)], row: 0, } @@ -80,12 +114,16 @@ impl Cells { } pub fn grow(&mut self, by: u16) { self.row += by; - self.cells.extend(repeat_n( - Cell::default(), - by as usize * (self.size.0) as usize, - )); + let at = self.offset() + + (self.margin.1 as usize - 1) * self.size.0 as usize; + self.cells.splice( + at..at, + repeat_n( + Cell::default(), + by as usize * (self.size.0) as usize, + ), + ); } - pub fn insert_chars(&mut self, characters: u16, (x, y): (u16, u16)) { let s = &mut self.row(y)[x as usize - 1..]; s.rotate_right(characters as usize); @@ -115,5 +153,35 @@ impl Cells { self.cells .drain(o + self.size.0 as usize * self.size.1 as usize..) .for_each(drop); + // let at = self.offset() + self.margin.1 as usize; + // self.cells + // .drain( + // (o + self.size.0 as usize * self.size.1 as usize) - at..at, + // ) + // .for_each(drop); + } +} + +#[cfg(test)] +mod test { + use crate::term::cells::{Cell, Cells}; + + #[test] + fn grow() { + let mut cells = Cells::new((4, 4)); + cells.row(1).fill(Cell::basic('1')); + cells.row(2).fill(Cell::basic('2')); + cells.row(3).fill(Cell::basic('3')); + cells.row(4).fill(Cell::basic('4')); + cells.row(5).fill(Cell::basic('5')); + dbg!(&cells); + + // cells.margin.1 = 3; + cells.grow(1); + dbg!(&cells); + assert_eq!( + format!("{cells:?}"), + "Cells { size: (5, 5), margin: (1, 5), row: 1, cells: [2, 2, 2, 2, 2]\n[3, 3, 3, 3, 3]\n[4, 4, 4, 4, 4]\n[5, 5, 5, 5, 5]\n[ , , , , ]\n }" + ); } } |