td_rs/
lib.rs

1use std::io::Write;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub struct Color (pub u8, pub u8, pub u8);
5
6#[derive(Debug, Clone)]
7pub struct Terminal {
8    width: usize,
9    height: usize,
10
11    ch: Box<[char]>,
12    fg: Box<[Color]>,
13    bg: Box<[Color]>
14}
15
16impl Terminal {
17    pub fn new() -> Self {
18        let mut win_size: libc::winsize = unsafe {std::mem::zeroed()};
19        unsafe {libc::ioctl(libc::STDOUT_FILENO, libc::TIOCGWINSZ, &mut win_size)};
20
21        let columns = win_size.ws_col as usize;
22        let rows = win_size.ws_row as usize;
23
24
25        let mut ch_buf = Vec::new();
26        ch_buf.resize(columns*rows, ' ');
27
28
29        let mut fg_buf = Vec::new();
30        fg_buf.resize(columns*rows, Color(0, 0, 0));
31
32        let mut bg_buf = Vec::new();
33        bg_buf.resize(columns*rows, Color(0, 0, 0));
34
35
36        Self {
37            width: columns,
38            height: rows,
39            ch: ch_buf.into_boxed_slice(),
40            fg: fg_buf.into_boxed_slice(),
41            bg: bg_buf.into_boxed_slice()
42        }
43    }
44
45    pub fn set_char(&mut self, x: usize, y: usize, ch: char) {
46        if !self.is_valid_coords(x, y) {return};
47        self.ch[y*self.width+x] = ch;
48    }
49
50    pub fn set_color_char(&mut self, x: usize, y: usize, ch: char, fg: Color, bg: Color) {
51        if !self.is_valid_coords(x, y) {return};
52        self.ch[y*self.width+x] = ch;
53        self.fg[y*self.width+x] = fg;
54        self.bg[y*self.width+x] = bg;
55    }
56
57    pub fn set_fg(&mut self, x: usize, y: usize, color: Color) {
58        if !self.is_valid_coords(x, y) {return};
59        self.fg[y*self.width+x] = color;
60    }
61
62    pub fn set_bg(&mut self, x: usize, y: usize, color: Color) {
63        if !self.is_valid_coords(x, y) {return};
64        self.bg[y*self.width+x] = color;
65    }
66
67    pub fn clear(&mut self, fg: Color, bg: Color) {
68        for y in 0..self.height {
69            for x in 0..self.width {
70                self.ch[y*self.width+x] = ' ';
71                self.fg[y*self.width+x] = fg;
72                self.bg[y*self.width+x] = bg;
73            }
74        }
75    }
76
77    pub fn display(&self) {
78        let mut output = String::new();
79
80        for y in 0..self.height {
81            for x in 0..self.width {
82                let fg = self.fg[y*self.width+x];
83                let bg = self.bg[y*self.width+x];
84
85                output += format!("\x1b[38;2;{};{};{}m\x1b[48;2;{};{};{}m{}", fg.0, fg.1, fg.2, bg.0, bg.1, bg.2, self.ch[y*self.width+x]).as_str();
86            }
87            if y < self.height-1 {output += "\n"};
88        }
89
90        print!("{}\x1b[m", output);
91
92        let _ = std::io::stdout().flush();
93    }
94
95    fn is_valid_coords(&self, x: usize, y: usize) -> bool {
96        x < self.width && y < self.height
97    }
98}