aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMroik <mroik@delayed.space>2025-11-27 04:42:48 +0100
committerMroik <mroik@delayed.space>2025-11-27 04:42:48 +0100
commitc32dcfc16bc5a5013c04d9c28793939b19aa88f5 (patch)
treebe08548373db8db74c5e01d8283d540217284ea8
parentf945f51a1092df692b5c47296bc681dc5507aff6 (diff)
Refactor events generationssingle-loop-event-generation
Move all events generation in the same code section
-rw-r--r--src/app.rs82
-rw-r--r--src/event.rs36
2 files changed, 47 insertions, 71 deletions
diff --git a/src/app.rs b/src/app.rs
index 45eca05..65d4f9c 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -15,9 +15,10 @@ use crossterm::{
},
};
use tokio::{
- spawn,
+ select,
sync::mpsc::{Receiver, Sender, channel},
- time::Instant,
+ task::spawn_blocking,
+ time::{self, Instant},
};
use crate::{
@@ -68,21 +69,16 @@ impl App<'_> {
}
}
- async fn run(&mut self) -> Result<(f64, f64, String), Box<dyn Error>> {
+ pub async fn start(&mut self) -> Result<(), Box<dyn Error>> {
self.stdout
.execute(EnterAlternateScreen)?
.execute(SetCursorStyle::SteadyBar)?;
enable_raw_mode()?;
- let (input_ks_tx, input_ks_rx) = channel(1);
- let (tick_ks_tx, tick_ks_rx) = channel(1);
- spawn(start_input_handler(self.event_tx.clone(), input_ks_rx));
- spawn(start_tick_generator(self.event_tx.clone(), tick_ks_rx));
-
self.running = true;
self.start = Some(Instant::now());
while self.running {
- self.process().await?;
+ self.run().await?;
}
let time = self.start.unwrap().elapsed().as_millis();
let total_chars = self
@@ -96,16 +92,9 @@ impl App<'_> {
let accuracy = total_chars * 100.0 / (total_chars + self.mistake_count as f64);
let history = self.generate_mistake_locations().await;
- input_ks_tx.send(()).await?;
- tick_ks_tx.send(()).await?;
-
disable_raw_mode()?;
self.stdout.execute(LeaveAlternateScreen)?;
- return Ok((wpm, accuracy, history));
- }
- pub async fn start(&mut self) -> Result<(), Box<dyn Error>> {
- let (wpm, accuracy, history) = self.run().await?;
if self.completed {
println!(
"Mistake history:\n{}\n\nYour stats\nWPM: {}\nAccuracy: {}%\nMistakes: {}",
@@ -149,18 +138,34 @@ impl App<'_> {
return a.join(" ");
}
- async fn process(&mut self) -> Result<(), Box<dyn Error>> {
- let event = self.event_rx.recv().await.unwrap();
- match event {
- Event::Terminate => self.running = false,
- Event::KeyPress(k) => self.handle_keypress(k).await?,
- Event::Backspace => self.handle_backspace().await,
- Event::Render => self.render().await?,
- Event::ForceRender => (),
- }
+ async fn run(&mut self) -> Result<(), Box<dyn Error>> {
+ let ev = self.event_tx.clone();
+ let mut tick_render = time::interval(Duration::from_millis(TICK_RATE));
+
+ // TODO: Handle errors
+ select! {
+ event = self.event_rx.recv() => {
+ let event = event.unwrap();
+ match event {
+ Event::Terminate => self.running = false,
+ Event::KeyPress(k) => self.handle_keypress(k).await?,
+ Event::Backspace => self.handle_backspace().await,
+ Event::Render => self.render().await?,
+ Event::ForceRender => (),
+ }
- if event != Event::Render {
- self.should_render = true;
+ if event != Event::Render {
+ self.should_render = true;
+ }
+ }
+ Ok(sst) = spawn_blocking(|| crossterm::event::poll(Duration::from_millis(TICK_RATE))) => {
+ if sst.unwrap() {
+ handle_input(self.event_tx.clone()).await.unwrap();
+ }
+ },
+ _ = tick_render.tick() => {
+ ev.send(Event::Render).await.unwrap();
+ },
}
return Ok(());
}
@@ -261,7 +266,7 @@ impl App<'_> {
.iter()
.map(|line| line.len())
.sum::<usize>();
- for i in 0..lines[current_line].len() {
+ for (i, _) in lines[current_line].iter().enumerate() {
if i + offset < self.state.current {
self.stdout
.queue(SetForegroundColor(Color::Green))?
@@ -342,27 +347,6 @@ impl App<'_> {
}
}
-async fn start_tick_generator(ev: Sender<Event>, mut kill_switch: Receiver<()>) {
- loop {
- tokio::select! {
- _ = async {
- tokio::time::sleep(Duration::from_millis(TICK_RATE)).await;
- ev.send(Event::Render).await
- } => (),
- _ = kill_switch.recv() => return,
- }
- }
-}
-
-async fn start_input_handler(ev: Sender<Event>, mut kill_switch: Receiver<()>) {
- loop {
- tokio::select! {
- _ = handle_input(&ev) => (),
- _ = kill_switch.recv() => return,
- }
- }
-}
-
async fn format_quote(quote: &str, row_len: u16) -> Result<Vec<Vec<&str>>, WordTooLongError> {
let max = if row_len - (MIN_MARGIN * 2) < MAX_QUOTE_LINE {
row_len - (MIN_MARGIN * 2)
diff --git a/src/event.rs b/src/event.rs
index 7e0db3e..22d538b 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -1,10 +1,8 @@
-use std::{error::Error, time::Duration};
+use std::error::Error;
-use crossterm::event::{KeyCode, KeyModifiers, poll, read};
+use crossterm::event::{KeyCode, KeyModifiers, read};
use tokio::sync::mpsc::Sender;
-use crate::app::TICK_RATE;
-
#[derive(PartialEq)]
pub enum Event {
Terminate,
@@ -17,25 +15,19 @@ pub enum Event {
// 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::Resize(_, _) => sender.send(Event::ForceRender).await?,
- crossterm::event::Event::Key(key_event) => {
- match (key_event.code, key_event.modifiers) {
- (KeyCode::Char('c'), KeyModifiers::CONTROL) => {
- sender.send(Event::Terminate).await?
- }
- (KeyCode::Backspace, _) => sender.send(Event::Backspace).await?,
- (KeyCode::Char(c), _) => sender.send(Event::KeyPress(c)).await?,
- _ => (),
- }
- }
+pub async fn handle_input(sender: Sender<Event>) -> Result<(), Box<dyn Error>> {
+ match read()? {
+ //crossterm::event::Event::FocusGained => todo!(),
+ //crossterm::event::Event::FocusLost => todo!(),
+ //crossterm::event::Event::Paste(_) => todo!(),
+ crossterm::event::Event::Resize(_, _) => sender.send(Event::ForceRender).await?,
+ crossterm::event::Event::Key(key_event) => match (key_event.code, key_event.modifiers) {
+ (KeyCode::Char('c'), KeyModifiers::CONTROL) => sender.send(Event::Terminate).await?,
+ (KeyCode::Backspace, _) => sender.send(Event::Backspace).await?,
+ (KeyCode::Char(c), _) => sender.send(Event::KeyPress(c)).await?,
_ => (),
- }
+ },
+ _ => (),
}
return Ok(());
}
XMR address: 854DmXNrxULU3ZFJVs4Wc8PFhbq29RhqHhY8W6cdWrtFN3qmooKyyeYPcDzZTNRxphhJ5UzASQfAdEMwSteVqymk28aLhqj