Upstream zed-industries/zed state of the touched files before 41f88af76a
This commit is contained in:
1 parent
ee1e5ee696
commit
08029c4aa7
1 file changed
+442
@@ -0,0 +1,442 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
/// The mappings defined in this file where created from reading the alacritty source
|
||||||
|
use gpui::Keystroke;
|
||||||
|
|
||||||
|
use crate::Modes;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
enum TerminalModifiers {
|
||||||
|
None,
|
||||||
|
Alt,
|
||||||
|
Ctrl,
|
||||||
|
Shift,
|
||||||
|
CtrlShift,
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerminalModifiers {
|
||||||
|
fn new(ks: &Keystroke) -> Self {
|
||||||
|
match (
|
||||||
|
ks.modifiers.alt,
|
||||||
|
ks.modifiers.control,
|
||||||
|
ks.modifiers.shift,
|
||||||
|
ks.modifiers.platform,
|
||||||
|
) {
|
||||||
|
(false, false, false, false) => TerminalModifiers::None,
|
||||||
|
(true, false, false, false) => TerminalModifiers::Alt,
|
||||||
|
(false, true, false, false) => TerminalModifiers::Ctrl,
|
||||||
|
(false, false, true, false) => TerminalModifiers::Shift,
|
||||||
|
(false, true, true, false) => TerminalModifiers::CtrlShift,
|
||||||
|
_ => TerminalModifiers::Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn any(&self) -> bool {
|
||||||
|
match &self {
|
||||||
|
TerminalModifiers::None => false,
|
||||||
|
TerminalModifiers::Alt => true,
|
||||||
|
TerminalModifiers::Ctrl => true,
|
||||||
|
TerminalModifiers::Shift => true,
|
||||||
|
TerminalModifiers::CtrlShift => true,
|
||||||
|
TerminalModifiers::Other => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn to_esc_str(
|
||||||
|
keystroke: &Keystroke,
|
||||||
|
mode: Modes,
|
||||||
|
option_as_meta: bool,
|
||||||
|
) -> Option<Cow<'static, str>> {
|
||||||
|
let modifiers = TerminalModifiers::new(keystroke);
|
||||||
|
|
||||||
|
// Manual Bindings including modifiers
|
||||||
|
let manual_esc_str: Option<&'static str> = match (keystroke.key.as_ref(), &modifiers) {
|
||||||
|
//Basic special keys
|
||||||
|
("tab", TerminalModifiers::None) => Some("\x09"),
|
||||||
|
("escape", TerminalModifiers::None) => Some("\x1b"),
|
||||||
|
("enter", TerminalModifiers::None) => Some("\x0d"),
|
||||||
|
("enter", TerminalModifiers::Shift) => Some("\x0a"),
|
||||||
|
("enter", TerminalModifiers::Alt) => Some("\x1b\x0d"),
|
||||||
|
("backspace", TerminalModifiers::None) => Some("\x7f"),
|
||||||
|
//Interesting escape codes
|
||||||
|
("tab", TerminalModifiers::Shift) => Some("\x1b[Z"),
|
||||||
|
("backspace", TerminalModifiers::Ctrl) => Some("\x08"),
|
||||||
|
("backspace", TerminalModifiers::Alt) => Some("\x1b\x7f"),
|
||||||
|
("backspace", TerminalModifiers::Shift) => Some("\x7f"),
|
||||||
|
("space", TerminalModifiers::Ctrl) => Some("\x00"),
|
||||||
|
("home", TerminalModifiers::None) if mode.contains(Modes::APP_CURSOR) => Some("\x1bOH"),
|
||||||
|
("home", TerminalModifiers::None) if !mode.contains(Modes::APP_CURSOR) => Some("\x1b[H"),
|
||||||
|
("end", TerminalModifiers::None) if mode.contains(Modes::APP_CURSOR) => Some("\x1bOF"),
|
||||||
|
("end", TerminalModifiers::None) if !mode.contains(Modes::APP_CURSOR) => Some("\x1b[F"),
|
||||||
|
("up", TerminalModifiers::None) if mode.contains(Modes::APP_CURSOR) => Some("\x1bOA"),
|
||||||
|
("up", TerminalModifiers::None) if !mode.contains(Modes::APP_CURSOR) => Some("\x1b[A"),
|
||||||
|
("down", TerminalModifiers::None) if mode.contains(Modes::APP_CURSOR) => Some("\x1bOB"),
|
||||||
|
("down", TerminalModifiers::None) if !mode.contains(Modes::APP_CURSOR) => Some("\x1b[B"),
|
||||||
|
("right", TerminalModifiers::None) if mode.contains(Modes::APP_CURSOR) => Some("\x1bOC"),
|
||||||
|
("right", TerminalModifiers::None) if !mode.contains(Modes::APP_CURSOR) => Some("\x1b[C"),
|
||||||
|
("left", TerminalModifiers::None) if mode.contains(Modes::APP_CURSOR) => Some("\x1bOD"),
|
||||||
|
("left", TerminalModifiers::None) if !mode.contains(Modes::APP_CURSOR) => Some("\x1b[D"),
|
||||||
|
("back", TerminalModifiers::None) => Some("\x7f"),
|
||||||
|
("insert", TerminalModifiers::None) => Some("\x1b[2~"),
|
||||||
|
("delete", TerminalModifiers::None) => Some("\x1b[3~"),
|
||||||
|
("pageup", TerminalModifiers::None) => Some("\x1b[5~"),
|
||||||
|
("pagedown", TerminalModifiers::None) => Some("\x1b[6~"),
|
||||||
|
("f1", TerminalModifiers::None) => Some("\x1bOP"),
|
||||||
|
("f2", TerminalModifiers::None) => Some("\x1bOQ"),
|
||||||
|
("f3", TerminalModifiers::None) => Some("\x1bOR"),
|
||||||
|
("f4", TerminalModifiers::None) => Some("\x1bOS"),
|
||||||
|
("f5", TerminalModifiers::None) => Some("\x1b[15~"),
|
||||||
|
("f6", TerminalModifiers::None) => Some("\x1b[17~"),
|
||||||
|
("f7", TerminalModifiers::None) => Some("\x1b[18~"),
|
||||||
|
("f8", TerminalModifiers::None) => Some("\x1b[19~"),
|
||||||
|
("f9", TerminalModifiers::None) => Some("\x1b[20~"),
|
||||||
|
("f10", TerminalModifiers::None) => Some("\x1b[21~"),
|
||||||
|
("f11", TerminalModifiers::None) => Some("\x1b[23~"),
|
||||||
|
("f12", TerminalModifiers::None) => Some("\x1b[24~"),
|
||||||
|
("f13", TerminalModifiers::None) => Some("\x1b[25~"),
|
||||||
|
("f14", TerminalModifiers::None) => Some("\x1b[26~"),
|
||||||
|
("f15", TerminalModifiers::None) => Some("\x1b[28~"),
|
||||||
|
("f16", TerminalModifiers::None) => Some("\x1b[29~"),
|
||||||
|
("f17", TerminalModifiers::None) => Some("\x1b[31~"),
|
||||||
|
("f18", TerminalModifiers::None) => Some("\x1b[32~"),
|
||||||
|
("f19", TerminalModifiers::None) => Some("\x1b[33~"),
|
||||||
|
("f20", TerminalModifiers::None) => Some("\x1b[34~"),
|
||||||
|
// NumpadEnter, Action::Esc("\n".into());
|
||||||
|
//Mappings for caret notation keys
|
||||||
|
("a", TerminalModifiers::Ctrl) => Some("\x01"), //1
|
||||||
|
("A", TerminalModifiers::CtrlShift) => Some("\x01"), //1
|
||||||
|
("b", TerminalModifiers::Ctrl) => Some("\x02"), //2
|
||||||
|
("B", TerminalModifiers::CtrlShift) => Some("\x02"), //2
|
||||||
|
("c", TerminalModifiers::Ctrl) => Some("\x03"), //3
|
||||||
|
("C", TerminalModifiers::CtrlShift) => Some("\x03"), //3
|
||||||
|
("d", TerminalModifiers::Ctrl) => Some("\x04"), //4
|
||||||
|
("D", TerminalModifiers::CtrlShift) => Some("\x04"), //4
|
||||||
|
("e", TerminalModifiers::Ctrl) => Some("\x05"), //5
|
||||||
|
("E", TerminalModifiers::CtrlShift) => Some("\x05"), //5
|
||||||
|
("f", TerminalModifiers::Ctrl) => Some("\x06"), //6
|
||||||
|
("F", TerminalModifiers::CtrlShift) => Some("\x06"), //6
|
||||||
|
("g", TerminalModifiers::Ctrl) => Some("\x07"), //7
|
||||||
|
("G", TerminalModifiers::CtrlShift) => Some("\x07"), //7
|
||||||
|
("h", TerminalModifiers::Ctrl) => Some("\x08"), //8
|
||||||
|
("H", TerminalModifiers::CtrlShift) => Some("\x08"), //8
|
||||||
|
("i", TerminalModifiers::Ctrl) => Some("\x09"), //9
|
||||||
|
("I", TerminalModifiers::CtrlShift) => Some("\x09"), //9
|
||||||
|
("j", TerminalModifiers::Ctrl) => Some("\x0a"), //10
|
||||||
|
("J", TerminalModifiers::CtrlShift) => Some("\x0a"), //10
|
||||||
|
("k", TerminalModifiers::Ctrl) => Some("\x0b"), //11
|
||||||
|
("K", TerminalModifiers::CtrlShift) => Some("\x0b"), //11
|
||||||
|
("l", TerminalModifiers::Ctrl) => Some("\x0c"), //12
|
||||||
|
("L", TerminalModifiers::CtrlShift) => Some("\x0c"), //12
|
||||||
|
("m", TerminalModifiers::Ctrl) => Some("\x0d"), //13
|
||||||
|
("M", TerminalModifiers::CtrlShift) => Some("\x0d"), //13
|
||||||
|
("n", TerminalModifiers::Ctrl) => Some("\x0e"), //14
|
||||||
|
("N", TerminalModifiers::CtrlShift) => Some("\x0e"), //14
|
||||||
|
("o", TerminalModifiers::Ctrl) => Some("\x0f"), //15
|
||||||
|
("O", TerminalModifiers::CtrlShift) => Some("\x0f"), //15
|
||||||
|
("p", TerminalModifiers::Ctrl) => Some("\x10"), //16
|
||||||
|
("P", TerminalModifiers::CtrlShift) => Some("\x10"), //16
|
||||||
|
("q", TerminalModifiers::Ctrl) => Some("\x11"), //17
|
||||||
|
("Q", TerminalModifiers::CtrlShift) => Some("\x11"), //17
|
||||||
|
("r", TerminalModifiers::Ctrl) => Some("\x12"), //18
|
||||||
|
("R", TerminalModifiers::CtrlShift) => Some("\x12"), //18
|
||||||
|
("s", TerminalModifiers::Ctrl) => Some("\x13"), //19
|
||||||
|
("S", TerminalModifiers::CtrlShift) => Some("\x13"), //19
|
||||||
|
("t", TerminalModifiers::Ctrl) => Some("\x14"), //20
|
||||||
|
("T", TerminalModifiers::CtrlShift) => Some("\x14"), //20
|
||||||
|
("u", TerminalModifiers::Ctrl) => Some("\x15"), //21
|
||||||
|
("U", TerminalModifiers::CtrlShift) => Some("\x15"), //21
|
||||||
|
("v", TerminalModifiers::Ctrl) => Some("\x16"), //22
|
||||||
|
("V", TerminalModifiers::CtrlShift) => Some("\x16"), //22
|
||||||
|
("w", TerminalModifiers::Ctrl) => Some("\x17"), //23
|
||||||
|
("W", TerminalModifiers::CtrlShift) => Some("\x17"), //23
|
||||||
|
("x", TerminalModifiers::Ctrl) => Some("\x18"), //24
|
||||||
|
("X", TerminalModifiers::CtrlShift) => Some("\x18"), //24
|
||||||
|
("y", TerminalModifiers::Ctrl) => Some("\x19"), //25
|
||||||
|
("Y", TerminalModifiers::CtrlShift) => Some("\x19"), //25
|
||||||
|
("z", TerminalModifiers::Ctrl) => Some("\x1a"), //26
|
||||||
|
("Z", TerminalModifiers::CtrlShift) => Some("\x1a"), //26
|
||||||
|
("@", TerminalModifiers::Ctrl) => Some("\x00"), //0
|
||||||
|
("[", TerminalModifiers::Ctrl) => Some("\x1b"), //27
|
||||||
|
("\\", TerminalModifiers::Ctrl) => Some("\x1c"), //28
|
||||||
|
("]", TerminalModifiers::Ctrl) => Some("\x1d"), //29
|
||||||
|
("^", TerminalModifiers::Ctrl) => Some("\x1e"), //30
|
||||||
|
("_", TerminalModifiers::Ctrl) => Some("\x1f"), //31
|
||||||
|
("?", TerminalModifiers::Ctrl) => Some("\x7f"), //127
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(esc_str) = manual_esc_str {
|
||||||
|
return Some(Cow::Borrowed(esc_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automated bindings applying modifiers
|
||||||
|
if modifiers.any() {
|
||||||
|
let modifier_code = modifier_code(keystroke);
|
||||||
|
let modified_esc_str = match keystroke.key.as_ref() {
|
||||||
|
"up" => Some(format!("\x1b[1;{}A", modifier_code)),
|
||||||
|
"down" => Some(format!("\x1b[1;{}B", modifier_code)),
|
||||||
|
"right" => Some(format!("\x1b[1;{}C", modifier_code)),
|
||||||
|
"left" => Some(format!("\x1b[1;{}D", modifier_code)),
|
||||||
|
"f1" => Some(format!("\x1b[1;{}P", modifier_code)),
|
||||||
|
"f2" => Some(format!("\x1b[1;{}Q", modifier_code)),
|
||||||
|
"f3" => Some(format!("\x1b[1;{}R", modifier_code)),
|
||||||
|
"f4" => Some(format!("\x1b[1;{}S", modifier_code)),
|
||||||
|
"f5" => Some(format!("\x1b[15;{}~", modifier_code)),
|
||||||
|
"f6" => Some(format!("\x1b[17;{}~", modifier_code)),
|
||||||
|
"f7" => Some(format!("\x1b[18;{}~", modifier_code)),
|
||||||
|
"f8" => Some(format!("\x1b[19;{}~", modifier_code)),
|
||||||
|
"f9" => Some(format!("\x1b[20;{}~", modifier_code)),
|
||||||
|
"f10" => Some(format!("\x1b[21;{}~", modifier_code)),
|
||||||
|
"f11" => Some(format!("\x1b[23;{}~", modifier_code)),
|
||||||
|
"f12" => Some(format!("\x1b[24;{}~", modifier_code)),
|
||||||
|
"f13" => Some(format!("\x1b[25;{}~", modifier_code)),
|
||||||
|
"f14" => Some(format!("\x1b[26;{}~", modifier_code)),
|
||||||
|
"f15" => Some(format!("\x1b[28;{}~", modifier_code)),
|
||||||
|
"f16" => Some(format!("\x1b[29;{}~", modifier_code)),
|
||||||
|
"f17" => Some(format!("\x1b[31;{}~", modifier_code)),
|
||||||
|
"f18" => Some(format!("\x1b[32;{}~", modifier_code)),
|
||||||
|
"f19" => Some(format!("\x1b[33;{}~", modifier_code)),
|
||||||
|
"f20" => Some(format!("\x1b[34;{}~", modifier_code)),
|
||||||
|
"insert" => Some(format!("\x1b[2;{}~", modifier_code)),
|
||||||
|
"pageup" => Some(format!("\x1b[5;{}~", modifier_code)),
|
||||||
|
"pagedown" => Some(format!("\x1b[6;{}~", modifier_code)),
|
||||||
|
"end" => Some(format!("\x1b[1;{}F", modifier_code)),
|
||||||
|
"home" => Some(format!("\x1b[1;{}H", modifier_code)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(esc_str) = modified_esc_str {
|
||||||
|
return Some(Cow::Owned(esc_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handling alt keys. These work for single ASCII characters.
|
||||||
|
if (!cfg!(target_os = "macos") || option_as_meta)
|
||||||
|
&& keystroke.modifiers.alt
|
||||||
|
&& keystroke.key.is_ascii()
|
||||||
|
&& keystroke.key.len() == 1
|
||||||
|
{
|
||||||
|
let key = keystroke.key.chars().next().unwrap();
|
||||||
|
|
||||||
|
if modifiers == TerminalModifiers::Alt {
|
||||||
|
return Some(Cow::Owned(format!("\x1b{key}")));
|
||||||
|
} else if keystroke.modifiers.shift {
|
||||||
|
return Some(Cow::Owned(format!("\x1b{}", key.to_ascii_uppercase())));
|
||||||
|
} else if keystroke.modifiers.control && key.is_ascii_lowercase() {
|
||||||
|
return Some(Cow::Owned(format!(
|
||||||
|
"\x1b{}",
|
||||||
|
(key as u8 - b'a' + 1) as char
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Code Modifiers
|
||||||
|
/// ---------+---------------------------
|
||||||
|
/// 2 | Shift
|
||||||
|
/// 3 | Alt
|
||||||
|
/// 4 | Shift + Alt
|
||||||
|
/// 5 | Control
|
||||||
|
/// 6 | Shift + Control
|
||||||
|
/// 7 | Alt + Control
|
||||||
|
/// 8 | Shift + Alt + Control
|
||||||
|
/// ---------+---------------------------
|
||||||
|
/// from: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
|
||||||
|
fn modifier_code(keystroke: &Keystroke) -> u32 {
|
||||||
|
let mut modifier_code = 0;
|
||||||
|
if keystroke.modifiers.shift {
|
||||||
|
modifier_code |= 1;
|
||||||
|
}
|
||||||
|
if keystroke.modifiers.alt {
|
||||||
|
modifier_code |= 1 << 1;
|
||||||
|
}
|
||||||
|
if keystroke.modifiers.control {
|
||||||
|
modifier_code |= 1 << 2;
|
||||||
|
}
|
||||||
|
modifier_code + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use gpui::Modifiers;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_plain_inputs() {
|
||||||
|
let ks = Keystroke {
|
||||||
|
modifiers: Modifiers {
|
||||||
|
control: false,
|
||||||
|
alt: false,
|
||||||
|
shift: false,
|
||||||
|
platform: false,
|
||||||
|
function: false,
|
||||||
|
},
|
||||||
|
key: "🖖🏻".to_string(), //2 char string
|
||||||
|
key_char: None,
|
||||||
|
};
|
||||||
|
assert_eq!(to_esc_str(&ks, Modes::NONE, false), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_application_mode() {
|
||||||
|
let app_cursor = Modes::APP_CURSOR;
|
||||||
|
let none = Modes::NONE;
|
||||||
|
|
||||||
|
let up = Keystroke::parse("up").unwrap();
|
||||||
|
let down = Keystroke::parse("down").unwrap();
|
||||||
|
let left = Keystroke::parse("left").unwrap();
|
||||||
|
let right = Keystroke::parse("right").unwrap();
|
||||||
|
|
||||||
|
assert_eq!(to_esc_str(&up, none, false), Some("\x1b[A".into()));
|
||||||
|
assert_eq!(to_esc_str(&down, none, false), Some("\x1b[B".into()));
|
||||||
|
assert_eq!(to_esc_str(&right, none, false), Some("\x1b[C".into()));
|
||||||
|
assert_eq!(to_esc_str(&left, none, false), Some("\x1b[D".into()));
|
||||||
|
|
||||||
|
assert_eq!(to_esc_str(&up, app_cursor, false), Some("\x1bOA".into()));
|
||||||
|
assert_eq!(to_esc_str(&down, app_cursor, false), Some("\x1bOB".into()));
|
||||||
|
assert_eq!(to_esc_str(&right, app_cursor, false), Some("\x1bOC".into()));
|
||||||
|
assert_eq!(to_esc_str(&left, app_cursor, false), Some("\x1bOD".into()));
|
||||||
|
|
||||||
|
let home = Keystroke::parse("home").unwrap();
|
||||||
|
let end = Keystroke::parse("end").unwrap();
|
||||||
|
assert_eq!(to_esc_str(&home, none, false), Some("\x1b[H".into()));
|
||||||
|
assert_eq!(to_esc_str(&end, none, false), Some("\x1b[F".into()));
|
||||||
|
assert_eq!(to_esc_str(&home, app_cursor, false), Some("\x1bOH".into()));
|
||||||
|
assert_eq!(to_esc_str(&end, app_cursor, false), Some("\x1bOF".into()));
|
||||||
|
|
||||||
|
let shift_up = Keystroke::parse("shift-up").unwrap();
|
||||||
|
let shift_down = Keystroke::parse("shift-down").unwrap();
|
||||||
|
let shift_home = Keystroke::parse("shift-home").unwrap();
|
||||||
|
let shift_end = Keystroke::parse("shift-end").unwrap();
|
||||||
|
assert_eq!(to_esc_str(&shift_up, none, false), Some("\x1b[1;2A".into()));
|
||||||
|
assert_eq!(
|
||||||
|
to_esc_str(&shift_down, none, false),
|
||||||
|
Some("\x1b[1;2B".into())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
to_esc_str(&shift_home, none, false),
|
||||||
|
Some("\x1b[1;2H".into())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
to_esc_str(&shift_end, none, false),
|
||||||
|
Some("\x1b[1;2F".into())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ctrl_codes() {
|
||||||
|
let letters_lower = 'a'..='z';
|
||||||
|
let letters_upper = 'A'..='Z';
|
||||||
|
let mode = Modes::APP_CURSOR;
|
||||||
|
|
||||||
|
for (lower, upper) in letters_lower.zip(letters_upper) {
|
||||||
|
assert_eq!(
|
||||||
|
to_esc_str(
|
||||||
|
&Keystroke::parse(&format!("ctrl-shift-{}", lower)).unwrap(),
|
||||||
|
mode,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
to_esc_str(
|
||||||
|
&Keystroke::parse(&format!("ctrl-{}", upper)).unwrap(),
|
||||||
|
mode,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
"On letter: {}/{}",
|
||||||
|
lower,
|
||||||
|
upper
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alt_is_meta() {
|
||||||
|
let ascii_printable = ' '..='~';
|
||||||
|
for character in ascii_printable {
|
||||||
|
assert_eq!(
|
||||||
|
to_esc_str(
|
||||||
|
&Keystroke::parse(&format!("alt-{}", character)).unwrap(),
|
||||||
|
Modes::NONE,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
format!("\x1b{}", character)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let gpui_keys = [
|
||||||
|
"up", "down", "right", "left", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
|
||||||
|
"f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "insert",
|
||||||
|
"pageup", "pagedown", "end", "home",
|
||||||
|
];
|
||||||
|
|
||||||
|
for key in gpui_keys {
|
||||||
|
assert_ne!(
|
||||||
|
to_esc_str(
|
||||||
|
&Keystroke::parse(&format!("alt-{}", key)).unwrap(),
|
||||||
|
Modes::NONE,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
format!("\x1b{}", key)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ctrl_alt_codes() {
|
||||||
|
let letters_lower = 'a'..='z';
|
||||||
|
let esc_codes = '\x01'..='\x1a';
|
||||||
|
for (character, esc_code) in letters_lower.zip(esc_codes) {
|
||||||
|
assert_eq!(
|
||||||
|
to_esc_str(
|
||||||
|
&Keystroke::parse(&format!("ctrl-alt-{}", character)).unwrap(),
|
||||||
|
Modes::NONE,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
format!("\x1b{}", esc_code)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_shift_enter_newline() {
|
||||||
|
let shift_enter = Keystroke::parse("shift-enter").unwrap();
|
||||||
|
let regular_enter = Keystroke::parse("enter").unwrap();
|
||||||
|
let mode = Modes::NONE;
|
||||||
|
|
||||||
|
// Shift-enter should send line feed (newline)
|
||||||
|
assert_eq!(to_esc_str(&shift_enter, mode, false), Some("\x0a".into()));
|
||||||
|
|
||||||
|
// Regular enter should still send carriage return
|
||||||
|
assert_eq!(to_esc_str(®ular_enter, mode, false), Some("\x0d".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_modifier_code_calc() {
|
||||||
|
// Code Modifiers
|
||||||
|
// ---------+---------------------------
|
||||||
|
// 2 | Shift
|
||||||
|
// 3 | Alt
|
||||||
|
// 4 | Shift + Alt
|
||||||
|
// 5 | Control
|
||||||
|
// 6 | Shift + Control
|
||||||
|
// 7 | Alt + Control
|
||||||
|
// 8 | Shift + Alt + Control
|
||||||
|
// ---------+---------------------------
|
||||||
|
// from: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
|
||||||
|
assert_eq!(2, modifier_code(&Keystroke::parse("shift-a").unwrap()));
|
||||||
|
assert_eq!(3, modifier_code(&Keystroke::parse("alt-a").unwrap()));
|
||||||
|
assert_eq!(4, modifier_code(&Keystroke::parse("shift-alt-a").unwrap()));
|
||||||
|
assert_eq!(5, modifier_code(&Keystroke::parse("ctrl-a").unwrap()));
|
||||||
|
assert_eq!(6, modifier_code(&Keystroke::parse("shift-ctrl-a").unwrap()));
|
||||||
|
assert_eq!(7, modifier_code(&Keystroke::parse("alt-ctrl-a").unwrap()));
|
||||||
|
assert_eq!(
|
||||||
|
8,
|
||||||
|
modifier_code(&Keystroke::parse("shift-ctrl-alt-a").unwrap())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user