File tree Expand file tree Collapse file tree 3 files changed +47
-3
lines changed
src/cli/cmd/tui/component/prompt Expand file tree Collapse file tree 3 files changed +47
-3
lines changed Original file line number Diff line number Diff line change @@ -30,6 +30,7 @@ import { DialogAlert } from "../../ui/dialog-alert"
3030import { useToast } from "../../ui/toast"
3131import { useKV } from "../../context/kv"
3232import { useTextareaKeybindings } from "../textarea-keybindings"
33+ import { resolvePastedContent } from "./paste"
3334
3435export type PromptProps = {
3536 sessionID ?: string
@@ -861,13 +862,15 @@ export function Prompt(props: PromptProps) {
861862 // Normalize line endings at the boundary
862863 // Windows ConPTY/Terminal often sends CR-only newlines in bracketed paste
863864 // Replace CRLF first, then any remaining CR
864- const normalizedText = event . text . replace ( / \r \n / g , "\n" ) . replace ( / \r / g , "\n" )
865- const pastedContent = normalizedText . trim ( )
866- if ( ! pastedContent ) {
865+ const resolvedContent = await resolvePastedContent ( event . text , Clipboard . read )
866+
867+ if ( ! resolvedContent ) {
867868 command . trigger ( "prompt.paste" )
868869 return
869870 }
870871
872+ const pastedContent = resolvedContent
873+
871874 // trim ' from the beginning and end of the pasted content. just
872875 // ' and nothing else
873876 const filepath = pastedContent . replace ( / ^ ' + | ' + $ / g, "" ) . replace ( / \\ / g, " " )
Original file line number Diff line number Diff line change 1+ import { Clipboard } from "../../util/clipboard"
2+
3+ export async function resolvePastedContent (
4+ eventText : string ,
5+ readClipboard : ( ) => Promise < Clipboard . Content | undefined > ,
6+ ) : Promise < string | undefined > {
7+ // Normalize and use paste payload when terminals supply text directly
8+ const normalized = eventText . replace ( / \r \n / g, "\n" ) . replace ( / \r / g, "\n" )
9+ const text = normalized . trim ( )
10+ if ( text ) return text
11+
12+ // Finder copy often yields empty paste events; fallback to clipboard text
13+ const clipboardContent = await readClipboard ( )
14+ const clipboardText = clipboardContent ?. mime . startsWith ( "text/" ) ? clipboardContent . data : undefined
15+ if ( ! clipboardText ) return
16+ return clipboardText . replace ( / \r \n / g, "\n" ) . replace ( / \r / g, "\n" ) . trim ( )
17+ }
Original file line number Diff line number Diff line change 1+ import { describe , expect , mock , test } from "bun:test"
2+ import { resolvePastedContent } from "../../../src/cli/cmd/tui/component/prompt/paste"
3+
4+ describe ( "resolvePastedContent" , ( ) => {
5+ test ( "returns normalized event text when present" , async ( ) => {
6+ const readClipboard = mock ( async ( ) => undefined )
7+ const result = await resolvePastedContent ( " Hello\r\nWorld " , readClipboard )
8+ expect ( result ) . toBe ( "Hello\nWorld" )
9+ expect ( readClipboard . mock . calls . length ) . toBe ( 0 )
10+ } )
11+
12+ test ( "falls back to clipboard text when event text is empty" , async ( ) => {
13+ const readClipboard = mock ( async ( ) => ( { data : " clipboard text " , mime : "text/plain" } ) )
14+ const result = await resolvePastedContent ( "" , readClipboard )
15+ expect ( result ) . toBe ( "clipboard text" )
16+ expect ( readClipboard . mock . calls . length ) . toBe ( 1 )
17+ } )
18+
19+ test ( "returns undefined when clipboard lacks text content" , async ( ) => {
20+ const readClipboard = mock ( async ( ) => ( { data : "ignored" , mime : "image/png" } ) )
21+ const result = await resolvePastedContent ( "" , readClipboard )
22+ expect ( result ) . toBeUndefined ( )
23+ } )
24+ } )
You can’t perform that action at this time.
0 commit comments