mod app;
mod ui;
pub use app::App;
use color_eyre::Result;
use ratatui::{
Terminal,
backend::CrosstermBackend,
crossterm::event::{self, Event},
};
use std::{
io,
time::{Duration, Instant},
};
pub fn run() -> Result<()> {
let backend = CrosstermBackend::new(io::stdout());
let mut terminal = Terminal::new(backend)?;
let mut app = App::new()?;
let panic_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
crossterm::execute!(io::stdout(), crossterm::terminal::LeaveAlternateScreen).ok();
crossterm::terminal::disable_raw_mode().ok();
panic_hook(panic_info);
}));
crossterm::terminal::enable_raw_mode()?;
crossterm::execute!(
io::stdout(),
crossterm::terminal::EnterAlternateScreen,
crossterm::event::EnableMouseCapture
)?;
terminal.clear()?;
let mut last_key_time: Option<Instant> = None;
loop {
terminal.draw(|f| ui::draw(f, &mut app))?;
if event::poll(Duration::from_millis(50))? {
if let Ok(Event::Key(key)) = event::read() {
if key.kind == event::KeyEventKind::Press {
let now = Instant::now();
if let Some(last_time) = last_key_time {
if now.duration_since(last_time) < Duration::from_millis(50) {
continue;
}
}
last_key_time = Some(now);
if app.handle_key_event(key)? {
break;
}
}
}
}
app.tick();
}
crossterm::terminal::disable_raw_mode()?;
crossterm::execute!(
io::stdout(),
crossterm::terminal::LeaveAlternateScreen,
crossterm::event::DisableMouseCapture
)?;
terminal.show_cursor()?;
Ok(())
}