#[allow(dead_code)] mod demo; #[allow(dead_code)] mod util; use std::sync::mpsc; use std::thread; use std::time::Duration; use crossterm::{input, AlternateScreen, InputEvent, KeyEvent}; use structopt::StructOpt; use tui::backend::CrosstermBackend; use tui::Terminal; use crate::demo::{ui, App}; enum Event { Input(I), Tick, } #[derive(Debug, StructOpt)] struct Cli { #[structopt(long = "tick-rate", default_value = "250")] tick_rate: u64, #[structopt(long = "log")] log: bool, } fn main() -> Result<(), failure::Error> { let cli = Cli::from_args(); stderrlog::new().quiet(!cli.log).verbosity(4).init()?; let screen = AlternateScreen::to_alternate(true)?; let backend = CrosstermBackend::with_alternate_screen(screen)?; let mut terminal = Terminal::new(backend)?; terminal.hide_cursor()?; // Setup input handling let (tx, rx) = mpsc::channel(); { let tx = tx.clone(); thread::spawn(move || { let input = input(); let reader = input.read_sync(); for event in reader { match event { InputEvent::Keyboard(key) => { if let Err(_) = tx.send(Event::Input(key)) { return; } if key == KeyEvent::Char('q') { return; } } _ => {} } } }); } { let tx = tx.clone(); thread::spawn(move || { let tx = tx.clone(); loop { tx.send(Event::Tick).unwrap(); thread::sleep(Duration::from_millis(cli.tick_rate)); } }); } let mut app = App::new("Crossterm Demo"); terminal.clear()?; loop { ui::draw(&mut terminal, &app)?; match rx.recv()? { Event::Input(event) => match event { KeyEvent::Char(c) => app.on_key(c), KeyEvent::Left => app.on_left(), KeyEvent::Up => app.on_up(), KeyEvent::Right => app.on_right(), KeyEvent::Down => app.on_down(), _ => {} }, Event::Tick => { app.on_tick(); } } if app.should_quit { break; } } Ok(()) }