icmd 0.1.0

A command-line software framework
Documentation
use std::fmt::Debug;
use std::io::stdout;
use std::io::Stdout;

use crossterm::event;
use crossterm::{cursor, execute, terminal};
use message::MessageQueue;
use utils::BoundError;

pub mod utils;

pub mod message;

pub mod looper;

pub mod interactor;

pub mod renderer;

/// This struct represents a command window in the terminal.
pub struct ICmdWindow {
    /// The width of the window.
    pub width: u16,

    /// The height of the window.
    pub height: u16,

    pub bg_color: String,

    /// The frames per second (FPS) of the window.
    pub fps: u16,

    /// The name of the window.
    pub name: String,

    /// The standard output stream.
    pub stdout: Stdout,

    /// Message queue
    pub message_queue: MessageQueue,
}

impl ICmdWindow {
    /// Creates a new ICmdWindow with the given width, height, and name.
    pub fn new(width: u16, height: u16, name: String) -> utils::Result<Self> {
        let mut stdout = stdout();
        terminal::enable_raw_mode().unwrap();

        let (max_width, max_height) = terminal::size().unwrap();

        execute!(stdout, terminal::Clear(terminal::ClearType::All)).unwrap();
        execute!(stdout, cursor::Hide).unwrap();
        execute!(stdout, event::EnableMouseCapture).unwrap();

        if width > max_width || height > max_height {
            Err(Box::new(BoundError(
                (width, height),
                (max_width, max_height),
            )))
        } else {
            Ok(ICmdWindow {
                width,
                height,
                name,
                bg_color: "\x1b[40m".to_string(), // Default Black background color
                // Set the default FPS to 30.
                fps: 30,

                stdout,
                message_queue: MessageQueue::new(10),
            })
        }
    }

    /// Creates a new ICmdWindow with the current terminal size and the given name.
    pub fn new_with_name(name: &'static str) -> Self {
        let (width, height) = terminal::size().unwrap();
        Self::new(width, height, name.to_string()).unwrap()
    }

    pub fn get_size(&self) -> (u16, u16) {
        (self.width, self.height)
    }
}

impl Default for ICmdWindow {
    fn default() -> Self {
        Self::new_with_name("ICmd Window")
    }
}

impl Debug for ICmdWindow {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ICmdWindow")
            .field("width", &self.width)
            .field("height", &self.height)
            .field("bg_color", &self.bg_color)
            .field("fps", &self.fps)
            .field("name", &self.name)
            .finish()
    }
}