diff --git a/ui-tui/src/app/useInputHandlers.ts b/ui-tui/src/app/useInputHandlers.ts index 83fd3385e4..be2e5379e9 100644 --- a/ui-tui/src/app/useInputHandlers.ts +++ b/ui-tui/src/app/useInputHandlers.ts @@ -8,8 +8,6 @@ import type { VoiceRecordResponse } from '../gatewayTypes.js' -import { writeClipboardText } from '../lib/clipboard.js' -import { writeOsc52Clipboard } from '../lib/osc52.js' import { isAction, isMac } from '../lib/platform.js' import { getInputSelection } from './inputSelectionStore.js' @@ -30,19 +28,13 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult { const pagerPageSize = Math.max(5, (terminal.stdout?.rows ?? 24) - 6) const copySelection = () => { + // ink's copySelection() already calls setClipboard() which handles + // pbcopy (macOS), wl-copy/xclip (Linux), tmux, and OSC 52 fallback. const text = terminal.selection.copySelection() - if (!text) { - return + if (text) { + actions.sys(`copied ${text.length} chars`) } - - void writeClipboardText(text).then(copied => { - if (!copied) { - writeOsc52Clipboard(text) - } - }) - - actions.sys(`copied ${text.length} chars`) } const clearSelection = () => { @@ -259,34 +251,19 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult { const inputSel = getInputSelection() if (inputSel && inputSel.end > inputSel.start) { - const text = inputSel.value.slice(inputSel.start, inputSel.end) - - void writeClipboardText(text).then(copied => { - if (!copied) { - writeOsc52Clipboard(text) - } - }) - - inputSel.clear() - } - - return - } - - if (isCtrl(key, ch, 'c')) { - if (!isMac && terminal.hasSelection) { - return copySelection() - } - - const inputSel = getInputSelection() - - if (!isMac && inputSel && inputSel.end > inputSel.start) { - writeOsc52Clipboard(inputSel.value.slice(inputSel.start, inputSel.end)) inputSel.clear() return } + // On macOS, Cmd+C with no selection is a no-op (Ctrl+C below handles interrupt). + // On non-macOS, isAction uses Ctrl, so fall through to interrupt/clear/exit. + if (isMac) { + return + } + } + + if (key.ctrl && ch.toLowerCase() === 'c') { if (live.busy && live.sid) { return turnController.interruptTurn({ appendMessage: actions.appendMessage, diff --git a/ui-tui/src/components/appLayout.tsx b/ui-tui/src/components/appLayout.tsx index e1a4b558a4..f13adf1bbd 100644 --- a/ui-tui/src/components/appLayout.tsx +++ b/ui-tui/src/components/appLayout.tsx @@ -6,7 +6,6 @@ import type { AppLayoutProgressProps, AppLayoutProps } from '../app/interfaces.j import { $isBlocked } from '../app/overlayStore.js' import { $uiState } from '../app/uiStore.js' import { PLACEHOLDER } from '../content/placeholders.js' -import { isMac } from '../lib/platform.js' import type { Theme } from '../theme.js' import type { DetailsMode } from '../types.js' @@ -236,7 +235,6 @@ const ComposerPane = memo(function ComposerPane({ {'> '} - + ) diff --git a/ui-tui/src/components/prompts.tsx b/ui-tui/src/components/prompts.tsx index 97c7c02868..967634d41f 100644 --- a/ui-tui/src/components/prompts.tsx +++ b/ui-tui/src/components/prompts.tsx @@ -126,7 +126,7 @@ export function ClarifyPrompt({ cols = 80, onAnswer, onCancel, req, t }: Clarify {'> '} - + diff --git a/ui-tui/src/components/textInput.tsx b/ui-tui/src/components/textInput.tsx index 1d16bb21a4..d3529df31c 100644 --- a/ui-tui/src/components/textInput.tsx +++ b/ui-tui/src/components/textInput.tsx @@ -5,7 +5,6 @@ import { useEffect, useMemo, useRef, useState } from 'react' import { setInputSelection } from '../app/inputSelectionStore.js' import { readClipboardText, writeClipboardText } from '../lib/clipboard.js' import { isActionMod, isMac } from '../lib/platform.js' -import { writeOsc52Clipboard } from '../lib/osc52.js' type InkExt = typeof Ink & { stringWidth: (s: string) => number @@ -282,7 +281,6 @@ export function TextInput({ onChange, onPaste, onSubmit, - allowClipboardHotkeys = false, mask, placeholder = '', focus = true @@ -508,12 +506,12 @@ export function TextInput({ (inp: string, k: Key, event: InputEvent) => { const eventRaw = event.keypress.raw - if (eventRaw === '\x1bv' || eventRaw === '\x1bV' || eventRaw === '\x16' || (allowClipboardHotkeys && isMac && k.meta && inp.toLowerCase() === 'v')) { + if (eventRaw === '\x1bv' || eventRaw === '\x1bV' || eventRaw === '\x16' || (isMac && k.meta && inp.toLowerCase() === 'v')) { if (cbPaste.current) { return void emitPaste({ cursor: curRef.current, hotkey: true, text: '', value: vRef.current }) } - if (allowClipboardHotkeys) { + if (isMac) { void readClipboardText().then(text => { if (text) { pastePlainText(text) @@ -524,17 +522,13 @@ export function TextInput({ return } - if (allowClipboardHotkeys && isMac && k.meta && inp.toLowerCase() === 'c') { + if (isMac && k.meta && inp.toLowerCase() === 'c') { const range = selRange() if (range) { const text = vRef.current.slice(range.start, range.end) - void writeClipboardText(text).then(copied => { - if (!copied) { - writeOsc52Clipboard(text) - } - }) + void writeClipboardText(text) } return @@ -735,7 +729,6 @@ export interface PasteEvent { } interface TextInputProps { - allowClipboardHotkeys?: boolean columns?: number focus?: boolean mask?: string