bacon 0.1.0

a background compiler for rust
use {
    crate::*,
    anyhow::*,
    crossbeam::channel::{bounded, select, unbounded, Receiver, Sender},
    crossterm::{
        cursor,
        event::{KeyCode::*, KeyEvent, KeyModifiers},
        execute,
        style::{Colorize, Styler},
        terminal, ExecutableCommand, QueueableCommand,
    },
    notify::{RecommendedWatcher, RecursiveMode, Watcher},
    std::{env, io::Write, path::PathBuf},
    termimad::{Event, EventSource},
};

pub fn run(w: &mut W) -> Result<()> {
    let mut state = AppState::new()?;
    let event_source = EventSource::new()?;
    let user_events = event_source.receiver();
    state.draw(w)?;
    state.report = Some(Report::compute()?);
    state.computing = false;
    state.draw(w)?;

    let src_dir = env::current_dir()?.join("src");
    if !src_dir.exists() {
        return Err(anyhow!("src directory not found"));
    }
    let (watch_sender, watch_receiver) = bounded(0);
    let mut watcher: RecommendedWatcher = Watcher::new_immediate(move |res| match res {
        Ok(_) => {
            debug!("notify event received");
            if let Err(e) = watch_sender.send(()) {
                debug!("error when notifying on inotify event: {}", e);
            }
        }
        Err(e) => warn!("watch error: {:?}", e),
    })?;
    watcher.watch(src_dir, RecursiveMode::Recursive)?;

    let computer = Computer::new()?;

    loop {
        select! {
            recv(user_events) -> user_event => {
                match user_event? {
                    Event::Resize(width, height) => {
                        state.screen = (width, height);
                        state.draw(w)?;
                    }
                    Event::Key(KeyEvent{ code, modifiers }) => {
                        match (code, modifiers) {
                            (Char('q'), KeyModifiers::NONE) | (Char('c'), KeyModifiers::CONTROL) => {
                                debug!("user requests quit");
                                break;
                            }
                            _ => {
                                debug!("ignored key event: {:?}", user_event);
                            }
                        }
                    }
                    _ => {
                    }
                }
                event_source.unblock(false);
            }
            recv(watch_receiver) -> _ => {
                debug!("got a watcher event");
                if let Err(e) = computer.task_sender.try_send(()) {
                    debug!("error sending task: {}", e);
                } else {
                    state.computing = true;
                    state.draw(w)?;
                }
            }
            recv(computer.report_receiver) -> report => {
                state.report = Some(report?);
                state.computing = false;
                state.draw(w)?;
            }
        }
    }
    Ok(())
}