aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 3f48139390eb2cdea5de3da1a1b435d2764d835a (plain) (blame)
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
87
88
89
90
91
92
93
94
95
96
97
mod app;
mod background_loader;
mod gentoo;
mod screens;
mod signal;
mod theme;
mod widgets;

use std::{
    io::{self, Stdout, stdout},
    panic::{set_hook, take_hook},
    time::Duration,
};

use clap::command;
use ratatui::{
    Terminal,
    crossterm::{
        event::poll,
        execute,
        terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
    },
    prelude::CrosstermBackend,
};

use crate::{
    app::App,
    gentoo::{Portage, portage_loader},
};

struct TuiGuard;

impl Drop for TuiGuard {
    fn drop(&mut self) {
        _ = restore_tui();
    }
}

fn main() -> color_eyre::Result<()> {
    color_eyre::install()?;

    // Just for --help and --version right now, later --config and possably more
    let _ = command!().get_matches();
    let _guard = TuiGuard;

    let tui = init_tui()?;

    let world_packages = portage_loader::load_world_packages()?;
    let installed_packages = portage_loader::load_installed_packages()?;
    // p.available_packages = portage_loader::load_available_packages()?;
    let p = Portage::new(installed_packages, world_packages, vec![]);

    let mut app = App::new(p);
    app.start_available_packages_load();

    run(tui, &mut app)?;

    Ok(())
}

fn run(mut terminal: Terminal<CrosstermBackend<Stdout>>, app: &mut App) -> color_eyre::Result<()> {
    loop {
        app.poll_available_packages();

        terminal.draw(|frame| app.draw(frame))?;

        if poll(Duration::from_millis(50))? {
            let should_exit = app.update()?;
            if should_exit {
                break;
            }
        }
    }

    Ok(())
}

fn init_tui() -> io::Result<ratatui::Terminal<CrosstermBackend<Stdout>>> {
    execute!(stdout(), EnterAlternateScreen)?;
    enable_raw_mode()?;
    init_panic_hook();
    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(())
}