a3s-tui 0.1.0

TEA (The Elm Architecture) framework for terminal user interfaces
Documentation
use crossterm::{cursor, execute, queue, terminal};
use std::io::{self, Stdout, Write};

pub struct Terminal {
    stdout: Stdout,
    alt_screen: bool,
    mouse_support: bool,
    raw_mode: bool,
}

pub struct TerminalOptions {
    pub alt_screen: bool,
    pub mouse_support: bool,
    pub raw_mode: bool,
}

impl Default for TerminalOptions {
    fn default() -> Self {
        Self {
            alt_screen: true,
            mouse_support: false,
            raw_mode: true,
        }
    }
}

impl Terminal {
    pub fn new(options: &TerminalOptions) -> io::Result<Self> {
        Ok(Self {
            stdout: io::stdout(),
            alt_screen: options.alt_screen,
            mouse_support: options.mouse_support,
            raw_mode: options.raw_mode,
        })
    }

    pub fn enter(&mut self) -> io::Result<()> {
        if self.raw_mode {
            terminal::enable_raw_mode()?;
        }
        if self.alt_screen {
            execute!(self.stdout, terminal::EnterAlternateScreen)?;
        }
        if self.mouse_support {
            execute!(self.stdout, crossterm::event::EnableMouseCapture)?;
        }
        execute!(self.stdout, cursor::Hide)?;
        Ok(())
    }

    pub fn exit(&mut self) -> io::Result<()> {
        execute!(self.stdout, cursor::Show)?;
        if self.mouse_support {
            execute!(self.stdout, crossterm::event::DisableMouseCapture)?;
        }
        if self.alt_screen {
            execute!(self.stdout, terminal::LeaveAlternateScreen)?;
        }
        if self.raw_mode {
            terminal::disable_raw_mode()?;
        }
        Ok(())
    }

    pub fn draw(&mut self, content: &str) -> io::Result<()> {
        queue!(
            self.stdout,
            cursor::MoveTo(0, 0),
            terminal::Clear(terminal::ClearType::All),
        )?;
        write!(self.stdout, "{}", content)?;
        self.stdout.flush()
    }

    pub fn draw_line(&mut self, row: u16, content: &str) -> io::Result<()> {
        queue!(
            self.stdout,
            cursor::MoveTo(0, row),
            terminal::Clear(terminal::ClearType::CurrentLine),
        )?;
        write!(self.stdout, "{}", content)?;
        Ok(())
    }

    pub fn flush(&mut self) -> io::Result<()> {
        self.stdout.flush()
    }

    pub fn write_raw(&mut self, s: &str) -> io::Result<()> {
        write!(self.stdout, "{}", s)
    }

    pub fn stdout_mut(&mut self) -> &mut Stdout {
        &mut self.stdout
    }

    pub fn size() -> io::Result<(u16, u16)> {
        terminal::size()
    }
}

impl Drop for Terminal {
    fn drop(&mut self) {
        let _ = self.exit();
    }
}