mirror of
https://git.aramjonghu.dev/AramJonghu/rustlings.git
synced 2026-09-06 01:53:30 +02:00
Pause input while running an exercise
This commit is contained in:
+41
-22
@@ -1,8 +1,32 @@
|
||||
use crossterm::event::{self, Event, KeyCode, KeyEventKind};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering::Relaxed},
|
||||
mpsc::Sender,
|
||||
};
|
||||
|
||||
use super::WatchEvent;
|
||||
|
||||
static INPUT_PAUSED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
// Private unit type to force using the constructor function.
|
||||
#[must_use = "When the guard is dropped, the input is unpaused"]
|
||||
pub struct InputPauseGuard(());
|
||||
|
||||
impl InputPauseGuard {
|
||||
#[inline]
|
||||
pub fn scoped_pause() -> Self {
|
||||
INPUT_PAUSED.store(true, Relaxed);
|
||||
Self(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InputPauseGuard {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
INPUT_PAUSED.store(false, Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
pub enum InputEvent {
|
||||
Run,
|
||||
Next,
|
||||
@@ -11,46 +35,41 @@ pub enum InputEvent {
|
||||
Quit,
|
||||
}
|
||||
|
||||
pub fn terminal_event_handler(tx: Sender<WatchEvent>, manual_run: bool) {
|
||||
let last_input_event = loop {
|
||||
let terminal_event = match event::read() {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
// If `send` returns an error, then the receiver is dropped and
|
||||
// a shutdown has been already initialized.
|
||||
let _ = tx.send(WatchEvent::TerminalEventErr(e));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match terminal_event {
|
||||
Event::Key(key) => {
|
||||
pub fn terminal_event_handler(sender: Sender<WatchEvent>, manual_run: bool) {
|
||||
let last_watch_event = loop {
|
||||
match event::read() {
|
||||
Ok(Event::Key(key)) => {
|
||||
match key.kind {
|
||||
KeyEventKind::Release | KeyEventKind::Repeat => continue,
|
||||
KeyEventKind::Press => (),
|
||||
}
|
||||
|
||||
if INPUT_PAUSED.load(Relaxed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let input_event = match key.code {
|
||||
KeyCode::Char('n') => InputEvent::Next,
|
||||
KeyCode::Char('h') => InputEvent::Hint,
|
||||
KeyCode::Char('l') => break InputEvent::List,
|
||||
KeyCode::Char('q') => break InputEvent::Quit,
|
||||
KeyCode::Char('l') => break WatchEvent::Input(InputEvent::List),
|
||||
KeyCode::Char('q') => break WatchEvent::Input(InputEvent::Quit),
|
||||
KeyCode::Char('r') if manual_run => InputEvent::Run,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if tx.send(WatchEvent::Input(input_event)).is_err() {
|
||||
if sender.send(WatchEvent::Input(input_event)).is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Event::Resize(width, _) => {
|
||||
if tx.send(WatchEvent::TerminalResize { width }).is_err() {
|
||||
Ok(Event::Resize(width, _)) => {
|
||||
if sender.send(WatchEvent::TerminalResize { width }).is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Event::FocusGained | Event::FocusLost | Event::Mouse(_) => continue,
|
||||
Ok(Event::FocusGained | Event::FocusLost | Event::Mouse(_)) => continue,
|
||||
Err(e) => break WatchEvent::TerminalEventErr(e),
|
||||
}
|
||||
};
|
||||
|
||||
let _ = tx.send(WatchEvent::Input(last_input_event));
|
||||
let _ = sender.send(last_watch_event);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user