use crate::io::crossterm_input::CrosstermInput;
use crate::io::crossterm_output::CrosstermOutput;
use crate::primitives::sized_xy::SizedXY;
use crate::primitives::xy::XY;
use crossterm::terminal;
use std::io::{stdout, Error, ErrorKind, Stdout};
pub type AppError = Box<dyn std::error::Error>;
#[derive(Default)]
pub struct App {
use_alt_screen_mode: bool,
}
impl App {
pub fn init() -> Self {
Self::default()
}
pub fn with_alt_screen_mode(mut self) -> Self {
self.use_alt_screen_mode = true;
self
}
fn run_init_chain(&self) -> Result<(), AppError> {
terminal::enable_raw_mode()?;
if self.use_alt_screen_mode {
crossterm::execute!(stdout(), terminal::EnterAlternateScreen)?;
}
Ok(())
}
fn run_teardown_chain(&self) -> Result<(), AppError> {
if self.use_alt_screen_mode {
crossterm::execute!(stdout(), terminal::LeaveAlternateScreen)?;
}
terminal::disable_raw_mode()?;
Ok(())
}
pub fn run_with<F>(self, f: F) -> Result<(), AppError>
where
F: FnOnce(CrosstermInput, CrosstermOutput<Stdout>),
{
self.run_init_chain()?;
let input = CrosstermInput::new();
let output = CrosstermOutput::new(stdout());
if output.size() == XY::ZERO {
return Err(Box::new(Error::new(ErrorKind::Other, "it seems like the screen has zero size")));
}
f(input, output);
self.run_teardown_chain()
}
}