noterm 0.2.3

noterm, a no_std terminal handler.
Documentation
//! Events.

use bitflags::bitflags;

pub mod parser;
pub mod stream;

pub use parser::parse;
pub use stream::stream;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Event {
    Cursor(CursorEvent),
    Key(KeyEvent),
    Screen(ScreenEvent),
}

impl Event {
    pub fn is_screen_event(&self) -> bool {
        matches!(self, Event::Screen(_))
    }

    pub fn as_screen_event(&self) -> Option<&ScreenEvent> {
        if let Event::Screen(event) = &self {
            return Some(event);
        }

        None
    }

    pub fn is_key_event(&self) -> bool {
        matches!(self, Event::Key(_))
    }

    pub fn as_key_event(&self) -> Option<&KeyEvent> {
        if let Event::Key(event) = &self {
            return Some(event);
        }

        None
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CursorEvent {
    Positioned { x: u16, y: u16 },
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct KeyEvent {
    pub code: KeyCode,
    pub modifiers: KeyModifiers,
    pub kind: KeyEventKind,
}

impl KeyEvent {
    pub fn new(code: KeyCode) -> Self {
        KeyEvent {
            code,
            modifiers: KeyModifiers::empty(),
            kind: KeyEventKind::Pressed,
        }
    }

    pub fn with_modifiers(mut self, modifiers: KeyModifiers) -> Self {
        self.modifiers |= modifiers;
        self
    }

    pub fn with_modifiers_maybe(mut self, modifiers_maybe: Option<KeyModifiers>) -> Self {
        if let Some(modifiers) = modifiers_maybe {
            self.modifiers |= modifiers;
        }
        self
    }

    pub fn with_kind(mut self, kind: KeyEventKind) -> Self {
        self.kind = kind;
        self
    }

    pub fn with_kind_maybe(mut self, kind_maybe: Option<KeyEventKind>) -> Self {
        if let Some(kind) = kind_maybe {
            self.kind = kind;
        }
        self
    }

    pub fn sanitize(mut self) -> Self {
        if self.code == KeyCode::Tab && self.modifiers.contains(KeyModifiers::SHIFT) {
            self.code = KeyCode::BackTab;
        }

        self
    }

    pub fn is_key_pressed(&self) -> bool {
        self.kind == KeyEventKind::Pressed
    }

    pub fn as_key_pressed(&self) -> Option<&KeyEvent> {
        if let KeyEvent {
            code: _,
            modifiers: _,
            kind: KeyEventKind::Pressed,
        } = &self
        {
            return Some(self);
        }

        None
    }

    pub fn is_key_released(&self) -> bool {
        self.kind == KeyEventKind::Released
    }

    pub fn as_key_released(&self) -> Option<&KeyEvent> {
        if let KeyEvent {
            code: _,
            modifiers: _,
            kind: KeyEventKind::Released,
        } = &self
        {
            return Some(self);
        }

        None
    }

    pub fn is_key_repeated(&self) -> bool {
        self.kind == KeyEventKind::Repeated
    }

    pub fn as_key_repeated(&self) -> Option<&KeyEvent> {
        if let KeyEvent {
            code: _,
            modifiers: _,
            kind: KeyEventKind::Repeated,
        } = &self
        {
            return Some(self);
        }

        None
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum KeyCode {
    Backspace,
    Enter,
    Left,
    Right,
    Up,
    Down,
    Home,
    End,
    PageUp,
    PageDown,
    Tab,
    BackTab,
    Delete,
    Insert,
    Fn(u8),
    Char(char),
    Escape,
    Modifier(ModifierKeyCode),
}

impl KeyCode {
    pub fn is_function_key(&self) -> bool {
        matches!(self, KeyCode::Fn(_))
    }

    pub fn as_function_key(&self) -> Option<&KeyCode> {
        if let KeyCode::Fn(_) = &self {
            return Some(self);
        }

        None
    }

    pub fn is_modifier_key(&self) -> bool {
        matches!(self, KeyCode::Modifier(_))
    }

    pub fn as_modifier_key(&self) -> Option<&KeyCode> {
        if let KeyCode::Modifier(_) = &self {
            return Some(self);
        }

        None
    }

    pub fn is_char_key(&self) -> bool {
        matches!(self, KeyCode::Char(_))
    }

    pub fn as_char_key(&self) -> Option<&KeyCode> {
        if let KeyCode::Char(_) = &self {
            return Some(self);
        }

        None
    }
}

impl From<KeyCode> for KeyEvent {
    fn from(code: KeyCode) -> Self {
        KeyEvent {
            code,
            modifiers: KeyModifiers::empty(),
            kind: KeyEventKind::Pressed,
        }
    }
}

impl From<(KeyCode, KeyModifiers)> for KeyEvent {
    fn from(value: (KeyCode, KeyModifiers)) -> Self {
        KeyEvent::from(value.0).with_modifiers(value.1)
    }
}

impl From<(KeyCode, Option<KeyModifiers>)> for KeyEvent {
    fn from(value: (KeyCode, Option<KeyModifiers>)) -> Self {
        KeyEvent::from(value.0).with_modifiers_maybe(value.1)
    }
}

impl From<(KeyCode, KeyEventKind)> for KeyEvent {
    fn from(value: (KeyCode, KeyEventKind)) -> Self {
        KeyEvent::from(value.0).with_kind(value.1)
    }
}

impl From<(KeyCode, Option<KeyEventKind>)> for KeyEvent {
    fn from(value: (KeyCode, Option<KeyEventKind>)) -> Self {
        KeyEvent::from(value.0).with_kind_maybe(value.1)
    }
}

impl From<(KeyCode, (KeyModifiers, KeyEventKind))> for KeyEvent {
    fn from(value: (KeyCode, (KeyModifiers, KeyEventKind))) -> Self {
        KeyEvent::from(value.0)
            .with_modifiers(value.1.0)
            .with_kind(value.1.1)
    }
}

impl From<(KeyCode, Option<(KeyModifiers, KeyEventKind)>)> for KeyEvent {
    fn from(value: (KeyCode, Option<(KeyModifiers, KeyEventKind)>)) -> Self {
        if let Some(key_modifiers_and_kind) = value.1 {
            KeyEvent::from((value.0, key_modifiers_and_kind))
        } else {
            KeyEvent::from(value.0)
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ModifierKeyCode {
    LeftShift,
    LeftControl,
    LeftAlt,
    LeftSuper,
    LeftMeta,
    RightShift,
    RightControl,
    RightAlt,
    RightSuper,
    RightMeta,
}

impl From<ModifierKeyCode> for KeyEvent {
    fn from(code: ModifierKeyCode) -> Self {
        KeyEvent {
            code: KeyCode::Modifier(code),
            modifiers: KeyModifiers::empty(),
            kind: KeyEventKind::Pressed,
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct KeyModifiers(u8);

bitflags! {
    impl KeyModifiers: u8 {
        const SHIFT = 1 << 0;
        const CONTROL = 1 << 1;
        const ALT = 1 << 2;
        const SUPER = 1 << 3;
        const META = 1 << 5;
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum KeyEventKind {
    Pressed,
    Released,
    Repeated,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ScreenEvent {
    FocusGained,
    FocusLost,
    Resized { width: u16, height: u16 },
}

impl ScreenEvent {
    pub fn is_focus_gained(&self) -> bool {
        *self == ScreenEvent::FocusGained
    }

    pub fn is_focus_lost(&self) -> bool {
        *self == ScreenEvent::FocusLost
    }

    pub fn is_resized(&self) -> bool {
        matches!(
            self,
            ScreenEvent::Resized {
                width: _,
                height: _
            }
        )
    }

    pub fn as_resized(&self) -> Option<&ScreenEvent> {
        if let ScreenEvent::Resized {
            width: _,
            height: _,
        } = &self
        {
            return Some(self);
        }

        None
    }
}