keymaps 1.2.0

A rust crate which provides a standardized encoding for key codes
Documentation
// keymaps - A rust crate which provides a standardized encoding for key codes
//
// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// This file is part of the keymaps crate.
//
// You should have received a copy of the License along with this program.
// If not, see <https://www.gnu.org/licenses/lgpl-3.0.txt>.

use std::ops::Deref;

pub(crate) mod display;
pub(crate) mod parsing;

#[cfg(feature = "crossterm")]
pub(crate) mod crossterm;

#[cfg(feature = "serde")]
pub(crate) mod serde;

#[cfg(test)]
mod tests;

/// A representation of a key press.
/// This can be encoded in a string representation.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[allow(clippy::struct_excessive_bools)]
pub struct Key {
    pub(super) value: KeyValue,
    pub(super) modifiers: KeyModifiers,
}

impl Key {
    #[must_use]
    pub fn value(&self) -> KeyValue {
        self.value
    }

    #[must_use]
    pub fn modifiers(&self) -> KeyModifiers {
        self.modifiers
    }
}

/// A wrapper of a [`Vec<Key>`], which is incredible useful if you need to encode multiple [`Key`]s.
///
/// For example, `<UP>AB` would parse (with [`Key::parse_multiple`]) as a [`Vec<Key>`]. To support
/// `serde` this struct exists.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub struct Keys(Vec<Key>);

impl From<Keys> for Vec<Key> {
    fn from(value: Keys) -> Self {
        value.0
    }
}
impl From<Vec<Key>> for Keys {
    fn from(value: Vec<Key>) -> Self {
        Self(value)
    }
}
impl Deref for Keys {
    type Target = [Key];

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
#[allow(clippy::struct_excessive_bools)]
pub struct KeyModifiers {
    pub(super) alt: bool,
    pub(super) ctrl: bool,
    pub(super) meta: bool,
    pub(super) shift: bool,
}
impl KeyModifiers {
    #[must_use]
    pub fn alt(&self) -> bool {
        self.alt
    }
    #[must_use]
    pub fn ctrl(&self) -> bool {
        self.ctrl
    }
    #[must_use]
    pub fn meta(&self) -> bool {
        self.meta
    }
    #[must_use]
    pub fn shift(&self) -> bool {
        self.shift
    }
}

// taken directly from crossterm
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[allow(variant_size_differences)]
#[non_exhaustive]
pub enum KeyValue {
    Backspace,
    Enter,
    Left,
    Right,
    Up,
    Down,
    Home,
    End,
    PageUp,
    PageDown,
    Tab,
    BackTab,
    Delete,
    Insert,
    F(u8),
    Char(char),
    Null, // TODO(@soispha): Should we keep this key (as it's effectively not a key)?<2023-10-15>
    Esc,
    CapsLock,
    ScrollLock,
    NumLock,
    PrintScreen,
    Pause,
    Menu,
    KeypadBegin,
    Media(MediaKeyCode),

    #[cfg(feature = "mouse-keys")]
    MouseKey(MouseKeyValue),

    #[cfg(feature = "modifier-keys")]
    ModifierKey(ModifierKeyCode),
}

// also taken from crossterm
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub enum MediaKeyCode {
    Play,
    Pause,
    PlayPause,
    Reverse,
    Stop,
    FastForward,
    Rewind,
    TrackNext,
    TrackPrevious,
    Record,
    LowerVolume,
    RaiseVolume,
    MuteVolume,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[cfg(feature = "mouse-keys")]
pub enum MouseKeyValue {
    Left,
    Right,
    Middle,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[cfg(feature = "modifier-keys")]
pub enum ModifierKeyCode {
    LeftAlt,
    RightAlt,
    LeftCtrl,
    RightCtrl,
    LeftMeta,
    RightMeta,
    LeftShift,
    RightShift,
}