use std::io::{self, Write};
use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
use crossterm::{cursor, execute};
pub const MIN_WIDTH: u16 = 40;
pub const MIN_HEIGHT: u16 = 10;
#[derive(Debug, Clone, Copy)]
pub struct TerminalSize {
pub width: u16,
pub height: u16,
}
impl TerminalSize {
pub fn is_valid(&self) -> bool {
self.width >= MIN_WIDTH && self.height >= MIN_HEIGHT
}
pub fn grid_columns(&self) -> usize {
match self.width {
0..60 => 1,
60..90 => 2,
90..120 => 3,
120..160 => 4,
_ => 5,
}
}
}
pub fn check_terminal_size() -> Option<TerminalSize> {
terminal::size()
.ok()
.map(|(width, height)| TerminalSize { width, height })
}
pub fn enable_raw_mode() -> io::Result<()> {
terminal::enable_raw_mode()
}
pub fn disable_raw_mode() -> io::Result<()> {
terminal::disable_raw_mode()
}
pub fn is_raw_mode_enabled() -> bool {
terminal::is_raw_mode_enabled().unwrap_or(false)
}
pub fn enter_alternate_screen() -> io::Result<()> {
execute!(io::stdout(), EnterAlternateScreen)?;
Ok(())
}
pub fn leave_alternate_screen() -> io::Result<()> {
execute!(io::stdout(), LeaveAlternateScreen)?;
Ok(())
}
pub fn show_cursor() -> io::Result<()> {
execute!(io::stdout(), cursor::Show)?;
Ok(())
}
pub fn hide_cursor() -> io::Result<()> {
execute!(io::stdout(), cursor::Hide)?;
Ok(())
}
pub fn prepare_for_script_execution() -> io::Result<()> {
if is_raw_mode_enabled() {
disable_raw_mode()?;
}
leave_alternate_screen()?;
show_cursor()?;
io::stdout().flush()?;
Ok(())
}
pub fn restore_for_tui() -> io::Result<()> {
enter_alternate_screen()?;
enable_raw_mode()?;
hide_cursor()?;
io::stdout().flush()?;
Ok(())
}
pub fn cleanup_terminal() -> io::Result<()> {
let _ = disable_raw_mode();
let _ = leave_alternate_screen();
let _ = show_cursor();
io::stdout().flush()?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_terminal_size_validity() {
let valid = TerminalSize {
width: 80,
height: 24,
};
assert!(valid.is_valid());
let too_small = TerminalSize {
width: 30,
height: 5,
};
assert!(!too_small.is_valid());
}
#[test]
fn test_grid_columns() {
assert_eq!(
TerminalSize {
width: 50,
height: 24
}
.grid_columns(),
1
);
assert_eq!(
TerminalSize {
width: 80,
height: 24
}
.grid_columns(),
2
);
assert_eq!(
TerminalSize {
width: 100,
height: 24
}
.grid_columns(),
3
);
assert_eq!(
TerminalSize {
width: 140,
height: 24
}
.grid_columns(),
4
);
assert_eq!(
TerminalSize {
width: 200,
height: 24
}
.grid_columns(),
5
);
}
}