1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
mod app;
mod event;
mod gentoo;
mod theme;
mod ui;
use std::{
io::{self, Stdout, stdout},
panic::{set_hook, take_hook},
};
use ratatui::{
Terminal,
backend::Backend,
crossterm::{
execute,
terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
},
prelude::CrosstermBackend,
};
use crate::{app::App, event::handle_event, gentoo::Portage, ui::ui};
struct TuiGuard;
impl Drop for TuiGuard {
fn drop(&mut self) {
_ = restore_tui();
}
}
fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
init_panic_hook();
let _guard = TuiGuard;
let mut tui = init_tui()?;
let mut p = Portage::new();
p.world_packages = Portage::load_world_packages()?;
p.installed_packages = Portage::load_installed_packages()?;
p.load_available_packages()?;
let mut app = App::new(p);
run(&mut tui, &mut app)?;
Ok(())
}
fn run<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<()>
where
io::Error: From<B::Error>,
{
loop {
terminal.draw(|frame| ui(frame, app))?;
let should_exit = handle_event(app)?;
if should_exit {
break;
}
}
Ok(())
}
fn init_tui() -> io::Result<ratatui::Terminal<CrosstermBackend<Stdout>>> {
enable_raw_mode()?;
execute!(stdout(), EnterAlternateScreen)?;
Terminal::new(CrosstermBackend::new(stdout()))
}
fn init_panic_hook() {
let original_hook = take_hook();
set_hook(Box::new(move |panic_info| {
let _ = restore_tui();
original_hook(panic_info);
}));
}
fn restore_tui() -> io::Result<()> {
disable_raw_mode()?;
execute!(stdout(), LeaveAlternateScreen)?;
Ok(())
}
|