tenseleyflow/fackr / 496c7e2

Browse files

Fix terminal bracketed paste handling

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
496c7e27d69625a7a2a4f0fff578586890f076bd
Parents
d8851a8
Tree
fe7dd4a

3 changed files

StatusFile+-
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 {
17751775
 
17761776
         // Route paste to terminal when terminal has focus.
17771777
         if self.focus == Focus::Terminal && self.terminal.visible {
1778
-            self.terminal.send_input(text.as_bytes())?;
1778
+            self.terminal.send_paste(text.as_bytes())?;
17791779
             return Ok(());
17801780
         }
17811781
 
src/terminal/panel.rsmodified
@@ -73,6 +73,16 @@ impl TerminalSession {
7373
         Ok(())
7474
     }
7575
 
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
+
7686
     /// Resize this session
7787
     fn resize(&mut self, width: u16, height: u16) {
7888
         self.screen.resize(width, height);
@@ -227,6 +237,14 @@ impl TerminalPanel {
227237
         Ok(())
228238
     }
229239
 
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
+
230248
     /// Send a key to the active terminal
231249
     pub fn send_key(&mut self, key: &crossterm::event::KeyEvent) -> Result<()> {
232250
         use crossterm::event::{KeyCode, KeyModifiers};
@@ -394,3 +412,24 @@ impl TerminalPanel {
394412
         }
395413
     }
396414
 }
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 {
209209
         std::mem::take(&mut self.response_queue)
210210
     }
211211
 
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
+
212217
     /// Enter alternate screen buffer
213218
     fn enter_alt_screen(&mut self) {
214219
         if !self.using_alt_screen {