Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a3bf8be

Browse files
committed
Ignore interrupts when reading inputs…
…as they can happen when the program is put into the background for instance.
1 parent b5aa292 commit a3bf8be

1 file changed

Lines changed: 33 additions & 3 deletions

File tree

crosstermion/src/input.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ pub enum Key {
2121
Esc,
2222
}
2323

24+
#[cfg(any(feature = "crossterm", feature = "termion"))]
25+
enum Action<T> {
26+
Continue,
27+
Result(Result<T, std::io::Error>),
28+
}
29+
30+
#[cfg(any(feature = "crossterm", feature = "termion"))]
31+
fn continue_on_interrupt<T>(result: Result<T, std::io::Error>) -> Action<T> {
32+
match result {
33+
Ok(v) => Action::Result(Ok(v)),
34+
Err(err) if err.kind() == std::io::ErrorKind::Interrupted => Action::Continue,
35+
Err(err) => Action::Result(Err(err)),
36+
}
37+
}
38+
2439
mod convert {
2540
#[cfg(any(feature = "crossterm", feature = "termion"))]
2641
use super::Key;
@@ -94,14 +109,21 @@ mod convert {
94109

95110
#[cfg(feature = "crossterm")]
96111
mod _impl {
112+
use crate::input::{continue_on_interrupt, Action};
113+
97114
/// Return a receiver of user input events to avoid blocking the main thread.
98115
pub fn key_input_channel() -> std::sync::mpsc::Receiver<super::Key> {
99116
use std::convert::TryInto;
100117

101118
let (key_send, key_receive) = std::sync::mpsc::sync_channel(0);
102119
std::thread::spawn(move || -> Result<(), std::io::Error> {
103120
loop {
104-
let event = crossterm::event::read().map_err(crate::crossterm_utils::into_io_error)?;
121+
let event = match continue_on_interrupt(
122+
crossterm::event::read().map_err(crate::crossterm_utils::into_io_error),
123+
) {
124+
Action::Continue => continue,
125+
Action::Result(res) => res?,
126+
};
105127
match event {
106128
crossterm::event::Event::Key(key) => {
107129
let key: Result<super::Key, _> = key.try_into();
@@ -137,6 +159,8 @@ mod _impl {
137159

138160
#[cfg(all(feature = "termion", not(feature = "crossterm")))]
139161
mod _impl {
162+
use crate::input::{continue_on_interrupt, Action};
163+
140164
/// Return a stream of user input events.
141165
///
142166
/// Requires feature `futures-channel`
@@ -149,7 +173,10 @@ mod _impl {
149173
// This brings blocking key-handling into the async world
150174
std::thread::spawn(move || -> Result<(), io::Error> {
151175
for key in io::stdin().keys() {
152-
let key: Result<super::Key, _> = key?.try_into();
176+
let key: Result<super::Key, _> = match continue_on_interrupt(key) {
177+
Action::Continue => continue,
178+
Action::Result(res) => res?.try_into(),
179+
};
153180
if let Ok(key) = key {
154181
if futures_lite::future::block_on(key_send.send(key)).is_err() {
155182
break;
@@ -168,7 +195,10 @@ mod _impl {
168195
let (key_send, key_receive) = std::sync::mpsc::sync_channel(0);
169196
std::thread::spawn(move || -> Result<(), io::Error> {
170197
for key in io::stdin().keys() {
171-
let key: Result<super::Key, _> = key?.try_into();
198+
let key: Result<super::Key, _> = match continue_on_interrupt(key) {
199+
Action::Continue => continue,
200+
Action::Result(res) => res?.try_into(),
201+
};
172202
if let Ok(key) = key {
173203
if key_send.send(key).is_err() {
174204
break;

0 commit comments

Comments
 (0)