use eframe::egui;
pub(super) fn terminal_bytes(
key: egui::Key,
modifiers: egui::Modifiers,
application_cursor: bool,
) -> Option<Vec<u8>> {
if modifiers.ctrl
&& let Some(character) = key.name().chars().next()
&& character.is_ascii_alphabetic()
&& key.name().len() == 1
{
return Some(vec![character.to_ascii_uppercase() as u8 - b'@']);
}
let bytes = match key {
egui::Key::Enter => b"\r".as_slice(),
egui::Key::Backspace => b"\x7f",
egui::Key::Tab if modifiers.shift => b"\x1b[Z",
egui::Key::Tab => b"\t",
egui::Key::Escape => b"\x1b",
egui::Key::ArrowUp if application_cursor => b"\x1bOA",
egui::Key::ArrowDown if application_cursor => b"\x1bOB",
egui::Key::ArrowRight if application_cursor => b"\x1bOC",
egui::Key::ArrowLeft if application_cursor => b"\x1bOD",
egui::Key::ArrowUp => b"\x1b[A",
egui::Key::ArrowDown => b"\x1b[B",
egui::Key::ArrowRight => b"\x1b[C",
egui::Key::ArrowLeft => b"\x1b[D",
egui::Key::Home => b"\x1b[H",
egui::Key::End => b"\x1b[F",
egui::Key::Insert => b"\x1b[2~",
egui::Key::Delete => b"\x1b[3~",
egui::Key::PageUp => b"\x1b[5~",
egui::Key::PageDown => b"\x1b[6~",
egui::Key::F1 => b"\x1bOP",
egui::Key::F2 => b"\x1bOQ",
egui::Key::F3 => b"\x1bOR",
egui::Key::F4 => b"\x1bOS",
egui::Key::F5 => b"\x1b[15~",
egui::Key::F6 => b"\x1b[17~",
egui::Key::F7 => b"\x1b[18~",
egui::Key::F8 => b"\x1b[19~",
egui::Key::F9 => b"\x1b[20~",
egui::Key::F10 => b"\x1b[21~",
egui::Key::F11 => b"\x1b[23~",
egui::Key::F12 => b"\x1b[24~",
_ => return None,
};
let mut result = Vec::with_capacity(bytes.len() + usize::from(modifiers.alt));
if modifiers.alt {
result.push(0x1b);
}
result.extend_from_slice(bytes);
Some(result)
}
pub(super) fn matches(accelerator: &str, key: egui::Key, modifiers: egui::Modifiers) -> bool {
let alt = accelerator.contains("<Alt>");
let control = accelerator.contains("<Control>");
let shift = accelerator.contains("<Shift>");
let super_key = accelerator.contains("<Super>") || accelerator.contains("<Meta>");
if modifiers.alt != alt
|| modifiers.ctrl != control
|| modifiers.shift != shift
|| modifiers.mac_cmd != super_key
{
return false;
}
let expected = accelerator.rsplit('>').next().unwrap_or(accelerator);
let expected = if expected.eq_ignore_ascii_case("Return") {
"Enter"
} else {
expected
};
key.name().eq_ignore_ascii_case(expected)
}
pub(super) fn is_modifier(key: egui::Key) -> bool {
matches!(
key,
egui::Key::ShiftLeft
| egui::Key::ShiftRight
| egui::Key::ControlLeft
| egui::Key::ControlRight
| egui::Key::AltLeft
| egui::Key::AltRight
| egui::Key::SuperLeft
| egui::Key::SuperRight
)
}
pub(super) fn accelerator(key: egui::Key, modifiers: egui::Modifiers) -> String {
let mut accelerator = String::new();
if modifiers.ctrl {
accelerator.push_str("<Control>");
}
if modifiers.alt {
accelerator.push_str("<Alt>");
}
if modifiers.shift {
accelerator.push_str("<Shift>");
}
if modifiers.mac_cmd || modifiers.command && !modifiers.ctrl {
accelerator.push_str("<Super>");
}
let name = if key == egui::Key::Enter {
"Return"
} else {
key.name()
};
accelerator.push_str(name);
accelerator
}