#[cfg_attr(all(feature = "strum"), derive(strum::EnumIter))]
#[cfg_attr(all(feature = "enum_ext"), enum_ext::enum_extend)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bitcode", derive(bitcode::Encode, bitcode::Decode))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash, PartialOrd, Ord)]
#[allow(missing_docs)]
#[cfg_attr(feature = "c_compatible", repr(C))]
pub enum KeyCode {
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
Num0,
Num1,
Num2,
Num3,
Num4,
Num5,
Num6,
Num7,
Num8,
Num9,
KeyPad0,
KeyPad1,
KeyPad2,
KeyPad3,
KeyPad4,
KeyPad5,
KeyPad6,
KeyPad7,
KeyPad8,
KeyPad9,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
LeftShift,
RightShift,
LeftControl,
RightControl,
LeftAlt,
RightAlt,
LeftSuper,
RightSuper,
LeftHyper,
RightHyper,
AltControl,
Space,
Enter,
Escape,
Backspace,
Tab,
BackTab,
Comma,
Period,
Minus,
Equal,
LeftBracket,
RightBracket,
Backslash,
Semicolon,
Quote,
Tilde,
Slash,
Grave,
Apostrophe,
UpArrow,
DownArrow,
LeftArrow,
RightArrow,
Insert,
Delete,
Home,
End,
PageUp,
PageDown,
CapsLock,
NumLock,
ScrollLock,
KeyPadDivide,
KeyPadMultiply,
KeyPadSubtract,
KeyPadAdd,
KeyPadDecimal,
KeyPadEnter,
AUmlautÄ,
UUmlautÜ,
OUmlautÖ,
SS,
ACircumflexÂ,
UAcuteÚ,
OCircumflexÔ,
ICircumflexÎ,
ECircumflexÊ,
EthÐ,
OELigatureŒ,
AAcuteÁ,
YAcuteÝ,
IUmlautÏ,
NTildeÑ,
OGraveÒ,
UGraveÙ,
ARingÅ,
AELigatureÆ,
OSlashØ,
IGraveÌ,
ThornÞ,
MediaPlayPause,
MediaPlay,
MediaPause,
MediaStop,
MediaNext,
MediaPrev,
VolumeUp,
VolumeDown,
Mute,
MediaReverse,
MediaFastForward,
MediaRecord,
BrowserBack,
BrowserForward,
BrowserRefresh,
BrowserHome,
LaunchMail,
LaunchApp1,
LaunchApp2,
Menu,
PrintScreen,
Pause,
Application,
AnyShift,
AnyAlt,
AnyControl,
AnySuper,
F25,
KeyPadEqual,
World1,
World2,
SpecialControl,
#[default]
Unknown,
}
macro_rules! define_keys {
( $( $ident:ident => $name:expr ),* $(,)? ) => {
impl KeyCode {
#[must_use]
pub const fn to_string(&self) -> &'static str {
match self {
$( Self::$ident => $name ),*
}
}
#[must_use]
pub fn str_to_keycode(string: &str) -> Self {
match string {
$( $name => Self::$ident ),*,
_=>Self::Unknown
}
}
#[must_use]
#[cfg(feature = "std")]
pub fn to_vec(&self) -> Vec<Self> {
Vec::from([*self])
}
pub const AVAILABLE_KEY_NAMES: &[&str] = &[
$( $name ),*
];
pub const AVAILABLE_KEYS: &[KeyCode] =&[
$( KeyCode::$ident ),*];
#[must_use] pub const fn get_available_key_names() -> &'static [&'static str] {
Self::AVAILABLE_KEY_NAMES
}
#[must_use] pub const fn get_available_keys() -> &'static [KeyCode] {
Self::AVAILABLE_KEYS
}
}
#[cfg(feature = "std")]
impl StringToKeyCodes for String {
fn to_keycodes(&self) -> Vec<KeyCode> {
let mut list = Vec::new();
for i in self.chars() {
list.push(i.to_keycode())
}
list
}
fn to_keycode(&self)->KeyCode{
KeyCode::str_to_keycode(self)
}
}#[cfg(feature = "std")]
impl StringToKeyCodes for char {
fn to_keycodes(&self) -> Vec<KeyCode> {
Vec::from([self.to_keycode()])
}
fn to_keycode(&self)->KeyCode{
KeyCode::str_to_keycode(&self.to_string())
}
}
};
}
#[cfg(feature = "std")]
pub const trait StringToKeyCodes {
fn to_keycodes(&self) -> Vec<KeyCode>;
fn to_keycode(&self) -> KeyCode;
}
impl KeyCode {
#[must_use]
#[allow(clippy::too_many_lines)]
pub const fn to_user_friendly_string(&self) -> Option<&'static str> {
match self {
Self::A => Some("A"),
Self::B => Some("B"),
Self::C => Some("C"),
Self::D => Some("D"),
Self::E => Some("E"),
Self::F => Some("F"),
Self::G => Some("G"),
Self::H => Some("H"),
Self::I => Some("I"),
Self::J => Some("J"),
Self::K => Some("K"),
Self::L => Some("L"),
Self::M => Some("M"),
Self::N => Some("N"),
Self::O => Some("O"),
Self::P => Some("P"),
Self::Q => Some("Q"),
Self::R => Some("R"),
Self::S => Some("S"),
Self::T => Some("T"),
Self::U => Some("U"),
Self::V => Some("V"),
Self::W => Some("W"),
Self::X => Some("X"),
Self::Y => Some("Y"),
Self::Z => Some("Z"),
Self::Num0 | Self::KeyPad0 => Some("0"),
Self::Num1 | Self::KeyPad1 => Some("1"),
Self::Num2 | Self::KeyPad2 => Some("2"),
Self::Num3 | Self::KeyPad3 => Some("3"),
Self::Num4 | Self::KeyPad4 => Some("4"),
Self::Num5 | Self::KeyPad5 => Some("5"),
Self::Num6 | Self::KeyPad6 => Some("6"),
Self::Num7 | Self::KeyPad7 => Some("7"),
Self::Num8 | Self::KeyPad8 => Some("8"),
Self::Num9 | Self::KeyPad9 => Some("9"),
Self::F1
| Self::F2
| Self::F3
| Self::F4
| Self::F5
| Self::F6
| Self::F7
| Self::F8
| Self::F9
| Self::F10
| Self::F11
| Self::F12
| Self::F13
| Self::F14
| Self::F15
| Self::F16
| Self::F17
| Self::F18
| Self::F19
| Self::F20
| Self::F21
| Self::F22
| Self::F23
| Self::F24
| Self::F25
| Self::LeftShift
| Self::RightShift
| Self::LeftControl
| Self::RightControl
| Self::LeftAlt
| Self::RightAlt
| Self::LeftSuper
| Self::RightSuper
| Self::Escape
| Self::Backspace
| Self::UpArrow
| Self::DownArrow
| Self::LeftArrow
| Self::RightArrow
| Self::Insert
| Self::Delete
| Self::Home
| Self::End
| Self::PageUp
| Self::PageDown
| Self::CapsLock
| Self::NumLock
| Self::ScrollLock
| Self::MediaPlayPause
| Self::MediaStop
| Self::MediaNext
| Self::MediaPrev
| Self::VolumeUp
| Self::VolumeDown
| Self::Mute
| Self::BrowserBack
| Self::BrowserForward
| Self::BrowserRefresh
| Self::BrowserHome
| Self::LaunchMail
| Self::LaunchApp1
| Self::LaunchApp2
| Self::Menu
| Self::PrintScreen
| Self::Pause
| Self::Application
| Self::World1
| Self::World2
| Self::AnyAlt
| Self::AnySuper
| Self::AnyControl
| Self::AnyShift
| Self::Unknown
| Self::Enter
| Self::KeyPadEnter
| Self::BackTab
| Self::Tab
| Self::LeftHyper
| Self::RightHyper
| Self::AltControl
| Self::MediaPlay
| Self::MediaPause
| Self::MediaReverse
| Self::MediaFastForward
| Self::MediaRecord
| Self::SpecialControl => None,
Self::Space => Some(" "),
Self::Comma => Some(","),
Self::Period | Self::KeyPadDecimal => Some("."),
Self::Minus | Self::KeyPadSubtract => Some("-"),
Self::Equal | Self::KeyPadEqual => Some("="),
Self::LeftBracket => Some("["),
Self::RightBracket => Some("]"),
Self::Backslash => Some("\\"),
Self::Semicolon => Some(";"),
Self::Quote => Some("\""),
Self::Tilde => Some("~"),
Self::Slash | Self::KeyPadDivide => Some("/"),
Self::Grave => Some("`"),
Self::Apostrophe => Some("'"),
Self::KeyPadMultiply => Some("*"),
Self::KeyPadAdd => Some("+"),
Self::AUmlautÄ => Some("Ä"),
Self::UUmlautÜ => Some("Ü"),
Self::OUmlautÖ => Some("Ö"),
Self::SS => Some("ß"),
Self::ACircumflex => Some("Â"),
Self::UAcuteÚ => Some("Ú"),
Self::OCircumflexÔ => Some("Ô"),
Self::ICircumflexÎ => Some("Î"),
Self::ECircumflexÊ => Some("Ê"),
Self::EthÐ => Some("Ð"),
Self::OELigatureŒ => Some("Œ"),
Self::AAcuteÁ => Some("Á"),
Self::YAcuteÝ => Some("Ý"),
Self::IUmlautÏ => Some("Ï"),
Self::NTildeÑ => Some("Ñ"),
Self::OGraveÒ => Some("Ò"),
Self::UGraveÙ => Some("Ù"),
Self::ARingÅ => Some("Å"),
Self::AELigatureÆ => Some("Æ"),
Self::OSlashØ => Some("Ø"),
Self::IGraveÌ => Some("Ì"),
Self::ThornÞ => Some("Þ"),
}
}
}
#[cfg(feature = "std")]
impl core::fmt::Display for KeyCode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let value = self.to_string();
write!(f, "{value}")
}
}
define_keys!(
A => "A",
B => "B",
C => "C",
D => "D",
E => "E",
F => "F",
G => "G",
H => "H",
I => "I",
J => "J",
K => "K",
L => "L",
M => "M",
N => "N",
O => "O",
P => "P",
Q => "Q",
R => "R",
S => "S",
T => "T",
U => "U",
V => "V",
W => "W",
X => "X",
Y => "Y",
Z => "Z",
Num0 => "0",
Num1 => "1",
Num2 => "2",
Num3 => "3",
Num4 => "4",
Num5 => "5",
Num6 => "6",
Num7 => "7",
Num8 => "8",
Num9 => "9",
KeyPad0 => "KeyPad 0",
KeyPad1 => "KeyPad 1",
KeyPad2 => "KeyPad 2",
KeyPad3 => "KeyPad 3",
KeyPad4 => "KeyPad 4",
KeyPad5 => "KeyPad 5",
KeyPad6 => "KeyPad 6",
KeyPad7 => "KeyPad 7",
KeyPad8 => "KeyPad 8",
KeyPad9 => "KeyPad 9",
F1 => "F1",
F2 => "F2",
F3 => "F3",
F4 => "F4",
F5 => "F5",
F6 => "F6",
F7 => "F7",
F8 => "F8",
F9 => "F9",
F10 => "F10",
F11 => "F11",
F12 => "F12",
F13 => "F13",
F14 => "F14",
F15 => "F15",
F16 => "F16",
F17 => "F17",
F18 => "F18",
F19 => "F19",
F20 => "F20",
F21 => "F21",
F22 => "F22",
F23 => "F23",
F24 => "F24",
LeftShift => "Left Shift",
RightShift => "Right Shift",
LeftControl => "Left Control",
RightControl => "Right Control",
LeftAlt => "Left Alt",
RightAlt => "Right Alt",
LeftSuper => "Left Super",
RightSuper => "Right Super",
LeftHyper=>"Hyper Left",
RightHyper=>"Hyper Right",
AltControl=>"Alt Control",
Space => "Space",
Enter => "Enter",
Escape => "Escape",
Backspace => "Backspace",
Tab => "Tab",
Comma => ",",
Period => ".",
Minus => "-",
Equal => "=",
LeftBracket => "[",
RightBracket => "]",
Backslash => "\\",
Semicolon => ";",
Quote => "\"",
Tilde => "~",
Slash => "/",
Grave => "`",
Apostrophe => "'",
UpArrow => "Up",
DownArrow => "Down",
LeftArrow => "Left",
RightArrow => "Right",
Insert => "Insert",
Delete => "Delete",
Home => "Home",
End => "End",
PageUp => "Page Up",
PageDown => "Page Down",
CapsLock => "Caps Lock",
NumLock => "Num Lock",
ScrollLock => "Scroll Lock",
KeyPadDivide => "KeyPad /",
KeyPadMultiply => "KeyPad *",
KeyPadSubtract => "KeyPad -",
KeyPadAdd => "KeyPad +",
KeyPadDecimal => "KeyPad .",
KeyPadEnter => "KeyPad Enter",
AUmlautÄ => "Ä",
UUmlautÜ => "Ü",
OUmlautÖ => "Ö",
SS => "ß",
ACircumflex => "Â",
UAcuteÚ => "Ú",
OCircumflexÔ => "Ô",
ICircumflexÎ => "Î",
ECircumflexÊ => "Ê",
EthÐ => "Ð",
OELigatureŒ => "Œ",
AAcuteÁ => "Á",
YAcuteÝ => "Ý",
IUmlautÏ => "Ï",
NTildeÑ => "Ñ",
OGraveÒ => "Ò",
UGraveÙ => "Ù",
ARingÅ => "Å",
AELigatureÆ => "Æ",
OSlashØ => "Ø",
IGraveÌ => "Ì",
ThornÞ => "Þ",
MediaPlayPause => "Media Play/Pause",
MediaStop => "Media Stop",
MediaNext => "Media Next",
MediaPrev => "Media Previous",
VolumeUp => "Volume Up",
VolumeDown => "Volume Down",
Mute => "Mute",
MediaPause=>"Media Pause",
MediaPlay=>"Media Play",
MediaReverse=>"Media Reverse",
MediaFastForward=>"Media Fast forward",
MediaRecord=>"Media Record",
BrowserBack => "Browser Back",
BrowserForward => "Browser Forward",
BrowserRefresh => "Browser Refresh",
BrowserHome => "Browser Home",
LaunchMail => "Launch Mail",
LaunchApp1 => "Launch App 1",
LaunchApp2 => "Launch App 2",
Menu => "Menu",
PrintScreen => "Print Screen",
Pause => "Pause",
Application => "Application",
AnyShift=>"Shift",
AnyControl=>"Control",
AnyAlt=>"Alt",
AnySuper=>"Super",
F25 => "F25",
KeyPadEqual => "KeyPad =",
World1 => "World 1",
World2 => "World 2",
BackTab=>"BackTab",
SpecialControl=>"Special Control",
Unknown => "Unknown",);
#[must_use]
#[cfg(feature = "std")]
pub fn keycodes_to_str(keycodes: &Vec<KeyCode>) -> (String, Vec<KeyCode>) {
let mut functions = Vec::new();
let mut output = String::new();
for key_code in keycodes {
let value = key_code.to_user_friendly_string();
if let Some(key) = value {
for l in key.chars() {
output.push(l);
}
} else {
functions.push(*key_code);
}
}
(output, functions)
}
impl KeyCode {
#[must_use]
pub const fn get_number<
T: crate::math::ConstOne
+ crate::math::ConstZero
+ crate::math::ConstNumbers128,
>(
&self,
) -> Option<T> {
Some(match self {
Self::Num0 => T::ZERO,
Self::Num1 => T::ONE,
Self::Num2 => T::CONST_2,
Self::Num3 => T::CONST_3,
Self::Num4 => T::CONST_4,
Self::Num5 => T::CONST_5,
Self::Num6 => T::CONST_6,
Self::Num7 => T::CONST_7,
Self::Num8 => T::CONST_8,
Self::Num9 => T::CONST_9,
_ => return None,
})
}
#[must_use]
pub const fn is_number(&self) -> bool {
self.get_number::<u8>().is_some()
}
}