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 crossterm::event::KeyCode;

use crate::key_repr::MediaKeyCode;

#[cfg(feature = "modifier-keys")]
use crate::key_repr::ModifierKeyCode;

use super::KeyValue;

impl From<KeyCode> for KeyValue {
    fn from(value: KeyCode) -> Self {
        match value {
            KeyCode::Backspace => Self::Backspace,
            KeyCode::Enter => Self::Enter,
            KeyCode::Left => Self::Left,
            KeyCode::Right => Self::Right,
            KeyCode::Up => Self::Up,
            KeyCode::Down => Self::Down,
            KeyCode::Home => Self::Home,
            KeyCode::End => Self::End,
            KeyCode::PageUp => Self::PageUp,
            KeyCode::PageDown => Self::PageDown,
            KeyCode::Tab => Self::Tab,
            KeyCode::BackTab => Self::BackTab,
            KeyCode::Delete => Self::Delete,
            KeyCode::Insert => Self::Insert,
            KeyCode::F(n) => Self::F(n),
            KeyCode::Char(c) => Self::Char(c),
            KeyCode::Null => Self::Null,
            KeyCode::Esc => Self::Esc,
            KeyCode::CapsLock => Self::CapsLock,
            KeyCode::ScrollLock => Self::ScrollLock,
            KeyCode::NumLock => Self::NumLock,
            KeyCode::PrintScreen => Self::PrintScreen,
            KeyCode::Pause => Self::Pause,
            KeyCode::Menu => Self::Menu,
            KeyCode::KeypadBegin => Self::KeypadBegin,
            KeyCode::Media(value) => KeyValue::Media(match value {
                crossterm::event::MediaKeyCode::Play => MediaKeyCode::Play,
                crossterm::event::MediaKeyCode::Pause => MediaKeyCode::Pause,
                crossterm::event::MediaKeyCode::PlayPause => MediaKeyCode::PlayPause,
                crossterm::event::MediaKeyCode::Reverse => MediaKeyCode::Reverse,
                crossterm::event::MediaKeyCode::Stop => MediaKeyCode::Stop,
                crossterm::event::MediaKeyCode::FastForward => MediaKeyCode::FastForward,
                crossterm::event::MediaKeyCode::Rewind => MediaKeyCode::Rewind,
                crossterm::event::MediaKeyCode::TrackNext => MediaKeyCode::TrackNext,
                crossterm::event::MediaKeyCode::TrackPrevious => MediaKeyCode::TrackPrevious,
                crossterm::event::MediaKeyCode::Record => MediaKeyCode::Record,
                crossterm::event::MediaKeyCode::LowerVolume => MediaKeyCode::LowerVolume,
                crossterm::event::MediaKeyCode::RaiseVolume => MediaKeyCode::RaiseVolume,
                crossterm::event::MediaKeyCode::MuteVolume => MediaKeyCode::MuteVolume,
            }),

            // FIXME(@soispha): This reduces our information, casting a KeyCode to a KeyValue
            // and back again would not equal the original KeyCode <2023-10-15>
            KeyCode::Modifier(_) => Self::Null,
        }
    }
}
impl From<KeyValue> for KeyCode {
    fn from(value: KeyValue) -> KeyCode {
        match value {
            KeyValue::Backspace => KeyCode::Backspace,
            KeyValue::Enter => KeyCode::Enter,
            KeyValue::Left => KeyCode::Left,
            KeyValue::Right => KeyCode::Right,
            KeyValue::Up => KeyCode::Up,
            KeyValue::Down => KeyCode::Down,
            KeyValue::Home => KeyCode::Home,
            KeyValue::End => KeyCode::End,
            KeyValue::PageUp => KeyCode::PageUp,
            KeyValue::PageDown => KeyCode::PageDown,
            KeyValue::Tab => KeyCode::Tab,
            KeyValue::BackTab => KeyCode::BackTab,
            KeyValue::Delete => KeyCode::Delete,
            KeyValue::Insert => KeyCode::Insert,
            KeyValue::F(n) => KeyCode::F(n),
            KeyValue::Char(c) => KeyCode::Char(c),
            KeyValue::Null => KeyCode::Null,
            KeyValue::Esc => KeyCode::Esc,
            KeyValue::CapsLock => KeyCode::CapsLock,
            KeyValue::ScrollLock => KeyCode::ScrollLock,
            KeyValue::NumLock => KeyCode::NumLock,
            KeyValue::PrintScreen => KeyCode::PrintScreen,
            KeyValue::Pause => KeyCode::Pause,
            KeyValue::Menu => KeyCode::Menu,
            KeyValue::KeypadBegin => KeyCode::KeypadBegin,
            KeyValue::Media(media_key_code) => KeyCode::Media(match media_key_code {
                MediaKeyCode::Play => crossterm::event::MediaKeyCode::Play,
                MediaKeyCode::Pause => crossterm::event::MediaKeyCode::Pause,
                MediaKeyCode::PlayPause => crossterm::event::MediaKeyCode::PlayPause,
                MediaKeyCode::Reverse => crossterm::event::MediaKeyCode::Reverse,
                MediaKeyCode::Stop => crossterm::event::MediaKeyCode::Stop,
                MediaKeyCode::FastForward => crossterm::event::MediaKeyCode::FastForward,
                MediaKeyCode::Rewind => crossterm::event::MediaKeyCode::Rewind,
                MediaKeyCode::TrackNext => crossterm::event::MediaKeyCode::TrackNext,
                MediaKeyCode::TrackPrevious => crossterm::event::MediaKeyCode::TrackPrevious,
                MediaKeyCode::Record => crossterm::event::MediaKeyCode::Record,
                MediaKeyCode::LowerVolume => crossterm::event::MediaKeyCode::LowerVolume,
                MediaKeyCode::RaiseVolume => crossterm::event::MediaKeyCode::RaiseVolume,
                MediaKeyCode::MuteVolume => crossterm::event::MediaKeyCode::MuteVolume,
            }),

            // FIXME(@bpeetz): `crossterm` uses a different enum for that. <2025-02-01>
            #[cfg(feature = "mouse-keys")]
            KeyValue::MouseKey(_) => KeyCode::Null,
            #[cfg(feature = "modifier-keys")]
            KeyValue::ModifierKey(modifier_key_code) => {
                KeyCode::Modifier(match modifier_key_code {
                    ModifierKeyCode::LeftAlt => crossterm::event::ModifierKeyCode::LeftAlt,
                    ModifierKeyCode::RightAlt => crossterm::event::ModifierKeyCode::RightAlt,
                    ModifierKeyCode::LeftCtrl => crossterm::event::ModifierKeyCode::LeftControl,
                    ModifierKeyCode::RightCtrl => crossterm::event::ModifierKeyCode::RightControl,
                    ModifierKeyCode::LeftMeta => crossterm::event::ModifierKeyCode::LeftSuper,
                    ModifierKeyCode::RightMeta => crossterm::event::ModifierKeyCode::RightSuper,
                    ModifierKeyCode::LeftShift => crossterm::event::ModifierKeyCode::LeftShift,
                    ModifierKeyCode::RightShift => crossterm::event::ModifierKeyCode::RightShift,
                })
            }
        }
    }
}