fix(tui): fix Linux Ctrl+C regression, remove double clipboard write

- Fix critical regression: on Linux, Ctrl+C could not interrupt/clear/exit
  because isAction(key,'c') shadowed the isCtrl block (both resolve to k.ctrl
  on non-macOS). Restructured: isAction block now falls through to interrupt
  logic on non-macOS when no selection exists.
- Remove double pbcopy: ink's copySelection() already calls setClipboard()
  which handles pbcopy+tmux+OSC52. The extra writeClipboardText call in
  useInputHandlers copySelection() was firing pbcopy a second time.
- Remove allowClipboardHotkeys prop from TextInput — every caller passed
  isMac, and TextInput already imports isMac. Eliminated prop-drilling
  through appLayout, maskedPrompt, and prompts.
- Remove dead code: the isCtrl copy paths (lines 277-288) were unreachable
  on any platform after the isAction block changes.
- Simplify textInput Cmd+C: use writeClipboardText directly without the
  redundant OSC52 fallback (this path is macOS-only where pbcopy works).
This commit is contained in:
kshitijk4poor 2026-04-20 14:15:57 +05:30 committed by kshitij
parent e388910fe6
commit b7e71fb727
5 changed files with 18 additions and 51 deletions

View file

@ -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({
<Box flexGrow={1} position="relative">
<TextInput
columns={Math.max(20, composer.cols - pw)}
allowClipboardHotkeys={isMac}
onChange={composer.updateInput}
onPaste={composer.handleTextPaste}
onSubmit={composer.submit}

View file

@ -2,7 +2,6 @@ import { Box, Text } from '@hermes/ink'
import { useState } from 'react'
import type { Theme } from '../theme.js'
import { isMac } from '../lib/platform.js'
import { TextInput } from './textInput.js'
@ -19,7 +18,7 @@ export function MaskedPrompt({ cols = 80, icon, label, onSubmit, sub, t }: Maske
<Box>
<Text color={t.color.label}>{'> '}</Text>
<TextInput columns={Math.max(20, cols - 6)} allowClipboardHotkeys={isMac} mask="*" onChange={setValue} onSubmit={onSubmit} value={value} />
<TextInput columns={Math.max(20, cols - 6)} mask="*" onChange={setValue} onSubmit={onSubmit} value={value} />
</Box>
</Box>
)

View file

@ -126,7 +126,7 @@ export function ClarifyPrompt({ cols = 80, onAnswer, onCancel, req, t }: Clarify
<Box>
<Text color={t.color.label}>{'> '}</Text>
<TextInput columns={Math.max(20, cols - 6)} allowClipboardHotkeys={isMac} onChange={setCustom} onSubmit={onAnswer} value={custom} />
<TextInput columns={Math.max(20, cols - 6)} onChange={setCustom} onSubmit={onAnswer} value={custom} />
</Box>
<Text color={t.color.dim}>

View file

@ -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