-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Problem / Background
When using PTY mode for SSH sessions, clipboard paste operations (Cmd+V on macOS / Ctrl+V on Linux/Windows) do not work. Users cannot paste text from their clipboard into the interactive SSH session.
Root Cause Analysis
The issue stems from two related problems in the PTY input handling:
-
Missing Event::Paste handler (
src/pty/session/input.rs, line 42)- The
handle_input_event()function has a catch-all_ => Nonepattern that silently ignoresEvent::Pasteevents from crossterm - Even when bracketed paste is enabled, paste events are discarded
- The
-
Bracketed Paste not enabled (
src/pty/terminal.rs)crossterm::event::EnableBracketedPasteis not called during terminal initialization inTerminalStateGuard::new()- Without bracketed paste mode, the terminal cannot properly distinguish paste operations from rapid keystrokes
DisableBracketedPasteis also not called in theDropimplementation for cleanup
-
No fallback for rapid keystroke paste
- Even without bracketed paste, some terminals send pasted text as rapid key events, but the current implementation doesn't handle this case efficiently
Proposed Solution
1. Enable Bracketed Paste Mode
In src/pty/terminal.rs, modify TerminalStateGuard::new():
use crossterm::event::{EnableBracketedPaste, DisableBracketedPaste};
// In new():
execute!(std::io::stdout(), EnableBracketedPaste)?;
// In Drop or restore_terminal_state():
execute!(std::io::stdout(), DisableBracketedPaste)?;2. Handle Event::Paste in input handler
In src/pty/session/input.rs, add a new match arm before the catch-all:
Event::Paste(text) => {
let bytes = text.into_bytes();
Some(SmallVec::from_slice(&bytes))
}Note: For large paste content exceeding SmallVec<[u8; 8]> capacity, consider using a Vec<u8> return type or returning an enum that can handle both small and large payloads efficiently.
Acceptance Criteria
-
EnableBracketedPasteis activated inTerminalStateGuard::new() -
DisableBracketedPasteis called during terminal state restoration (Drop) -
Event::Paste(text)is handled inhandle_input_event()and text is sent to SSH channel - Paste operations work correctly on macOS (Cmd+V), Linux (Ctrl+Shift+V), and Windows (Ctrl+V)
- Large paste content (>8 bytes) is handled without truncation
- Terminal state is properly restored after session ends (bracketed paste disabled)
- Unit tests added for paste event handling
Technical Considerations
-
SmallVec capacity: The current
SmallVec<[u8; 8]>may not be sufficient for paste operations. Consider:- Increasing capacity (e.g.,
SmallVec<[u8; 64]>) - Using
Cow<'static, [u8]>for zero-copy small sequences - Changing return type to
Vec<u8>for paste events specifically
- Increasing capacity (e.g.,
-
Performance: Paste operations can involve large amounts of text. Ensure efficient memory handling to avoid unnecessary allocations.
-
Security: Be aware of paste-jacking attacks. Consider adding optional paste confirmation for multi-line or large pastes in future iterations.
Affected Files
src/pty/terminal.rs- Enable/disable bracketed paste modesrc/pty/session/input.rs- HandleEvent::Pasteevents
Additional Context
- crossterm documentation: https://docs.rs/crossterm/latest/crossterm/event/struct.EnableBracketedPaste.html
- Bracketed paste mode: https://cirw.in/blog/bracketed-paste