mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-06 02:37:05 +08:00
Compare commits
2 Commits
dependabot
...
bb/tui-cop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3b143c49c | ||
|
|
94953affa6 |
@@ -32,10 +32,10 @@ describe('platform action modifier', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('isCopyShortcut', () => {
|
describe('isCopyShortcut', () => {
|
||||||
it('keeps Ctrl+C as the local non-macOS copy chord', async () => {
|
it('keeps Ctrl+C as interrupt instead of local non-macOS copy', async () => {
|
||||||
const { isCopyShortcut } = await importPlatform('linux')
|
const { isCopyShortcut } = await importPlatform('linux')
|
||||||
|
|
||||||
expect(isCopyShortcut({ ctrl: true, meta: false, super: false }, 'c', {})).toBe(true)
|
expect(isCopyShortcut({ ctrl: true, meta: false, super: false }, 'c', {})).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('accepts client Cmd+C over SSH even when running on Linux', async () => {
|
it('accepts client Cmd+C over SSH even when running on Linux', async () => {
|
||||||
|
|||||||
@@ -357,9 +357,12 @@ export function useInputHandlers(ctx: InputHandlerContext): InputHandlerResult {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// On macOS, Cmd+C with no selection is a no-op (Ctrl+C below handles interrupt).
|
// Copy shortcuts with no selection are no-ops. Plain Ctrl+C below still
|
||||||
// On non-macOS, isAction uses Ctrl, so fall through to interrupt/clear/exit.
|
// handles interrupt/clear/exit; forwarded Cmd+C over SSH should not
|
||||||
if (isMac) {
|
// leak through to TextInput as a literal "c".
|
||||||
|
const plainCtrlC = key.ctrl && !key.meta && key.super !== true && ch.toLowerCase() === 'c'
|
||||||
|
|
||||||
|
if (isMac || !plainCtrlC) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import type {
|
|||||||
import { useGitBranch } from '../hooks/useGitBranch.js'
|
import { useGitBranch } from '../hooks/useGitBranch.js'
|
||||||
import { useVirtualHistory } from '../hooks/useVirtualHistory.js'
|
import { useVirtualHistory } from '../hooks/useVirtualHistory.js'
|
||||||
import { appendTranscriptMessage } from '../lib/messages.js'
|
import { appendTranscriptMessage } from '../lib/messages.js'
|
||||||
import { isMac } from '../lib/platform.js'
|
|
||||||
import { asRpcResult, rpcErrorMessage } from '../lib/rpc.js'
|
import { asRpcResult, rpcErrorMessage } from '../lib/rpc.js'
|
||||||
import { terminalParityHints } from '../lib/terminalParity.js'
|
import { terminalParityHints } from '../lib/terminalParity.js'
|
||||||
import { buildToolTrailLine, sameToolTrailGroup, toolTrailLabel } from '../lib/text.js'
|
import { buildToolTrailLine, sameToolTrailGroup, toolTrailLabel } from '../lib/text.js'
|
||||||
@@ -150,19 +149,15 @@ export function useMainApp(gw: GatewayClient) {
|
|||||||
selection.setSelectionBgColor(ui.theme.color.selectionBg)
|
selection.setSelectionBgColor(ui.theme.color.selectionBg)
|
||||||
}, [selection, ui.theme.color.selectionBg])
|
}, [selection, ui.theme.color.selectionBg])
|
||||||
|
|
||||||
// macOS Terminal.app does not forward Cmd+C to fullscreen TUIs that enable
|
// Terminals generally route native selection/copy around fullscreen TUIs
|
||||||
// mouse tracking, so the only reliable native-feeling path is iTerm-style
|
// until mouse tracking is enabled; then the app owns selection. Mirror
|
||||||
// copy-on-select: once a drag creates a stable TUI selection, write it to
|
// terminal copy-on-select behavior by writing stable TUI selections to the
|
||||||
// the system clipboard while keeping the highlight visible.
|
// clipboard while keeping the highlight visible.
|
||||||
//
|
//
|
||||||
// Subscribe directly via the ink selection bus (not useSyncExternalStore)
|
// Subscribe directly via the ink selection bus (not useSyncExternalStore)
|
||||||
// so React doesn't re-render MainApp on every drag-move tick. The version
|
// so React doesn't re-render MainApp on every drag-move tick. The version
|
||||||
// ref de-dupes against re-entrant notifications.
|
// ref de-dupes against re-entrant notifications.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isMac) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return selection.subscribe(() => {
|
return selection.subscribe(() => {
|
||||||
if (!selection.hasSelection()) {
|
if (!selection.hasSelection()) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,15 +5,19 @@ const paste = isMac ? 'Cmd' : 'Alt'
|
|||||||
|
|
||||||
const copyHotkeys: [string, string][] = isMac
|
const copyHotkeys: [string, string][] = isMac
|
||||||
? [
|
? [
|
||||||
|
['Mouse select', 'copy selection'],
|
||||||
['Cmd+C', 'copy selection'],
|
['Cmd+C', 'copy selection'],
|
||||||
['Ctrl+C', 'interrupt / clear draft / exit']
|
['Ctrl+C', 'interrupt / clear draft / exit']
|
||||||
]
|
]
|
||||||
: isRemoteShell()
|
: isRemoteShell()
|
||||||
? [
|
? [
|
||||||
['Cmd+C', 'copy selection when forwarded by the terminal'],
|
['Mouse select / Cmd+C', 'copy selection when forwarded by the terminal'],
|
||||||
['Ctrl+C', 'copy selection / interrupt / clear draft / exit']
|
['Ctrl+C', 'interrupt / clear draft / exit']
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
['Mouse select', 'copy selection'],
|
||||||
|
['Ctrl+C', 'interrupt / clear draft / exit']
|
||||||
]
|
]
|
||||||
: [['Ctrl+C', 'copy selection / interrupt / clear draft / exit']]
|
|
||||||
|
|
||||||
export const HOTKEYS: [string, string][] = [
|
export const HOTKEYS: [string, string][] = [
|
||||||
...copyHotkeys,
|
...copyHotkeys,
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
* as `key.meta`. Some macOS terminals also translate Cmd+Left/Right/Backspace
|
* as `key.meta`. Some macOS terminals also translate Cmd+Left/Right/Backspace
|
||||||
* into readline-style Ctrl+A/Ctrl+E/Ctrl+U before the app sees them.
|
* into readline-style Ctrl+A/Ctrl+E/Ctrl+U before the app sees them.
|
||||||
* On other platforms the action modifier is Ctrl.
|
* On other platforms the action modifier is Ctrl.
|
||||||
* Ctrl+C stays the interrupt key on macOS. On non-mac terminals it can also
|
* Ctrl+C stays the interrupt key on local terminals. Remote sessions can still
|
||||||
* copy an active TUI selection, matching common terminal selection behavior.
|
* accept client-forwarded Cmd+C for copying a TUI selection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const isMac = process.platform === 'darwin'
|
export const isMac = process.platform === 'darwin'
|
||||||
@@ -43,7 +43,7 @@ export const isCopyShortcut = (
|
|||||||
env: NodeJS.ProcessEnv = process.env
|
env: NodeJS.ProcessEnv = process.env
|
||||||
): boolean =>
|
): boolean =>
|
||||||
ch.toLowerCase() === 'c' &&
|
ch.toLowerCase() === 'c' &&
|
||||||
(isAction(key, ch, 'c') ||
|
((isMac && isAction(key, ch, 'c')) ||
|
||||||
(isRemoteShell(env) && (key.meta || key.super === true)) ||
|
(isRemoteShell(env) && (key.meta || key.super === true)) ||
|
||||||
// VS Code/Cursor/Windsurf terminal setup forwards Cmd+C as a CSI-u
|
// VS Code/Cursor/Windsurf terminal setup forwards Cmd+C as a CSI-u
|
||||||
// sequence with the super bit plus a benign ctrl bit. Accept that shape
|
// sequence with the super bit plus a benign ctrl bit. Accept that shape
|
||||||
|
|||||||
Reference in New Issue
Block a user