From 3bfce3fd2d07588ffd1e3d6fa301626632627cf9 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 31 Jul 2026 14:17:35 -0400 Subject: [PATCH] feat(tui): expand pasted text (#39920) --- packages/tui/src/component/prompt/index.tsx | 30 ++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/tui/src/component/prompt/index.tsx b/packages/tui/src/component/prompt/index.tsx index 525e384a976..d24d4cca37b 100644 --- a/packages/tui/src/component/prompt/index.tsx +++ b/packages/tui/src/component/prompt/index.tsx @@ -1168,6 +1168,19 @@ export function Prompt(props: PromptProps) { ) } + function expandPastedText(extmarkId: number) { + const extmark = input.extmarks.get(extmarkId) + const ref = store.extmarkToPart.get(extmarkId) + if (!extmark || ref?.type !== "pasted") return false + const part = store.prompt.pasted[ref.index] + if (!part) return false + + input.extmarks.delete(extmarkId) + input.setSelection(extmark.start, extmark.end) + input.insertText(part.text) + return true + } + async function pasteInputText(text: string) { const normalizedText = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n") const pastedContent = normalizedText.trim() @@ -1191,6 +1204,15 @@ export function Prompt(props: PromptProps) { const lineCount = (pastedContent.match(/\n/g)?.length ?? 0) + 1 if ((lineCount >= 3 || pastedContent.length > 150) && config.prompt?.paste !== "full") { + const extmark = input.extmarks.getAllForTypeId(promptPartTypeId).find((extmark) => { + const ref = store.extmarkToPart.get(extmark.id) + return ( + (extmark.end === input.cursorOffset || extmark.end + 1 === input.cursorOffset) && + ref?.type === "pasted" && + store.prompt.pasted[ref.index]?.text === pastedContent + ) + }) + if (extmark && expandPastedText(extmark.id)) return pasteText(pastedContent, `[Pasted ~${lineCount} lines]`) return } @@ -1425,8 +1447,14 @@ export function Prompt(props: PromptProps) { }, 0) }} onMouseDown={(r: MouseEvent) => { - if (props.disabled) return + if (props.disabled || r.button !== 0) return r.target?.focus() + const extmark = input.extmarks + .getAtOffset(input.cursorOffset) + .find((item) => store.extmarkToPart.get(item.id)?.type === "pasted") + if (!extmark || !expandPastedText(extmark.id)) return + r.preventDefault() + r.stopPropagation() }} focusedBackgroundColor="transparent" cursorColor={props.disabled ? theme.background.surface.offset : theme.text.default}