|
|
@@ -18,7 +18,7 @@ import { usePromptStash } from "./stash"
|
|
|
import { DialogStash } from "../dialog-stash"
|
|
|
import { type AutocompleteRef, Autocomplete } from "./autocomplete"
|
|
|
import { useCommandDialog } from "../dialog-command"
|
|
|
-import { useRenderer } from "@opentui/solid"
|
|
|
+import { useKeyboard, useRenderer } from "@opentui/solid"
|
|
|
import { Editor } from "@tui/util/editor"
|
|
|
import { useExit } from "../../context/exit"
|
|
|
import { Clipboard } from "../../util/clipboard"
|
|
|
@@ -356,6 +356,20 @@ export function Prompt(props: PromptProps) {
|
|
|
]
|
|
|
})
|
|
|
|
|
|
+ // Windows Terminal 1.25+ handles Ctrl+V on keydown when kitty events are
|
|
|
+ // enabled, but still reports the kitty key-release event. Probe on release.
|
|
|
+ if (process.platform === "win32") {
|
|
|
+ useKeyboard(
|
|
|
+ (evt) => {
|
|
|
+ if (!input.focused) return
|
|
|
+ if (evt.name === "v" && evt.ctrl && evt.eventType === "release") {
|
|
|
+ command.trigger("prompt.paste")
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { release: true },
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
const ref: PromptRef = {
|
|
|
get focused() {
|
|
|
return input.focused
|
|
|
@@ -850,10 +864,9 @@ export function Prompt(props: PromptProps) {
|
|
|
e.preventDefault()
|
|
|
return
|
|
|
}
|
|
|
- // Handle clipboard paste (Ctrl+V) - check for images first on Windows
|
|
|
- // This is needed because Windows terminal doesn't properly send image data
|
|
|
- // through bracketed paste, so we need to intercept the keypress and
|
|
|
- // directly read from clipboard before the terminal handles it
|
|
|
+ // Check clipboard for images before terminal-handled paste runs.
|
|
|
+ // This helps terminals that forward Ctrl+V to the app; Windows
|
|
|
+ // Terminal 1.25+ usually handles Ctrl+V before this path.
|
|
|
if (keybind.match("input_paste", e)) {
|
|
|
const content = await Clipboard.read()
|
|
|
if (content?.mime.startsWith("image/")) {
|
|
|
@@ -936,6 +949,9 @@ export function Prompt(props: PromptProps) {
|
|
|
// Replace CRLF first, then any remaining CR
|
|
|
const normalizedText = decodePasteBytes(event.bytes).replace(/\r\n/g, "\n").replace(/\r/g, "\n")
|
|
|
const pastedContent = normalizedText.trim()
|
|
|
+
|
|
|
+ // Windows Terminal <1.25 can surface image-only clipboard as an
|
|
|
+ // empty bracketed paste. Windows Terminal 1.25+ does not.
|
|
|
if (!pastedContent) {
|
|
|
command.trigger("prompt.paste")
|
|
|
return
|