Translate Alt/Shift/Ctrl-modified keys and F-keys to terminal escape sequences

This commit is contained in:
Andrew Hamilton 2026-08-06 08:44:47 +10:00
parent 17c54d8921
commit fd89732a72

View file

@ -79,7 +79,7 @@ pub fn start(
w.set_size_polling(true);
w.set_close_polling(true);
w.set_key_polling(true);
w.set_char_polling(true);
w.set_char_mods_polling(true);
w.set_focus_polling(true);
w.focus();
let focus_deadline = Instant::now() + Duration::from_secs(2);
@ -306,9 +306,12 @@ pub fn start(
});
}
}
glfw::WindowEvent::Char(codepoint) => {
glfw::WindowEvent::CharModifiers(codepoint, mods) => {
if let Some(ref cb) = on_key {
let s: String = codepoint.into();
let mut s: String = codepoint.into();
if mods.contains(glfw::Modifiers::Alt) && !s.is_empty() {
s.insert(0, '\x1b');
}
Python::with_gil(|py| {
let _ = cb.call1(py, (s,));
});
@ -410,26 +413,74 @@ pub fn start(
Some(String::from('\x16'))
}
} else if mods.contains(glfw::Modifiers::Control) {
let code = key as i32;
if (65..=90).contains(&code) {
Some(String::from((code - 64) as u8 as char))
} else {
None
match key {
glfw::Key::Up => Some("\x1b[1;5A".into()),
glfw::Key::Down => Some("\x1b[1;5B".into()),
glfw::Key::Left => Some("\x1b[1;5D".into()),
glfw::Key::Right => Some("\x1b[1;5C".into()),
_ => {
let code = key as i32;
if (65..=90).contains(&code) {
Some(String::from((code - 64) as u8 as char))
} else {
None
}
}
}
} else {
let mod_num = if mods.contains(glfw::Modifiers::Shift)
&& mods.contains(glfw::Modifiers::Alt)
{ 4 }
else if mods.contains(glfw::Modifiers::Alt) { 3 }
else if mods.contains(glfw::Modifiers::Shift) { 2 }
else { 1 };
match key {
glfw::Key::Up => if mod_num > 1 {
Some(format!("\x1b[1;{}A", mod_num))
} else { Some("\x1b[A".into()) },
glfw::Key::Down => if mod_num > 1 {
Some(format!("\x1b[1;{}B", mod_num))
} else { Some("\x1b[B".into()) },
glfw::Key::Left => if mod_num > 1 {
Some(format!("\x1b[1;{}D", mod_num))
} else { Some("\x1b[D".into()) },
glfw::Key::Right => if mod_num > 1 {
Some(format!("\x1b[1;{}C", mod_num))
} else { Some("\x1b[C".into()) },
glfw::Key::Home => if mod_num > 1 {
Some(format!("\x1b[1;{}H", mod_num))
} else { Some("\x1b[H".into()) },
glfw::Key::End => if mod_num > 1 {
Some(format!("\x1b[1;{}F", mod_num))
} else { Some("\x1b[F".into()) },
glfw::Key::PageUp => if mod_num > 1 {
Some(format!("\x1b[5;{}~", mod_num))
} else { Some("\x1b[5~".into()) },
glfw::Key::PageDown => if mod_num > 1 {
Some(format!("\x1b[6;{}~", mod_num))
} else { Some("\x1b[6~".into()) },
glfw::Key::Tab => if mods.contains(glfw::Modifiers::Shift) {
Some("\x1b[Z".into())
} else { Some("\t".into()) },
glfw::Key::Backspace => if mods.contains(glfw::Modifiers::Alt) {
Some("\x1b\x7f".into())
} else { Some("\x7f".into()) },
glfw::Key::Insert => Some("\x1b[2~".into()),
glfw::Key::Delete => Some("\x1b[3~".into()),
glfw::Key::F1 => Some("\x1bOP".into()),
glfw::Key::F2 => Some("\x1bOQ".into()),
glfw::Key::F3 => Some("\x1bOR".into()),
glfw::Key::F4 => Some("\x1bOS".into()),
glfw::Key::F5 => Some("\x1b[15~".into()),
glfw::Key::F6 => Some("\x1b[17~".into()),
glfw::Key::F7 => Some("\x1b[18~".into()),
glfw::Key::F8 => Some("\x1b[19~".into()),
glfw::Key::F9 => Some("\x1b[20~".into()),
glfw::Key::F10 => Some("\x1b[21~".into()),
glfw::Key::F11 => Some("\x1b[23~".into()),
glfw::Key::F12 => Some("\x1b[24~".into()),
glfw::Key::Enter => Some("\n".into()),
glfw::Key::Escape => Some("\x1b".into()),
glfw::Key::Backspace => Some("\x7f".into()),
glfw::Key::Tab => Some("\t".into()),
glfw::Key::Up => Some("\x1b[A".into()),
glfw::Key::Down => Some("\x1b[B".into()),
glfw::Key::Left => Some("\x1b[D".into()),
glfw::Key::Right => Some("\x1b[C".into()),
glfw::Key::Home => Some("\x1b[H".into()),
glfw::Key::End => Some("\x1b[F".into()),
glfw::Key::PageUp => Some("\x1b[5~".into()),
glfw::Key::PageDown => Some("\x1b[6~".into()),
_ => None,
}
};