From 8ab7d44d514e904df743dfe50be7bba725dc67ae Mon Sep 17 00:00:00 2001 From: tidely <43219534+tidely@users.noreply.github.com> Date: Tue, 3 Jun 2025 06:12:28 +0300 Subject: [PATCH] terminal: Match trait bounds with terminal input (#31441) The core change here is the following: ```rust fn write_to_pty(&self, input: impl Into>); // into fn write_to_pty(&self, input: impl Into>); ``` This matches the trait bounds that's used by the Alacritty crate. We are now allowed to effectively pass `&'static str` instead of always needing a `String`. The main benefit comes from making the `to_esc_str` function return a `Cow<'static, str>` instead of `String`. We save an allocation in the following instances: - When the user presses any special key that isn't alphanumerical (in the terminal) - When the uses presses any key while a modifier is active (in the terminal) - When focusing/un-focusing the terminal - When completing or undoing a terminal transaction - When starting a terminal assist This basically saves us an allocation on **every key** press in the terminal. NOTE: This same optimization can be done for **nearly all** keypresses in the entirety of Zed by changing the signature of the `Keystroke` struct in gpui. If the Zed team is interested in a PR for it, let me know. Release Notes: - N/A --- crates/agent/src/terminal_codegen.rs | 9 +- crates/agent/src/terminal_inline_assistant.rs | 2 +- crates/project/src/terminals.rs | 2 +- crates/terminal/src/mappings/keys.rs | 313 ++++++++---------- crates/terminal/src/terminal.rs | 28 +- crates/terminal_view/src/terminal_view.rs | 4 +- 6 files changed, 162 insertions(+), 196 deletions(-) diff --git a/crates/agent/src/terminal_codegen.rs b/crates/agent/src/terminal_codegen.rs index 4208402417..54f5b52f58 100644 --- a/crates/agent/src/terminal_codegen.rs +++ b/crates/agent/src/terminal_codegen.rs @@ -179,18 +179,17 @@ impl TerminalTransaction { // Ensure that the assistant cannot accidentally execute commands that are streamed into the terminal let input = Self::sanitize_input(hunk); self.terminal - .update(cx, |terminal, _| terminal.input(input)); + .update(cx, |terminal, _| terminal.input(input.into_bytes())); } pub fn undo(&self, cx: &mut App) { self.terminal - .update(cx, |terminal, _| terminal.input(CLEAR_INPUT.to_string())); + .update(cx, |terminal, _| terminal.input(CLEAR_INPUT.as_bytes())); } pub fn complete(&self, cx: &mut App) { - self.terminal.update(cx, |terminal, _| { - terminal.input(CARRIAGE_RETURN.to_string()) - }); + self.terminal + .update(cx, |terminal, _| terminal.input(CARRIAGE_RETURN.as_bytes())); } fn sanitize_input(mut input: String) -> String { diff --git a/crates/agent/src/terminal_inline_assistant.rs b/crates/agent/src/terminal_inline_assistant.rs index d96e37ea58..4e907f04ce 100644 --- a/crates/agent/src/terminal_inline_assistant.rs +++ b/crates/agent/src/terminal_inline_assistant.rs @@ -202,7 +202,7 @@ impl TerminalInlineAssistant { .update(cx, |terminal, cx| { terminal .terminal() - .update(cx, |terminal, _| terminal.input(CLEAR_INPUT.to_string())); + .update(cx, |terminal, _| terminal.input(CLEAR_INPUT.as_bytes())); }) .log_err(); diff --git a/crates/project/src/terminals.rs b/crates/project/src/terminals.rs index b49c5e29dc..00e12a312f 100644 --- a/crates/project/src/terminals.rs +++ b/crates/project/src/terminals.rs @@ -514,7 +514,7 @@ impl Project { terminal_handle: &Entity, cx: &mut App, ) { - terminal_handle.update(cx, |terminal, _| terminal.input(command)); + terminal_handle.update(cx, |terminal, _| terminal.input(command.into_bytes())); } pub fn local_terminal_handles(&self) -> &Vec> { diff --git a/crates/terminal/src/mappings/keys.rs b/crates/terminal/src/mappings/keys.rs index 785cfaeacc..a9139ae601 100644 --- a/crates/terminal/src/mappings/keys.rs +++ b/crates/terminal/src/mappings/keys.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + /// The mappings defined in this file where created from reading the alacritty source use alacritty_terminal::term::TermMode; use gpui::Keystroke; @@ -41,162 +43,138 @@ impl AlacModifiers { } } -pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) -> Option { +pub fn to_esc_str( + keystroke: &Keystroke, + mode: &TermMode, + alt_is_meta: bool, +) -> Option> { let modifiers = AlacModifiers::new(keystroke); // Manual Bindings including modifiers - let manual_esc_str = match (keystroke.key.as_ref(), &modifiers) { + let manual_esc_str: Option<&'static str> = match (keystroke.key.as_ref(), &modifiers) { //Basic special keys - ("tab", AlacModifiers::None) => Some("\x09".to_string()), - ("escape", AlacModifiers::None) => Some("\x1b".to_string()), - ("enter", AlacModifiers::None) => Some("\x0d".to_string()), - ("enter", AlacModifiers::Shift) => Some("\x0d".to_string()), - ("enter", AlacModifiers::Alt) => Some("\x1b\x0d".to_string()), - ("backspace", AlacModifiers::None) => Some("\x7f".to_string()), + ("tab", AlacModifiers::None) => Some("\x09"), + ("escape", AlacModifiers::None) => Some("\x1b"), + ("enter", AlacModifiers::None) => Some("\x0d"), + ("enter", AlacModifiers::Shift) => Some("\x0d"), + ("enter", AlacModifiers::Alt) => Some("\x1b\x0d"), + ("backspace", AlacModifiers::None) => Some("\x7f"), //Interesting escape codes - ("tab", AlacModifiers::Shift) => Some("\x1b[Z".to_string()), - ("backspace", AlacModifiers::Ctrl) => Some("\x08".to_string()), - ("backspace", AlacModifiers::Alt) => Some("\x1b\x7f".to_string()), - ("backspace", AlacModifiers::Shift) => Some("\x7f".to_string()), - ("space", AlacModifiers::Ctrl) => Some("\x00".to_string()), - ("home", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => { - Some("\x1b[1;2H".to_string()) - } - ("end", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => { - Some("\x1b[1;2F".to_string()) - } + ("tab", AlacModifiers::Shift) => Some("\x1b[Z"), + ("backspace", AlacModifiers::Ctrl) => Some("\x08"), + ("backspace", AlacModifiers::Alt) => Some("\x1b\x7f"), + ("backspace", AlacModifiers::Shift) => Some("\x7f"), + ("space", AlacModifiers::Ctrl) => Some("\x00"), + ("home", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => Some("\x1b[1;2H"), + ("end", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => Some("\x1b[1;2F"), ("pageup", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => { - Some("\x1b[5;2~".to_string()) + Some("\x1b[5;2~") } ("pagedown", AlacModifiers::Shift) if mode.contains(TermMode::ALT_SCREEN) => { - Some("\x1b[6;2~".to_string()) + Some("\x1b[6;2~") } - ("home", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => { - Some("\x1bOH".to_string()) - } - ("home", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => { - Some("\x1b[H".to_string()) - } - ("end", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => { - Some("\x1bOF".to_string()) - } - ("end", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => { - Some("\x1b[F".to_string()) - } - ("up", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => { - Some("\x1bOA".to_string()) - } - ("up", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => { - Some("\x1b[A".to_string()) - } - ("down", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => { - Some("\x1bOB".to_string()) - } - ("down", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => { - Some("\x1b[B".to_string()) - } - ("right", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => { - Some("\x1bOC".to_string()) - } - ("right", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => { - Some("\x1b[C".to_string()) - } - ("left", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => { - Some("\x1bOD".to_string()) - } - ("left", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => { - Some("\x1b[D".to_string()) - } - ("back", AlacModifiers::None) => Some("\x7f".to_string()), - ("insert", AlacModifiers::None) => Some("\x1b[2~".to_string()), - ("delete", AlacModifiers::None) => Some("\x1b[3~".to_string()), - ("pageup", AlacModifiers::None) => Some("\x1b[5~".to_string()), - ("pagedown", AlacModifiers::None) => Some("\x1b[6~".to_string()), - ("f1", AlacModifiers::None) => Some("\x1bOP".to_string()), - ("f2", AlacModifiers::None) => Some("\x1bOQ".to_string()), - ("f3", AlacModifiers::None) => Some("\x1bOR".to_string()), - ("f4", AlacModifiers::None) => Some("\x1bOS".to_string()), - ("f5", AlacModifiers::None) => Some("\x1b[15~".to_string()), - ("f6", AlacModifiers::None) => Some("\x1b[17~".to_string()), - ("f7", AlacModifiers::None) => Some("\x1b[18~".to_string()), - ("f8", AlacModifiers::None) => Some("\x1b[19~".to_string()), - ("f9", AlacModifiers::None) => Some("\x1b[20~".to_string()), - ("f10", AlacModifiers::None) => Some("\x1b[21~".to_string()), - ("f11", AlacModifiers::None) => Some("\x1b[23~".to_string()), - ("f12", AlacModifiers::None) => Some("\x1b[24~".to_string()), - ("f13", AlacModifiers::None) => Some("\x1b[25~".to_string()), - ("f14", AlacModifiers::None) => Some("\x1b[26~".to_string()), - ("f15", AlacModifiers::None) => Some("\x1b[28~".to_string()), - ("f16", AlacModifiers::None) => Some("\x1b[29~".to_string()), - ("f17", AlacModifiers::None) => Some("\x1b[31~".to_string()), - ("f18", AlacModifiers::None) => Some("\x1b[32~".to_string()), - ("f19", AlacModifiers::None) => Some("\x1b[33~".to_string()), - ("f20", AlacModifiers::None) => Some("\x1b[34~".to_string()), + ("home", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => Some("\x1bOH"), + ("home", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => Some("\x1b[H"), + ("end", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => Some("\x1bOF"), + ("end", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => Some("\x1b[F"), + ("up", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => Some("\x1bOA"), + ("up", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => Some("\x1b[A"), + ("down", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => Some("\x1bOB"), + ("down", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => Some("\x1b[B"), + ("right", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => Some("\x1bOC"), + ("right", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => Some("\x1b[C"), + ("left", AlacModifiers::None) if mode.contains(TermMode::APP_CURSOR) => Some("\x1bOD"), + ("left", AlacModifiers::None) if !mode.contains(TermMode::APP_CURSOR) => Some("\x1b[D"), + ("back", AlacModifiers::None) => Some("\x7f"), + ("insert", AlacModifiers::None) => Some("\x1b[2~"), + ("delete", AlacModifiers::None) => Some("\x1b[3~"), + ("pageup", AlacModifiers::None) => Some("\x1b[5~"), + ("pagedown", AlacModifiers::None) => Some("\x1b[6~"), + ("f1", AlacModifiers::None) => Some("\x1bOP"), + ("f2", AlacModifiers::None) => Some("\x1bOQ"), + ("f3", AlacModifiers::None) => Some("\x1bOR"), + ("f4", AlacModifiers::None) => Some("\x1bOS"), + ("f5", AlacModifiers::None) => Some("\x1b[15~"), + ("f6", AlacModifiers::None) => Some("\x1b[17~"), + ("f7", AlacModifiers::None) => Some("\x1b[18~"), + ("f8", AlacModifiers::None) => Some("\x1b[19~"), + ("f9", AlacModifiers::None) => Some("\x1b[20~"), + ("f10", AlacModifiers::None) => Some("\x1b[21~"), + ("f11", AlacModifiers::None) => Some("\x1b[23~"), + ("f12", AlacModifiers::None) => Some("\x1b[24~"), + ("f13", AlacModifiers::None) => Some("\x1b[25~"), + ("f14", AlacModifiers::None) => Some("\x1b[26~"), + ("f15", AlacModifiers::None) => Some("\x1b[28~"), + ("f16", AlacModifiers::None) => Some("\x1b[29~"), + ("f17", AlacModifiers::None) => Some("\x1b[31~"), + ("f18", AlacModifiers::None) => Some("\x1b[32~"), + ("f19", AlacModifiers::None) => Some("\x1b[33~"), + ("f20", AlacModifiers::None) => Some("\x1b[34~"), // NumpadEnter, Action::Esc("\n".into()); //Mappings for caret notation keys - ("a", AlacModifiers::Ctrl) => Some("\x01".to_string()), //1 - ("A", AlacModifiers::CtrlShift) => Some("\x01".to_string()), //1 - ("b", AlacModifiers::Ctrl) => Some("\x02".to_string()), //2 - ("B", AlacModifiers::CtrlShift) => Some("\x02".to_string()), //2 - ("c", AlacModifiers::Ctrl) => Some("\x03".to_string()), //3 - ("C", AlacModifiers::CtrlShift) => Some("\x03".to_string()), //3 - ("d", AlacModifiers::Ctrl) => Some("\x04".to_string()), //4 - ("D", AlacModifiers::CtrlShift) => Some("\x04".to_string()), //4 - ("e", AlacModifiers::Ctrl) => Some("\x05".to_string()), //5 - ("E", AlacModifiers::CtrlShift) => Some("\x05".to_string()), //5 - ("f", AlacModifiers::Ctrl) => Some("\x06".to_string()), //6 - ("F", AlacModifiers::CtrlShift) => Some("\x06".to_string()), //6 - ("g", AlacModifiers::Ctrl) => Some("\x07".to_string()), //7 - ("G", AlacModifiers::CtrlShift) => Some("\x07".to_string()), //7 - ("h", AlacModifiers::Ctrl) => Some("\x08".to_string()), //8 - ("H", AlacModifiers::CtrlShift) => Some("\x08".to_string()), //8 - ("i", AlacModifiers::Ctrl) => Some("\x09".to_string()), //9 - ("I", AlacModifiers::CtrlShift) => Some("\x09".to_string()), //9 - ("j", AlacModifiers::Ctrl) => Some("\x0a".to_string()), //10 - ("J", AlacModifiers::CtrlShift) => Some("\x0a".to_string()), //10 - ("k", AlacModifiers::Ctrl) => Some("\x0b".to_string()), //11 - ("K", AlacModifiers::CtrlShift) => Some("\x0b".to_string()), //11 - ("l", AlacModifiers::Ctrl) => Some("\x0c".to_string()), //12 - ("L", AlacModifiers::CtrlShift) => Some("\x0c".to_string()), //12 - ("m", AlacModifiers::Ctrl) => Some("\x0d".to_string()), //13 - ("M", AlacModifiers::CtrlShift) => Some("\x0d".to_string()), //13 - ("n", AlacModifiers::Ctrl) => Some("\x0e".to_string()), //14 - ("N", AlacModifiers::CtrlShift) => Some("\x0e".to_string()), //14 - ("o", AlacModifiers::Ctrl) => Some("\x0f".to_string()), //15 - ("O", AlacModifiers::CtrlShift) => Some("\x0f".to_string()), //15 - ("p", AlacModifiers::Ctrl) => Some("\x10".to_string()), //16 - ("P", AlacModifiers::CtrlShift) => Some("\x10".to_string()), //16 - ("q", AlacModifiers::Ctrl) => Some("\x11".to_string()), //17 - ("Q", AlacModifiers::CtrlShift) => Some("\x11".to_string()), //17 - ("r", AlacModifiers::Ctrl) => Some("\x12".to_string()), //18 - ("R", AlacModifiers::CtrlShift) => Some("\x12".to_string()), //18 - ("s", AlacModifiers::Ctrl) => Some("\x13".to_string()), //19 - ("S", AlacModifiers::CtrlShift) => Some("\x13".to_string()), //19 - ("t", AlacModifiers::Ctrl) => Some("\x14".to_string()), //20 - ("T", AlacModifiers::CtrlShift) => Some("\x14".to_string()), //20 - ("u", AlacModifiers::Ctrl) => Some("\x15".to_string()), //21 - ("U", AlacModifiers::CtrlShift) => Some("\x15".to_string()), //21 - ("v", AlacModifiers::Ctrl) => Some("\x16".to_string()), //22 - ("V", AlacModifiers::CtrlShift) => Some("\x16".to_string()), //22 - ("w", AlacModifiers::Ctrl) => Some("\x17".to_string()), //23 - ("W", AlacModifiers::CtrlShift) => Some("\x17".to_string()), //23 - ("x", AlacModifiers::Ctrl) => Some("\x18".to_string()), //24 - ("X", AlacModifiers::CtrlShift) => Some("\x18".to_string()), //24 - ("y", AlacModifiers::Ctrl) => Some("\x19".to_string()), //25 - ("Y", AlacModifiers::CtrlShift) => Some("\x19".to_string()), //25 - ("z", AlacModifiers::Ctrl) => Some("\x1a".to_string()), //26 - ("Z", AlacModifiers::CtrlShift) => Some("\x1a".to_string()), //26 - ("@", AlacModifiers::Ctrl) => Some("\x00".to_string()), //0 - ("[", AlacModifiers::Ctrl) => Some("\x1b".to_string()), //27 - ("\\", AlacModifiers::Ctrl) => Some("\x1c".to_string()), //28 - ("]", AlacModifiers::Ctrl) => Some("\x1d".to_string()), //29 - ("^", AlacModifiers::Ctrl) => Some("\x1e".to_string()), //30 - ("_", AlacModifiers::Ctrl) => Some("\x1f".to_string()), //31 - ("?", AlacModifiers::Ctrl) => Some("\x7f".to_string()), //127 + ("a", AlacModifiers::Ctrl) => Some("\x01"), //1 + ("A", AlacModifiers::CtrlShift) => Some("\x01"), //1 + ("b", AlacModifiers::Ctrl) => Some("\x02"), //2 + ("B", AlacModifiers::CtrlShift) => Some("\x02"), //2 + ("c", AlacModifiers::Ctrl) => Some("\x03"), //3 + ("C", AlacModifiers::CtrlShift) => Some("\x03"), //3 + ("d", AlacModifiers::Ctrl) => Some("\x04"), //4 + ("D", AlacModifiers::CtrlShift) => Some("\x04"), //4 + ("e", AlacModifiers::Ctrl) => Some("\x05"), //5 + ("E", AlacModifiers::CtrlShift) => Some("\x05"), //5 + ("f", AlacModifiers::Ctrl) => Some("\x06"), //6 + ("F", AlacModifiers::CtrlShift) => Some("\x06"), //6 + ("g", AlacModifiers::Ctrl) => Some("\x07"), //7 + ("G", AlacModifiers::CtrlShift) => Some("\x07"), //7 + ("h", AlacModifiers::Ctrl) => Some("\x08"), //8 + ("H", AlacModifiers::CtrlShift) => Some("\x08"), //8 + ("i", AlacModifiers::Ctrl) => Some("\x09"), //9 + ("I", AlacModifiers::CtrlShift) => Some("\x09"), //9 + ("j", AlacModifiers::Ctrl) => Some("\x0a"), //10 + ("J", AlacModifiers::CtrlShift) => Some("\x0a"), //10 + ("k", AlacModifiers::Ctrl) => Some("\x0b"), //11 + ("K", AlacModifiers::CtrlShift) => Some("\x0b"), //11 + ("l", AlacModifiers::Ctrl) => Some("\x0c"), //12 + ("L", AlacModifiers::CtrlShift) => Some("\x0c"), //12 + ("m", AlacModifiers::Ctrl) => Some("\x0d"), //13 + ("M", AlacModifiers::CtrlShift) => Some("\x0d"), //13 + ("n", AlacModifiers::Ctrl) => Some("\x0e"), //14 + ("N", AlacModifiers::CtrlShift) => Some("\x0e"), //14 + ("o", AlacModifiers::Ctrl) => Some("\x0f"), //15 + ("O", AlacModifiers::CtrlShift) => Some("\x0f"), //15 + ("p", AlacModifiers::Ctrl) => Some("\x10"), //16 + ("P", AlacModifiers::CtrlShift) => Some("\x10"), //16 + ("q", AlacModifiers::Ctrl) => Some("\x11"), //17 + ("Q", AlacModifiers::CtrlShift) => Some("\x11"), //17 + ("r", AlacModifiers::Ctrl) => Some("\x12"), //18 + ("R", AlacModifiers::CtrlShift) => Some("\x12"), //18 + ("s", AlacModifiers::Ctrl) => Some("\x13"), //19 + ("S", AlacModifiers::CtrlShift) => Some("\x13"), //19 + ("t", AlacModifiers::Ctrl) => Some("\x14"), //20 + ("T", AlacModifiers::CtrlShift) => Some("\x14"), //20 + ("u", AlacModifiers::Ctrl) => Some("\x15"), //21 + ("U", AlacModifiers::CtrlShift) => Some("\x15"), //21 + ("v", AlacModifiers::Ctrl) => Some("\x16"), //22 + ("V", AlacModifiers::CtrlShift) => Some("\x16"), //22 + ("w", AlacModifiers::Ctrl) => Some("\x17"), //23 + ("W", AlacModifiers::CtrlShift) => Some("\x17"), //23 + ("x", AlacModifiers::Ctrl) => Some("\x18"), //24 + ("X", AlacModifiers::CtrlShift) => Some("\x18"), //24 + ("y", AlacModifiers::Ctrl) => Some("\x19"), //25 + ("Y", AlacModifiers::CtrlShift) => Some("\x19"), //25 + ("z", AlacModifiers::Ctrl) => Some("\x1a"), //26 + ("Z", AlacModifiers::CtrlShift) => Some("\x1a"), //26 + ("@", AlacModifiers::Ctrl) => Some("\x00"), //0 + ("[", AlacModifiers::Ctrl) => Some("\x1b"), //27 + ("\\", AlacModifiers::Ctrl) => Some("\x1c"), //28 + ("]", AlacModifiers::Ctrl) => Some("\x1d"), //29 + ("^", AlacModifiers::Ctrl) => Some("\x1e"), //30 + ("_", AlacModifiers::Ctrl) => Some("\x1f"), //31 + ("?", AlacModifiers::Ctrl) => Some("\x7f"), //127 _ => None, }; - if manual_esc_str.is_some() { - return manual_esc_str; + if let Some(esc_str) = manual_esc_str { + return Some(Cow::Borrowed(esc_str)); } // Automated bindings applying modifiers @@ -235,8 +213,8 @@ pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) -> "home" => Some(format!("\x1b[1;{}H", modifier_code)), _ => None, }; - if modified_esc_str.is_some() { - return modified_esc_str; + if let Some(esc_str) = modified_esc_str { + return Some(Cow::Owned(esc_str)); } } @@ -250,7 +228,7 @@ pub fn to_esc_str(keystroke: &Keystroke, mode: &TermMode, alt_is_meta: bool) -> } else { &keystroke.key }; - return Some(format!("\x1b{}", key)); + return Some(Cow::Owned(format!("\x1b{}", key))); } } @@ -306,33 +284,27 @@ mod test { let alt_screen = TermMode::ALT_SCREEN; assert_eq!( to_esc_str(&shift_pageup, &alt_screen, false), - Some("\x1b[5;2~".to_string()) + Some("\x1b[5;2~".into()) ); assert_eq!( to_esc_str(&shift_pagedown, &alt_screen, false), - Some("\x1b[6;2~".to_string()) + Some("\x1b[6;2~".into()) ); assert_eq!( to_esc_str(&shift_home, &alt_screen, false), - Some("\x1b[1;2H".to_string()) + Some("\x1b[1;2H".into()) ); assert_eq!( to_esc_str(&shift_end, &alt_screen, false), - Some("\x1b[1;2F".to_string()) + Some("\x1b[1;2F".into()) ); let pageup = Keystroke::parse("pageup").unwrap(); let pagedown = Keystroke::parse("pagedown").unwrap(); let any = TermMode::ANY; - assert_eq!( - to_esc_str(&pageup, &any, false), - Some("\x1b[5~".to_string()) - ); - assert_eq!( - to_esc_str(&pagedown, &any, false), - Some("\x1b[6~".to_string()) - ); + assert_eq!(to_esc_str(&pageup, &any, false), Some("\x1b[5~".into())); + assert_eq!(to_esc_str(&pagedown, &any, false), Some("\x1b[6~".into())); } #[test] @@ -361,27 +333,18 @@ mod test { let left = Keystroke::parse("left").unwrap(); let right = Keystroke::parse("right").unwrap(); - assert_eq!(to_esc_str(&up, &none, false), Some("\x1b[A".to_string())); - assert_eq!(to_esc_str(&down, &none, false), Some("\x1b[B".to_string())); - assert_eq!(to_esc_str(&right, &none, false), Some("\x1b[C".to_string())); - assert_eq!(to_esc_str(&left, &none, false), Some("\x1b[D".to_string())); + 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".to_string()) - ); - assert_eq!( - to_esc_str(&down, &app_cursor, false), - Some("\x1bOB".to_string()) - ); + 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".to_string()) - ); - assert_eq!( - to_esc_str(&left, &app_cursor, false), - Some("\x1bOD".to_string()) + Some("\x1bOC".into()) ); + assert_eq!(to_esc_str(&left, &app_cursor, false), Some("\x1bOD".into())); } #[test] diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 21100f42c1..efdcc90a0c 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -724,12 +724,13 @@ impl Terminal { // The terminal only supports pasting strings, not images. Some(text) => format(text), _ => format(""), - }, + } + .into_bytes(), ) } - AlacTermEvent::PtyWrite(out) => self.write_to_pty(out), + AlacTermEvent::PtyWrite(out) => self.write_to_pty(out.into_bytes()), AlacTermEvent::TextAreaSizeRequest(format) => { - self.write_to_pty(format(self.last_content.terminal_bounds.into())) + self.write_to_pty(format(self.last_content.terminal_bounds.into()).into_bytes()) } AlacTermEvent::CursorBlinkingChange => { let terminal = self.term.lock(); @@ -761,7 +762,7 @@ impl Terminal { // followed by a color request sequence. let color = self.term.lock().colors()[index] .unwrap_or_else(|| to_alac_rgb(get_color_at_index(index, cx.theme().as_ref()))); - self.write_to_pty(format(color)); + self.write_to_pty(format(color).into_bytes()); } AlacTermEvent::ChildExit(error_code) => { self.register_task_finished(Some(error_code), cx); @@ -1227,11 +1228,11 @@ impl Terminal { } ///Write the Input payload to the tty. - fn write_to_pty(&self, input: impl Into>) { + fn write_to_pty(&self, input: impl Into>) { self.pty_tx.notify(input.into()); } - pub fn input(&mut self, input: impl Into>) { + pub fn input(&mut self, input: impl Into>) { self.events .push_back(InternalEvent::Scroll(AlacScroll::Bottom)); self.events.push_back(InternalEvent::SetSelection(None)); @@ -1345,7 +1346,10 @@ impl Terminal { // Keep default terminal behavior let esc = to_esc_str(keystroke, &self.last_content.mode, alt_is_meta); if let Some(esc) = esc { - self.input(esc); + match esc { + Cow::Borrowed(string) => self.input(string.as_bytes()), + Cow::Owned(string) => self.input(string.into_bytes()), + }; true } else { false @@ -1378,7 +1382,7 @@ impl Terminal { text.replace("\r\n", "\r").replace('\n', "\r") }; - self.input(paste_text); + self.input(paste_text.into_bytes()); } pub fn sync(&mut self, window: &mut Window, cx: &mut Context) { @@ -1487,13 +1491,13 @@ impl Terminal { pub fn focus_in(&self) { if self.last_content.mode.contains(TermMode::FOCUS_IN_OUT) { - self.write_to_pty("\x1b[I".to_string()); + self.write_to_pty("\x1b[I".as_bytes()); } } pub fn focus_out(&mut self) { if self.last_content.mode.contains(TermMode::FOCUS_IN_OUT) { - self.write_to_pty("\x1b[O".to_string()); + self.write_to_pty("\x1b[O".as_bytes()); } } @@ -1660,7 +1664,7 @@ impl Terminal { MouseButton::Middle => { if let Some(item) = _cx.read_from_primary() { let text = item.text().unwrap_or_default().to_string(); - self.input(text); + self.input(text.into_bytes()); } } _ => {} @@ -1832,7 +1836,7 @@ impl Terminal { .map(|name| name.to_string_lossy().to_string()) .unwrap_or_default(); - let argv = fpi.argv.clone(); + let argv = fpi.argv.as_slice(); let process_name = format!( "{}{}", fpi.name, diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index c393fd54ad..e7b2138677 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -266,7 +266,7 @@ impl TerminalView { pub(crate) fn commit_text(&mut self, text: &str, cx: &mut Context) { if !text.is_empty() { self.terminal.update(cx, |term, _| { - term.input(text.to_string()); + term.input(text.to_string().into_bytes()); }); } } @@ -643,7 +643,7 @@ impl TerminalView { fn send_text(&mut self, text: &SendText, _: &mut Window, cx: &mut Context) { self.clear_bell(cx); self.terminal.update(cx, |term, _| { - term.input(text.0.to_string()); + term.input(text.0.to_string().into_bytes()); }); }