aboutsummaryrefslogtreecommitdiffstats
path: root/src/term.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/term.rs')
-rw-r--r--src/term.rs277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/term.rs b/src/term.rs
new file mode 100644
index 0000000..ef6c546
--- /dev/null
+++ b/src/term.rs
@@ -0,0 +1,277 @@
+// TODO: read all of this from terminfo
+
+#[derive(Default, Debug)]
+pub struct ClearScreen;
+
+impl ClearScreen {
+ pub fn new() -> Self {
+ Self::default()
+ }
+}
+
+impl std::fmt::Display for ClearScreen {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str("\x1b[H\x1b[J")
+ }
+}
+
+#[derive(Default, Debug)]
+pub struct CRLF;
+
+impl CRLF {
+ pub fn new() -> Self {
+ Self::default()
+ }
+}
+
+impl std::fmt::Display for CRLF {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str("\r\n")
+ }
+}
+
+#[derive(Default, Debug)]
+pub struct MoveTo {
+ row: u16,
+ col: u16,
+}
+
+impl MoveTo {
+ pub fn new(pos: crate::grid::Pos) -> Self {
+ Self {
+ row: pos.row,
+ col: pos.col,
+ }
+ }
+}
+
+impl std::fmt::Display for MoveTo {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if self.row == 0 && self.col == 0 {
+ f.write_str("\x1b[H")
+ } else {
+ write!(f, "\x1b[{};{}H", self.row + 1, self.col + 1)
+ }
+ }
+}
+
+#[derive(Default, Debug)]
+pub struct Attrs {
+ fgcolor: Option<crate::attrs::Color>,
+ bgcolor: Option<crate::attrs::Color>,
+ bold: Option<bool>,
+ italic: Option<bool>,
+ underline: Option<bool>,
+ inverse: Option<bool>,
+}
+
+impl Attrs {
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ pub fn fgcolor(mut self, fgcolor: crate::attrs::Color) -> Self {
+ self.fgcolor = Some(fgcolor);
+ self
+ }
+
+ pub fn bgcolor(mut self, bgcolor: crate::attrs::Color) -> Self {
+ self.bgcolor = Some(bgcolor);
+ self
+ }
+
+ pub fn bold(mut self, bold: bool) -> Self {
+ self.bold = Some(bold);
+ self
+ }
+
+ pub fn italic(mut self, italic: bool) -> Self {
+ self.italic = Some(italic);
+ self
+ }
+
+ pub fn underline(mut self, underline: bool) -> Self {
+ self.underline = Some(underline);
+ self
+ }
+
+ pub fn inverse(mut self, inverse: bool) -> Self {
+ self.inverse = Some(inverse);
+ self
+ }
+}
+
+impl std::fmt::Display for Attrs {
+ #[allow(unused_assignments, clippy::cognitive_complexity)]
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str("\x1b[")?;
+ let mut first = true;
+
+ macro_rules! write_param {
+ ($i:expr) => {
+ if first {
+ first = false;
+ } else {
+ f.write_str(";")?;
+ }
+ write!(f, "{}", $i)?;
+ };
+ }
+
+ if let Some(fgcolor) = self.fgcolor {
+ match fgcolor {
+ crate::attrs::Color::Default => {
+ write_param!(39);
+ }
+ crate::attrs::Color::Idx(i) => {
+ if i < 8 {
+ write_param!(i + 30);
+ } else if i < 16 {
+ write_param!(i + 82);
+ } else {
+ write_param!(38);
+ write_param!(5);
+ write_param!(i);
+ }
+ }
+ crate::attrs::Color::Rgb(r, g, b) => {
+ write_param!(38);
+ write_param!(2);
+ write_param!(r);
+ write_param!(g);
+ write_param!(b);
+ }
+ }
+ }
+
+ if let Some(bgcolor) = self.bgcolor {
+ match bgcolor {
+ crate::attrs::Color::Default => {
+ write_param!(49);
+ }
+ crate::attrs::Color::Idx(i) => {
+ if i < 8 {
+ write_param!(i + 40);
+ } else if i < 16 {
+ write_param!(i + 92);
+ } else {
+ write_param!(48);
+ write_param!(5);
+ write_param!(i);
+ }
+ }
+ crate::attrs::Color::Rgb(r, g, b) => {
+ write_param!(48);
+ write_param!(2);
+ write_param!(r);
+ write_param!(g);
+ write_param!(b);
+ }
+ }
+ }
+
+ if let Some(bold) = self.bold {
+ if bold {
+ write_param!(1);
+ } else {
+ write_param!(22);
+ }
+ }
+
+ if let Some(italic) = self.italic {
+ if italic {
+ write_param!(3);
+ } else {
+ write_param!(23);
+ }
+ }
+
+ if let Some(underline) = self.underline {
+ if underline {
+ write_param!(4);
+ } else {
+ write_param!(24);
+ }
+ }
+
+ if let Some(inverse) = self.inverse {
+ if inverse {
+ write_param!(7);
+ } else {
+ write_param!(27);
+ }
+ }
+
+ f.write_str("m")?;
+ Ok(())
+ }
+}
+
+#[derive(Debug)]
+pub struct MoveRight {
+ count: u16,
+}
+
+impl MoveRight {
+ pub fn new(count: u16) -> Self {
+ Self { count }
+ }
+}
+
+impl Default for MoveRight {
+ fn default() -> Self {
+ Self { count: 1 }
+ }
+}
+
+impl std::fmt::Display for MoveRight {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self.count {
+ 0 => Ok(()),
+ 1 => f.write_str("\x1b[C"),
+ n => write!(f, "\x1b[{}C", n),
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct EraseChar {
+ count: u16,
+}
+
+impl Default for EraseChar {
+ fn default() -> Self {
+ Self { count: 1 }
+ }
+}
+
+impl std::fmt::Display for EraseChar {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self.count {
+ 0 => Ok(()),
+ 1 => f.write_str("\x1b[X"),
+ n => write!(f, "\x1b[{}X", n),
+ }
+ }
+}
+
+#[derive(Default, Debug)]
+pub struct HideCursor {
+ hide: bool,
+}
+
+impl HideCursor {
+ pub fn new(hide: bool) -> Self {
+ Self { hide }
+ }
+}
+
+impl std::fmt::Display for HideCursor {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if self.hide {
+ f.write_str("\x1b[?25l")
+ } else {
+ f.write_str("\x1b[?25h")
+ }
+ }
+}