Skip to main content

void_graph/
check.rs

1//! Terminal size checking for graph rendering.
2//!
3//! Adapted from [Serie](https://github.com/lusingander/serie) by lusingander.
4//! Original source: https://github.com/lusingander/serie/blob/master/src/check.rs
5
6use ratatui::crossterm::terminal;
7use thiserror::Error;
8
9/// Error for terminal size issues
10#[derive(Debug, Error)]
11pub enum CheckError {
12    #[error("terminal too small: {0}")]
13    TooSmall(String),
14
15    #[error("io error: {0}")]
16    Io(#[from] std::io::Error),
17}
18
19/// Cell width type for graph rendering
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum CellWidthType {
22    Single,
23    Double,
24}
25
26/// Graph width preference
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum GraphWidthType {
29    Single,
30    Double,
31    Auto,
32}
33
34/// Decide cell width based on terminal size and graph requirements
35pub fn decide_cell_width_type(
36    max_pos_x: usize,
37    cell_width_type: Option<GraphWidthType>,
38) -> Result<CellWidthType, CheckError> {
39    let (w, h) = terminal::size()?;
40    decide_cell_width_type_from(max_pos_x, w as usize, h as usize, cell_width_type)
41}
42
43fn decide_cell_width_type_from(
44    max_pos_x: usize,
45    term_width: usize,
46    term_height: usize,
47    cell_width_type: Option<GraphWidthType>,
48) -> Result<CellWidthType, CheckError> {
49    let single_image_cell_width = max_pos_x + 1;
50    let double_image_cell_width = single_image_cell_width * 2;
51
52    match cell_width_type {
53        Some(GraphWidthType::Double) => {
54            let required_width = double_image_cell_width + 2;
55            if required_width > term_width {
56                let msg = format!("Terminal too small ({term_width}x{term_height}). Need at least {required_width} columns.");
57                return Err(CheckError::TooSmall(msg));
58            }
59            Ok(CellWidthType::Double)
60        }
61        Some(GraphWidthType::Single) => {
62            let required_width = single_image_cell_width + 2;
63            if required_width > term_width {
64                let msg = format!("Terminal too small ({term_width}x{term_height}). Need at least {required_width} columns.");
65                return Err(CheckError::TooSmall(msg));
66            }
67            Ok(CellWidthType::Single)
68        }
69        Some(GraphWidthType::Auto) | None => {
70            let double_required_width = double_image_cell_width + 2;
71            if double_required_width <= term_width {
72                return Ok(CellWidthType::Double);
73            }
74            let single_required_width = single_image_cell_width + 2;
75            if single_required_width <= term_width {
76                return Ok(CellWidthType::Single);
77            }
78            let msg = format!("Terminal too small ({term_width}x{term_height}). Need at least {single_required_width} columns.");
79            Err(CheckError::TooSmall(msg))
80        }
81    }
82}