diff options
| author | Mroik <mroik@delayed.space> | 2025-01-27 17:43:32 +0100 |
|---|---|---|
| committer | Mroik <mroik@delayed.space> | 2025-02-01 19:33:03 +0100 |
| commit | 5bd36b139d8ba07bce7edb8828beec3f114b3271 (patch) | |
| tree | 05ea85542c182e7cc91de4f0c340b71d4a07618e | |
| parent | 3c6073f6b08a7e812e2f1f22bb3882427e980663 (diff) | |
Implement app loop
| -rw-r--r-- | src/app.rs | 80 | ||||
| -rw-r--r-- | src/event.rs | 37 | ||||
| -rw-r--r-- | src/main.rs | 7 |
3 files changed, 88 insertions, 36 deletions
@@ -1,21 +1,26 @@ use std::{ error::Error, io::{stdout, Stdout}, - time::Duration, }; -use crossterm::event::{poll, read, KeyCode, KeyModifiers}; +use crossterm::{ + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, + ExecutableCommand, +}; use rand::Rng; -use tokio::sync::mpsc::{channel, Receiver, Sender}; +use tokio::{ + spawn, + sync::mpsc::{channel, Receiver, Sender}, +}; -use crate::event::Event; +use crate::event::{handle_input, Event}; -const TICK_RATE: u64 = 1000 / 20; +pub const TICK_RATE: u64 = 1000 / 20; pub struct App { stdout: Stdout, quote: Vec<String>, - event_tx: Sender<Event>, + pub event_tx: Sender<Event>, event_rx: Receiver<Event>, running: bool, } @@ -34,39 +39,44 @@ impl App { } } - pub async fn run(&mut self) { - todo!() - } + pub async fn run(&mut self) -> Result<(), Box<dyn Error>> { + self.stdout.execute(EnterAlternateScreen)?; + enable_raw_mode()?; + + let (ks_tx, ks_rx): (Sender<()>, Receiver<()>) = channel(1); + let ev = self.event_tx.clone(); + spawn(async { + start_input_handler(ev, ks_rx).await; + }); - // TODO - // - [ ] Pause on focus lost - // - [ ] Invalidate on paste - async fn handle_input(&mut self) -> Result<(), Box<dyn Error>> { + self.running = true; while self.running { - if poll(Duration::from_millis(TICK_RATE))? { - match read()? { - //crossterm::event::Event::FocusGained => todo!(), - //crossterm::event::Event::FocusLost => todo!(), - //crossterm::event::Event::Paste(_) => todo!(), - crossterm::event::Event::Key(key_event) => { - if key_event.code == KeyCode::Char('c') - && key_event.modifiers == KeyModifiers::CONTROL - { - self.event_tx.send(Event::Terminate).await?; - continue; - } - if key_event.code == KeyCode::Backspace { - self.event_tx.send(Event::Backspace).await?; - continue; - } - if let KeyCode::Char(c) = key_event.code { - self.event_tx.send(Event::KeyPress(c)).await?; - } - } - _ => (), - } + self.process().await?; + } + let _ = ks_tx.send(()); + + disable_raw_mode()?; + self.stdout.execute(LeaveAlternateScreen)?; + return Ok(()); + } + + async fn process(&mut self) -> Result<(), Box<dyn Error>> { + match self.event_rx.recv().await.unwrap() { + Event::Terminate => { + self.running = false; } + Event::KeyPress(_) => todo!(), + Event::Backspace => todo!(), } return Ok(()); } } + +async fn start_input_handler(ev: Sender<Event>, mut kill_switch: Receiver<()>) { + loop { + tokio::select! { + _ = handle_input(&ev) => (), + _ = kill_switch.recv() => return, + } + } +} diff --git a/src/event.rs b/src/event.rs index 1320c68..d5cdabe 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,5 +1,42 @@ +use std::{error::Error, time::Duration}; + +use crossterm::event::{poll, read, KeyCode, KeyModifiers}; +use tokio::sync::mpsc::Sender; + +use crate::app::TICK_RATE; + pub enum Event { Terminate, KeyPress(char), Backspace, } + +// TODO +// - [ ] Pause on focus lost +// - [ ] Invalidate on paste +pub async fn handle_input(sender: &Sender<Event>) -> Result<(), Box<dyn Error>> { + if poll(Duration::from_millis(TICK_RATE))? { + match read()? { + //crossterm::event::Event::FocusGained => todo!(), + //crossterm::event::Event::FocusLost => todo!(), + //crossterm::event::Event::Paste(_) => todo!(), + crossterm::event::Event::Key(key_event) => { + if key_event.code == KeyCode::Char('c') + && key_event.modifiers == KeyModifiers::CONTROL + { + sender.send(Event::Terminate).await?; + return Ok(()); + } + if key_event.code == KeyCode::Backspace { + sender.send(Event::Backspace).await?; + return Ok(()); + } + if let KeyCode::Char(c) = key_event.code { + sender.send(Event::KeyPress(c)).await?; + } + } + _ => (), + } + } + return Ok(()); +} diff --git a/src/main.rs b/src/main.rs index ba5277e..0365d5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ pub mod event; use std::{error::Error, fs::read_to_string, path::Path}; +use app::App; use clap::Parser; #[derive(Parser)] @@ -44,8 +45,12 @@ fn generate_quotes(path: &Path) -> Result<Vec<Vec<String>>, Box<dyn Error>> { } #[tokio::main] -async fn main() { +async fn main() -> Result<(), Box<dyn Error>> { let args = Args::parse(); let path = Path::new(&args.quote_folder); let quotes = generate_quotes(&path).unwrap(); + let mut app = App::new("es); + + app.run().await?; + return Ok(()); } |
