console_input/
keypress.rs

1pub use crossterm::event::{self, Event};
2use crossterm::event::{poll, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
3use std::time::Duration;
4
5mod raw_mode;
6pub use raw_mode::{disable as disable_raw_mode, enable as enable_raw_mode, exit as exit_raw_mode};
7
8/// Get an [`Event`]. When raw mode is disabled, the input will only be registered after enter is pressed. Call [`enable_raw_mode()`] at the beginning of the program to avoid having to press enter
9#[must_use]
10pub fn read() -> Option<Event> {
11    event::read().ok()
12}
13
14/// Get an [`Event`], without blocking. When raw mode is disabled, the input will only be registered after enter is pressed. Call [`enable_raw_mode()`] at the beginning of the program to avoid having to press enter
15#[must_use]
16pub fn read_non_blocking() -> Option<Event> {
17    match poll(Duration::ZERO) {
18        Ok(true) => read(),
19        _ => None,
20    }
21}
22
23/// If the event is a `Ctrl+C` (Keyboard Interrupt), exit immediately.
24///
25/// ## Example
26/// ```
27/// # use console_input::keypress;
28/// # let event = keypress::read_non_blocking();
29/// // Will get the input but exit the process if the input was `Ctrl+C`
30/// keypress::exit_if_kb_interrupt(&event);
31/// ```
32pub fn exit_if_kb_interrupt(event: &Option<Event>) {
33    if matches!(
34        event,
35        Some(Event::Key(KeyEvent {
36            code: KeyCode::Char('c'),
37            modifiers: KeyModifiers::CONTROL,
38            kind: KeyEventKind::Press,
39            ..
40        }))
41    ) {
42        exit_raw_mode();
43    }
44}
45
46/// Get an input, with or without blocking, and exit if the input is a keyboard interrupt (Ctrl+C)
47///
48/// ## Example
49/// ```
50/// # use console_input::keypress;
51/// // Will get the input without blocking, but exit the process if the input was `Ctrl+C`
52/// let event = keypress::read_and_handle_kb_interrupt(false);
53/// ```
54#[must_use]
55pub fn read_and_handle_kb_interrupt(blocking: bool) -> Option<Event> {
56    let event = if blocking {
57        read()
58    } else {
59        read_non_blocking()
60    };
61    exit_if_kb_interrupt(&event);
62    event
63}