Fix terminal bracketed paste handling
Authored by
mfwolffe <wolffemf@dukes.jmu.edu>
- SHA
496c7e27d69625a7a2a4f0fff578586890f076bd- Parents
-
d8851a8 - Tree
fe7dd4a
496c7e2
496c7e27d69625a7a2a4f0fff578586890f076bdd8851a8
fe7dd4a| Status | File | + | - |
|---|---|---|---|
| M |
src/editor/state.rs
|
1 | 1 |
| M |
src/terminal/panel.rs
|
39 | 0 |
| M |
src/terminal/screen.rs
|
5 | 0 |
src/editor/state.rsmodified@@ -1775,7 +1775,7 @@ impl Editor { | |||
| 1775 | 1775 | ||
| 1776 | // Route paste to terminal when terminal has focus. | 1776 | // Route paste to terminal when terminal has focus. |
| 1777 | if self.focus == Focus::Terminal && self.terminal.visible { | 1777 | if self.focus == Focus::Terminal && self.terminal.visible { |
| 1778 | - self.terminal.send_input(text.as_bytes())?; | 1778 | + self.terminal.send_paste(text.as_bytes())?; |
| 1779 | return Ok(()); | 1779 | return Ok(()); |
| 1780 | } | 1780 | } |
| 1781 | 1781 | ||
src/terminal/panel.rsmodified@@ -73,6 +73,16 @@ impl TerminalSession { | |||
| 73 | Ok(()) | 73 | Ok(()) |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | + /// Send pasted input, honoring bracketed paste mode when requested by the app. | ||
| 77 | + fn send_paste(&mut self, data: &[u8]) -> Result<()> { | ||
| 78 | + let payload = if self.screen.bracketed_paste_enabled() { | ||
| 79 | + encode_bracketed_paste(data) | ||
| 80 | + } else { | ||
| 81 | + data.to_vec() | ||
| 82 | + }; | ||
| 83 | + self.send_input(&payload) | ||
| 84 | + } | ||
| 85 | + | ||
| 76 | /// Resize this session | 86 | /// Resize this session |
| 77 | fn resize(&mut self, width: u16, height: u16) { | 87 | fn resize(&mut self, width: u16, height: u16) { |
| 78 | self.screen.resize(width, height); | 88 | self.screen.resize(width, height); |
@@ -227,6 +237,14 @@ impl TerminalPanel { | |||
| 227 | Ok(()) | 237 | Ok(()) |
| 228 | } | 238 | } |
| 229 | 239 | ||
| 240 | + /// Send pasted input to the active terminal session. | ||
| 241 | + pub fn send_paste(&mut self, data: &[u8]) -> Result<()> { | ||
| 242 | + if let Some(session) = self.sessions.get_mut(self.active_session) { | ||
| 243 | + session.send_paste(data)?; | ||
| 244 | + } | ||
| 245 | + Ok(()) | ||
| 246 | + } | ||
| 247 | + | ||
| 230 | /// Send a key to the active terminal | 248 | /// Send a key to the active terminal |
| 231 | pub fn send_key(&mut self, key: &crossterm::event::KeyEvent) -> Result<()> { | 249 | pub fn send_key(&mut self, key: &crossterm::event::KeyEvent) -> Result<()> { |
| 232 | use crossterm::event::{KeyCode, KeyModifiers}; | 250 | use crossterm::event::{KeyCode, KeyModifiers}; |
@@ -394,3 +412,24 @@ impl TerminalPanel { | |||
| 394 | } | 412 | } |
| 395 | } | 413 | } |
| 396 | } | 414 | } |
| 415 | + | ||
| 416 | +fn encode_bracketed_paste(data: &[u8]) -> Vec<u8> { | ||
| 417 | + let mut wrapped = Vec::with_capacity(data.len() + 12); | ||
| 418 | + wrapped.extend_from_slice(b"\x1b[200~"); | ||
| 419 | + wrapped.extend_from_slice(data); | ||
| 420 | + wrapped.extend_from_slice(b"\x1b[201~"); | ||
| 421 | + wrapped | ||
| 422 | +} | ||
| 423 | + | ||
| 424 | +#[cfg(test)] | ||
| 425 | +mod tests { | ||
| 426 | + use super::encode_bracketed_paste; | ||
| 427 | + | ||
| 428 | + #[test] | ||
| 429 | + fn bracketed_paste_wraps_raw_bytes() { | ||
| 430 | + assert_eq!( | ||
| 431 | + encode_bracketed_paste(b"line 1\nline 2"), | ||
| 432 | + b"\x1b[200~line 1\nline 2\x1b[201~" | ||
| 433 | + ); | ||
| 434 | + } | ||
| 435 | +} | ||
src/terminal/screen.rsmodified@@ -209,6 +209,11 @@ impl TerminalScreen { | |||
| 209 | std::mem::take(&mut self.response_queue) | 209 | std::mem::take(&mut self.response_queue) |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | + /// Whether the application running in the terminal has enabled bracketed paste. | ||
| 213 | + pub fn bracketed_paste_enabled(&self) -> bool { | ||
| 214 | + self.bracketed_paste | ||
| 215 | + } | ||
| 216 | + | ||
| 212 | /// Enter alternate screen buffer | 217 | /// Enter alternate screen buffer |
| 213 | fn enter_alt_screen(&mut self) { | 218 | fn enter_alt_screen(&mut self) { |
| 214 | if !self.using_alt_screen { | 219 | if !self.using_alt_screen { |