in crates/figterm/src/input/mod.rs [393:536]
fn encode_kitty(&self, mods: Modifiers, is_down: bool, flags: KittyKeyboardFlags) -> Result<String> {
use KeyCode::{
Backspace,
Char,
Delete,
DownArrow,
End,
Enter,
Function,
Home,
Insert,
LeftArrow,
PageDown,
PageUp,
RightArrow,
Tab,
UpArrow,
};
if !flags.contains(KittyKeyboardFlags::REPORT_EVENT_TYPES) && !is_down {
return Ok(String::new());
}
// Normalize
let key = match self {
Char('\r') => Enter,
Char('\t') => Tab,
Char('\x7f') => Delete,
Char('\x08') => Backspace,
c => *c,
};
if mods.is_empty() && !flags.contains(KittyKeyboardFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES) {
// Check for simple text generating keys
match key {
Enter => return Ok("\r".to_string()),
Tab => return Ok("\t".to_string()),
Backspace => return Ok("\x7f".to_string()),
Char(c) => return Ok(c.to_string()),
_ => {},
}
}
let mut modifiers = 0;
if mods.contains(Modifiers::SHIFT) {
modifiers |= 1;
}
if mods.contains(Modifiers::ALT) {
modifiers |= 2;
}
if mods.contains(Modifiers::CTRL) {
modifiers |= 4;
}
if mods.contains(Modifiers::META) {
modifiers |= 8;
}
modifiers += 1;
let event_type = if flags.contains(KittyKeyboardFlags::REPORT_EVENT_TYPES) && !is_down {
":3"
} else {
""
};
match key {
Char(shifted_key) => {
let c = shifted_key.to_ascii_lowercase();
let key_code = if flags.contains(KittyKeyboardFlags::REPORT_ALTERNATE_KEYS) && c != shifted_key {
// Note: we don't have enough information here to know what the base-layout key
// should really be.
let base_layout = c;
format!("{c}:{shifted_key}:{base_layout}")
} else {
(c as u32).to_string()
};
Ok(format!("\x1b[{key_code};{modifiers}{event_type}u"))
},
LeftArrow | RightArrow | UpArrow | DownArrow | Home | End => {
let c = match key {
UpArrow => 'A',
DownArrow => 'B',
RightArrow => 'C',
LeftArrow => 'D',
Home => 'H',
End => 'F',
_ => unreachable!(),
};
Ok(format!("\x1b[1;{modifiers}{event_type}{c}"))
},
PageUp | PageDown | Insert | Delete => {
let c = match key {
Insert => 2,
Delete => 3,
PageUp => 5,
PageDown => 6,
_ => unreachable!(),
};
Ok(format!("\x1b[{c};{modifiers}{event_type}~"))
},
Function(n) if n < 13 => {
if mods.is_empty() && n < 5 {
// F1-F4 are encoded using SS3 if there are no modifiers
Ok((match n {
1 => "\x1bOP",
2 => "\x1bOQ",
3 => "\x1bOR",
4 => "\x1bOS",
_ => unreachable!("wat?"),
})
.to_string())
} else {
// Higher numbered F-keys plus modified F-keys are encoded
// using CSI instead of SS3.
let intro = match n {
1 => "\x1b[11",
2 => "\x1b[12",
3 => "\x1b[13",
4 => "\x1b[14",
5 => "\x1b[15",
6 => "\x1b[17",
7 => "\x1b[18",
8 => "\x1b[19",
9 => "\x1b[20",
10 => "\x1b[21",
11 => "\x1b[23",
12 => "\x1b[24",
_ => unreachable!(),
};
Ok(format!("{intro};{modifiers}{event_type}~"))
}
},
_ => {
if let Some(code) = key.kitty_function_code() {
Ok(format!("\x1b[{code};{modifiers}{event_type}u"))
} else {
Ok(String::new())
}
},
}
}