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::{
    Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers as CrosstermKeyModifiers,
};

use crate::{error, key_repr::KeyValue};

use super::{Key, KeyModifiers};

mod key_value;

#[cfg(test)]
mod tests;

impl From<Key> for Event {
    fn from(value: Key) -> Self {
        let mut modifiers;
        {
            modifiers = CrosstermKeyModifiers::all();
            if !value.modifiers.alt {
                modifiers.remove(CrosstermKeyModifiers::ALT);
            }
            if !value.modifiers.ctrl {
                modifiers.remove(CrosstermKeyModifiers::CONTROL);
            }
            if !value.modifiers.meta {
                modifiers.remove(CrosstermKeyModifiers::META);
                modifiers.remove(CrosstermKeyModifiers::SUPER);
            }
            if !value.modifiers.shift {
                modifiers.remove(CrosstermKeyModifiers::SHIFT);
            }
            modifiers.remove(CrosstermKeyModifiers::HYPER);
            modifiers.remove(CrosstermKeyModifiers::META);
            if value.modifiers.alt
                || value.modifiers.ctrl
                || value.modifiers.meta
                || value.modifiers.shift
            {
                modifiers.remove(CrosstermKeyModifiers::NONE);
            }
        }

        Event::Key(KeyEvent {
            code: {
                if let KeyValue::Char(char) = value.value {
                    KeyCode::Char(char)
                } else {
                    value.value.into()
                }
            },
            modifiers,
            kind: KeyEventKind::Press,
            state: KeyEventState::NONE,
        })
    }
}

impl TryFrom<&Event> for Key {
    type Error = error::KeyFromCrossterm;

    fn try_from(value: &Event) -> Result<Self, Self::Error> {
        match value {
            Event::Key(key_event) => {
                let mut modifiers = KeyModifiers::default();
                {
                    let key_mods = key_event.modifiers;

                    modifiers.alt =
                        CrosstermKeyModifiers::intersects(&key_mods, CrosstermKeyModifiers::ALT);
                    modifiers.ctrl = CrosstermKeyModifiers::intersects(
                        &key_mods,
                        CrosstermKeyModifiers::CONTROL,
                    );
                    modifiers.meta =
                        CrosstermKeyModifiers::intersects(&key_mods, CrosstermKeyModifiers::META)
                            || CrosstermKeyModifiers::intersects(
                                &key_mods,
                                CrosstermKeyModifiers::SUPER,
                            );
                    modifiers.shift =
                        CrosstermKeyModifiers::intersects(&key_mods, CrosstermKeyModifiers::SHIFT);
                    // let hyper = CrosstermKeyModifiers::intersects(&key_mods, CrosstermKeyModifiers::HYPER);
                    // let none = CrosstermKeyModifiers::intersects(&key_mods, CrosstermKeyModifiers::NONE);
                }

                let output_key = Key {
                    value: key_event.code.into(),
                    modifiers,
                };

                Ok(output_key)
            }
            event => Err(error::KeyFromCrossterm::OnlyKey(event.to_owned())),
        }
    }
}