diff --git a/src/ClaudeDo.Ui/Services/PtyTerminalSession.cs b/src/ClaudeDo.Ui/Services/PtyTerminalSession.cs index 82980292..597469df 100644 --- a/src/ClaudeDo.Ui/Services/PtyTerminalSession.cs +++ b/src/ClaudeDo.Ui/Services/PtyTerminalSession.cs @@ -137,6 +137,42 @@ public sealed class PtyTerminalSession : IDisposable } } + /// + /// Inserts at the cursor without submitting it — the drop-a-file-path + /// case. Same write seam as , just without the Enter. + /// + public async Task SendTextAsync(string text) + { + if (_control is not { } control || !IsRunning || string.IsNullOrEmpty(text)) return false; + try + { + await SendRawAsync(control, text); + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Pastes the clipboard into the session. wires paste to the + /// right-click menu only, so Ctrl+V otherwise reaches the child as a raw control byte and does + /// nothing. Goes through the emulator's own rather than + /// writing the clipboard text raw, because that is what honours bracketed-paste mode — without + /// it a multi-line paste is read line by line and submits on the first newline. + /// + public async Task PasteAsync() + { + if (_control is not { } control || !IsRunning) return; + try + { + if (s_terminalViewField?.GetValue(control) is TerminalView view) + await view.PasteAsync(); + } + catch (Exception) { /* best-effort, same as SendLineAsync */ } + } + // Long enough that the two writes can't be read as one chunk by the child's stdin reader. private static readonly TimeSpan SubmitDelay = TimeSpan.FromMilliseconds(150); diff --git a/src/ClaudeDo.Ui/ViewModels/InteractiveTerminalViewModel.cs b/src/ClaudeDo.Ui/ViewModels/InteractiveTerminalViewModel.cs index ca72e00c..b0fed886 100644 --- a/src/ClaudeDo.Ui/ViewModels/InteractiveTerminalViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/InteractiveTerminalViewModel.cs @@ -136,6 +136,14 @@ public sealed partial class InteractiveTerminalViewModel : ViewModelBase, IDispo /// type into (or the write seam is gone). public Task SendLineAsync(string text) => _session.SendLineAsync(text); + /// Inserts text at the cursor without submitting — see + /// (dropped file paths). + public Task SendTextAsync(string text) => _session.SendTextAsync(text); + + /// Pastes the clipboard into the session (Ctrl+V) — see + /// . + public Task PasteAsync() => _session.PasteAsync(); + public void Kill() => _session.Kill(); public void Dispose() diff --git a/src/ClaudeDo.Ui/Views/InteractiveTerminalView.axaml b/src/ClaudeDo.Ui/Views/InteractiveTerminalView.axaml index 8277ddbb..520972aa 100644 --- a/src/ClaudeDo.Ui/Views/InteractiveTerminalView.axaml +++ b/src/ClaudeDo.Ui/Views/InteractiveTerminalView.axaml @@ -4,7 +4,8 @@ xmlns:term="using:Iciclecreek.Terminal" x:Class="ClaudeDo.Ui.Views.InteractiveTerminalView" x:DataType="vm:InteractiveTerminalViewModel" - x:Name="Root"> + x:Name="Root" + DragDrop.AllowDrop="True">