#[allow(dead_code)] mod demo; #[allow(dead_code)] mod util; use crate::demo::{ui, App}; use crossterm::{ event::{self, Event as CEvent, KeyCode}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; use std::{ io::{stdout, Write}, sync::mpsc, thread, time::Duration, }; use structopt::StructOpt; use tui::{backend::CrosstermBackend, Terminal}; 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()?; enable_raw_mode()?; let mut stdout = stdout(); execute!(stdout, EnterAlternateScreen)?; let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; terminal.hide_cursor()?; // Setup input handling let (tx, rx) = mpsc::channel(); thread::spawn(move || { loop { // poll for tick rate duration, if no events, sent tick event. if event::poll(Duration::from_millis(cli.tick_rate)).unwrap() { if let CEvent::Key(key) = event::read().unwrap() { tx.send(Event::Input(key)).unwrap(); } } tx.send(Event::Tick).unwrap(); } }); let mut app = App::new("Crossterm Demo"); terminal.clear()?; loop { terminal.draw(|mut f| ui::draw(&mut f, &mut app))?; match rx.recv()? { Event::Input(event) => match event.code { KeyCode::Char('q') => { disable_raw_mode()?; execute!(terminal.backend_mut(), LeaveAlternateScreen)?; terminal.show_cursor()?; break; } KeyCode::Char(c) => app.on_key(c), KeyCode::Left => app.on_left(), KeyCode::Up => app.on_up(), KeyCode::Right => app.on_right(), KeyCode::Down => app.on_down(), _ => {} }, Event::Tick => { app.on_tick(); } } if app.should_quit { break; } } Ok(()) }