Skip to main content

rskit_cli/prompt/
key.rs

1//! The keystroke vocabulary a key-driven [`Terminal`](crate::prompt::terminal::Terminal) yields.
2//!
3//! [`Key`] is rskit's own, minimal key abstraction
4//! so no third-party terminal type (crossterm, termion, …) leaks into the public prompt surface.
5//! The rich terminal maps platform events onto it;
6//! the scripted terminal feeds canned sequences of it in tests.
7
8/// A single decoded keystroke from an interactive terminal.
9///
10/// Only the keys the prompt widgets act on are modelled; anything else decodes to [`Key::Unknown`]
11/// so callers can ignore it without a catch-all on a platform enum.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum Key {
15    /// Confirm the current answer (Enter / Return).
16    Enter,
17    /// Space bar — toggles the focused item in multi-select, or inserts a literal space in text entry.
18    Space,
19    /// Delete the character before the cursor (Backspace).
20    Backspace,
21    /// Abandon the prompt (Escape).
22    Escape,
23    /// Advance focus (Tab).
24    Tab,
25    /// Move focus up / to the previous item.
26    Up,
27    /// Move focus down / to the next item.
28    Down,
29    /// Move the text cursor left.
30    Left,
31    /// Move the text cursor right.
32    Right,
33    /// Jump to the first item / start of line.
34    Home,
35    /// Jump to the last item / end of line.
36    End,
37    /// A printable character was typed.
38    Char(char),
39    /// A cancellation request (Ctrl+C / Ctrl+D).
40    Interrupt,
41    /// A key with no prompt-relevant meaning.
42    Unknown,
43}
44
45impl Key {
46    /// Whether this key represents a cancellation request.
47    #[must_use]
48    pub const fn is_interrupt(self) -> bool {
49        matches!(self, Self::Interrupt)
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::Key;
56
57    #[test]
58    fn only_interrupt_reports_as_interrupt() {
59        assert!(Key::Interrupt.is_interrupt());
60        for key in [
61            Key::Enter,
62            Key::Escape,
63            Key::Char('a'),
64            Key::Space,
65            Key::Unknown,
66        ] {
67            assert!(!key.is_interrupt());
68        }
69    }
70}