ted/
lib.rs

1use std::cmp::{max, min};
2use std::io::{stdout, Write};
3use std::{thread, time};
4
5pub fn escape<T: std::fmt::Display>(code: T) {
6    print!("{}[{}", 27 as char, code);
7}
8
9/// Set foreground color, using 24-bit true color (not supported on all terminals)
10pub fn tc_color_fg(r: u8, g: u8, b: u8) {
11    escape(format!("38;2;{};{};{}", r, g, b));
12}
13
14/// Set background color, using 24-bit true color (not supported on all terminals)
15pub fn tc_color_bg(r: u8, g: u8, b: u8) {
16    escape(format!("48;2;{};{};{}", r, g, b));
17}
18
19/// Set foreground color, using 8-bit color
20pub fn color_fg(color: u8) {
21    escape(format!("38;5;{}m", color));
22}
23
24/// Set background color, using 8-bit color
25pub fn color_bg(color: u8) {
26    escape(format!("48;5;{}m", color));
27}
28
29/// Remove all color modifiers
30pub fn decolor() {
31    escape("0m");
32}
33
34/// Clear the screen (full clear, not scroll)
35pub fn clear() {
36    print!("{}c", 27 as char);
37}
38
39/// Draw a single character onto the screen
40pub fn pixel(c: char, x: u32, y: u32) {
41    escape(format!("{};{}H{}", y, x, c));
42    stdout().flush().unwrap();
43}
44
45/// Draw an orthoganal line to the screen
46pub fn orth_line(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
47    if x1 != x2 && y1 != y2 {
48        // TODO: replace with error handling
49        panic!("Cannot draw non-ortho lines with orth-line");
50    }
51
52    if x1 != x2 {
53        let mut x = min(x1, x2);
54
55        while x != max(x1, x2) + 1 {
56            pixel(c, x, y1);
57
58            x += 1;
59        }
60    } else {
61        let mut y = min(y1, y2);
62
63        while y != max(y1, y2) + 1 {
64            pixel(c, x1, y);
65
66            y += 1;
67        }
68    }
69}
70
71pub fn line(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
72  if x1 == x2 || y1 == y2 {
73    orth_line(c, x1, x2, y1, y2);
74    return;
75  }
76
77  let mut dx: i32 = (x2 - x1) as i32;
78  let mut dy: i32 = (y2 - y1) as i32;
79
80  let sx = if (x2 as i32) - (x1 as i32) > 0 { 1 } else { -1 };
81  let sy = if (y2 as i32) - (y1 as i32) > 0 { 1 } else { -1 };
82
83  let xx; let xy; let yx; let yy;
84  if dx > dy {
85    xx = sx;
86    xy = 0i32;
87    yx = 0i32;
88    yy = sy;
89  } else {
90    std::mem::swap(&mut dx, &mut dy);
91    xx = 0i32;
92    xy = sy;
93    yx = sx;
94    yy = 0i32;
95  }
96
97  let mut err = ((dy << 1) - dx) as i32;
98
99  let mut x = 0;
100  let mut y = 0;
101
102  while x <= dx {
103    pixel(c, ((x1 as i32) + x*xx + y*yx) as u32, ((y1 as i32) + x*xy + y*yy) as u32);
104
105    if err >= 0 {
106      y += 1;
107      err -= (dx as i32) << 1;
108    }
109
110    err += (dy as i32) << 1;
111    x += 1;
112  }
113}
114
115/// Draw a rectangle onto the screen
116pub fn rect(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
117    orth_line(c, x1, y1, x1, y2);
118    orth_line(c, x1, y1, x2, y1);
119    orth_line(c, x2, y2, x1, y2);
120    orth_line(c, x2, y2, x2, y1);
121}
122
123/// Draw a filled rectangle onto the screen
124pub fn rect_fill(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
125    let mut y = y1;
126    while y != y2 {
127        orth_line(c, x1, y, x2, y);
128        y += 1;
129    }
130}
131
132/// Draw a triangle onto the screen
133pub fn triangle(c: char, x1: u32, y1: u32, x2: u32, y2: u32, x3: u32, y3: u32) {
134  line(c, x1, y1, x2, y2);
135  line(c, x1, y1, x3, y3);
136  line(c, x3, y3, x2, y2);
137}
138
139/// Draw a filled triangle onto the screen
140pub fn triangle_fill(c: char, x1: u32, y1: u32, x2: u32, y2: u32, x3: u32, y3: u32) {
141  unimplemented!();
142}
143
144/// Draw text onto the screen (non-wrapping)
145pub fn text(s: String, ox: u32, y: u32) {
146    let mut x = ox;
147
148    for c in s.chars() {
149        pixel(c, x, y);
150        x += 1;
151    }
152}
153
154/// Set cursor to position
155pub fn goto(x: u32, y: u32) {
156  escape(format!("{};{}H", y, x));
157}
158
159/// Put cursor to top of screen
160pub fn home() {
161  goto(1, 1);
162}
163
164/// Put cursor to the bottom of the screen 
165pub fn bot() {
166    goto(1, 9999);
167}
168
169// TODO: probably remove
170/// Pause for a certain amount of seconds
171pub fn sleep(seconds: f32) {
172    let secs = seconds as u64;
173    let mils = (seconds % 1.0 * 1000.0 * 1000000.0) as u32;
174    thread::sleep(time::Duration::new(secs, mils));
175}
176