diff options
author | Sam Tay <samctay@pm.me> | 2022-08-22 18:02:16 -0700 |
---|---|---|
committer | Sam Tay <samctay@pm.me> | 2022-08-22 18:20:50 -0700 |
commit | 29815c2fabc4e691fcf94fd26dea22a0ca81aaf4 (patch) | |
tree | c95b42d7f065759042aa887604075937688c70e0 | |
parent | a5c3a48b421dd75075531937e60e32008c3c3b97 (diff) |
Dont block tokio task
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/error.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/term.rs | 40 |
5 files changed, 35 insertions, 18 deletions
@@ -29,6 +29,12 @@ dependencies = [ ] [[package]] +name = "anyhow" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" + +[[package]] name = "async-compression" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2026,6 +2032,7 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" name = "so" version = "0.4.8" dependencies = [ + "anyhow", "clap", "criterion", "crossterm", @@ -30,6 +30,7 @@ path = "benches/md_parsing.rs" harness = false [dependencies] +anyhow = "1.0" clap = "2.33" crossterm = { version = "0.23", features = ["event-stream"] } directories = "2.0" diff --git a/src/error.rs b/src/error.rs index 2bcb899..cc15174 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,8 +2,11 @@ use std::path::PathBuf; pub type Result<T, E = Error> = std::result::Result<T, E>; +// TODO convert/remove this to just use anyhow #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("{0}")] + Anyhow(#[from] anyhow::Error), #[error("Termimad error: {0}")] Termimad(#[from] termimad::Error), #[error("Crossterm error: {0}")] diff --git a/src/main.rs b/src/main.rs index e732d5a..40a1e51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,7 +88,7 @@ async fn run() -> Result<Option<tui::App>> { // Kick off the rest of the search in the background let app = task::spawn(async move { tui::App::from_search(search).await }); - if !Term::wait_for_char(' ')? { + if !Term::wait_for_char(' ').await? { return Ok(None); } diff --git a/src/term.rs b/src/term.rs index abb27c3..e986bf7 100644 --- a/src/term.rs +++ b/src/term.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use crossterm::event::{read, Event, KeyCode, KeyEvent}; use crossterm::style::{Color, Print}; use crossterm::terminal::ClearType; @@ -83,26 +84,31 @@ impl Term { Ok(()) } - /// Blocks and waits for the user to press any key. Returns whether or not that key is the + /// Waits for the user to press any key. Returns whether or not that key is the /// character key `c`. - pub fn wait_for_char(c: char) -> Result<bool> { - let mut pressed = false; - terminal::enable_raw_mode()?; - loop { - match read()? { - Event::Key(KeyEvent { - code: KeyCode::Char(ch), - .. - }) if ch == c => { - pressed = true; - break; + pub async fn wait_for_char(c: char) -> Result<bool> { + let (tx, rx) = oneshot::channel(); + + tokio::task::spawn_blocking(move || { + let mut pressed = false; + terminal::enable_raw_mode().unwrap(); + loop { + match read().unwrap() { + Event::Key(KeyEvent { + code: KeyCode::Char(ch), + .. + }) if ch == c => { + pressed = true; + break; + } + Event::Key(_) => break, + _ => (), } - Event::Key(_) => break, - _ => (), } - } - terminal::disable_raw_mode()?; - Ok(pressed) + terminal::disable_raw_mode().unwrap(); + tx.send(pressed).unwrap(); + }); + Ok(rx.await.context("failed to get key event")?) } /// As it sounds, takes a future and shows a CLI spinner until it's output is ready |