From 612713ab1b003d56fc4c2ddcdcac399168796f71 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sun, 5 May 2024 23:27:19 -0400 Subject: [PATCH] Improve event handling and the main loop --- editor-challenge/src/main.rs | 93 ++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 30 deletions(-) diff --git a/editor-challenge/src/main.rs b/editor-challenge/src/main.rs index db55133..7673fc3 100644 --- a/editor-challenge/src/main.rs +++ b/editor-challenge/src/main.rs @@ -1,11 +1,23 @@ -use crossterm::{event::{self, KeyCode, KeyEvent}, terminal::{disable_raw_mode, enable_raw_mode}}; -use std::{io::{self, Read}, sync::mpsc, thread, time::{Duration, Instant}}; +use crossterm::{ + event::{self, KeyCode, KeyEvent, KeyModifiers}, + terminal::{disable_raw_mode, enable_raw_mode}, +}; +use std::{ + io::{self, Read}, + sync::mpsc, + thread, + time::{Duration, Instant}, +}; use tui::{ - backend::CrosstermBackend, layout::{Alignment, Constraint, Direction, Layout}, style::{Color, Style}, widgets::{Block, BorderType, Borders, Paragraph}, Terminal + backend::CrosstermBackend, + layout::{Alignment, Constraint, Direction, Layout}, + style::{Color, Style}, + widgets::{Block, BorderType, Borders, Paragraph}, + Terminal, }; -const TITLE: &str = "Editor Challenge"; -const COPYRIGHT: &str = "Editor Challenge, (c) Savanni D'Gerinel - all rights reserved"; +const TITLE: &str = "Text Editor Challenge"; +const COPYRIGHT: &str = "(c) Savanni D'Gerinel - all rights reserved"; const TICK_RATE_MS: u64 = 200; fn render(terminal: &mut Terminal) -> Result<(), anyhow::Error> @@ -54,29 +66,55 @@ where Ok(()) } +#[derive(Debug)] enum Event { Input(I), Tick, } fn handle_input(tx: mpsc::Sender>, tick_rate: Duration) { - let mut last_tick = Instant::now(); - loop { - let timeout = tick_rate.checked_sub(last_tick.elapsed()) - .unwrap_or_else(|| Duration::from_secs(0)); + let mut last_tick = Instant::now(); + loop { + let timeout = tick_rate + .checked_sub(last_tick.elapsed()) + .unwrap_or_else(|| Duration::from_secs(0)); - if event::poll(timeout).expect("poll works") { - if let event::Event::Key(key) = event::read().expect("can read events") { - tx.send(Event::Input(key)).expect("can send events"); - } - } - - if last_tick.elapsed() >= tick_rate { - if let Ok(_) = tx.send(Event::Tick) { - last_tick = Instant::now(); - } + if event::poll(timeout).expect("poll works") { + if let event::Event::Key(key) = event::read().expect("can read events") { + tx.send(Event::Input(key)).expect("can send events"); } } + + if last_tick.elapsed() >= tick_rate { + if let Ok(_) = tx.send(Event::Tick) { + last_tick = Instant::now(); + } + } + } +} + +fn app_loop( + terminal: &mut Terminal, + rx: mpsc::Receiver>, +) -> Result<(), anyhow::Error> +where + T: tui::backend::Backend, +{ + loop { + render(terminal)?; + + let event = rx.recv()?; + + match event { + Event::Input(KeyEvent { code, modifiers }) + if code == KeyCode::Char('x') && modifiers == KeyModifiers::CONTROL => + { + break; + } + _ => {} + } + } + Ok(()) } fn main() -> Result<(), anyhow::Error> { @@ -94,17 +132,12 @@ fn main() -> Result<(), anyhow::Error> { let mut terminal = Terminal::new(backend)?; let _ = terminal.clear()?; - loop { - render(&mut terminal)?; + let result = app_loop(&mut terminal, rx); - let event = rx.recv()?; + disable_raw_mode()?; + terminal.show_cursor()?; - match event { - Event::Input(KeyEvent{ code, .. }) if code == KeyCode::Char('q') => { - disable_raw_mode()?; - return Ok(()); - } - _ => {}, - } - } + result?; + + Ok(()) }