mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
fix: let Ctrl+D pass through as EOF on Windows/Linux (#599)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
7cdc866f96
commit
b1a10c7ef2
@@ -36,7 +36,7 @@ const SHORTCUT_GROUP_DEFINITIONS: ShortcutGroupDefinition[] = [
|
||||
{
|
||||
action: 'Switch worktree',
|
||||
searchKeywords: ['shortcut', 'global', 'worktree', 'switch', 'jump'],
|
||||
keys: ({ mod, shift }) => mod === '⌘' ? [mod, 'J'] : [mod, shift, 'J']
|
||||
keys: ({ mod, shift }) => (mod === '⌘' ? [mod, 'J'] : [mod, shift, 'J'])
|
||||
},
|
||||
{
|
||||
action: 'Create worktree',
|
||||
@@ -131,12 +131,16 @@ const SHORTCUT_GROUP_DEFINITIONS: ShortcutGroupDefinition[] = [
|
||||
{
|
||||
action: 'Split pane right',
|
||||
searchKeywords: ['shortcut', 'pane', 'split'],
|
||||
keys: ({ mod }) => [mod, 'D']
|
||||
// Why: on Windows/Linux, Ctrl+D must pass through as EOF (#586),
|
||||
// so split-right requires Shift on non-Mac platforms.
|
||||
keys: ({ mod, shift }) => (mod === '⌘' ? [mod, 'D'] : [mod, shift, 'D'])
|
||||
},
|
||||
{
|
||||
action: 'Split pane down',
|
||||
searchKeywords: ['shortcut', 'pane', 'split'],
|
||||
keys: ({ mod, shift }) => [mod, shift, 'D']
|
||||
// Why: on Windows/Linux, Ctrl+Shift+D is taken by split-right (#586),
|
||||
// so split-down uses Alt+Shift+D following Windows Terminal convention.
|
||||
keys: ({ mod, shift }) => (mod === '⌘' ? [mod, shift, 'D'] : ['Alt', shift, 'D'])
|
||||
},
|
||||
{
|
||||
action: 'Close pane (EOF)',
|
||||
|
||||
@@ -105,12 +105,16 @@ export default function TerminalContextMenu({
|
||||
<DropdownMenuItem onSelect={onSplitRight}>
|
||||
<PanelRightOpen />
|
||||
Split Right
|
||||
<DropdownMenuShortcut>{mod}D</DropdownMenuShortcut>
|
||||
{/* Why: on Windows/Linux, Ctrl+D must pass through as EOF (#586),
|
||||
so split-right requires Shift on non-Mac platforms. */}
|
||||
<DropdownMenuShortcut>{isMac ? `${mod}D` : `${mod}${shift}D`}</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onSelect={onSplitDown}>
|
||||
<PanelBottomOpen />
|
||||
Split Down
|
||||
<DropdownMenuShortcut>{`${mod}${shift}D`}</DropdownMenuShortcut>
|
||||
{/* Why: on Windows/Linux, Alt+Shift+D is used for split-down because
|
||||
Ctrl+Shift+D is taken by split-right (#586). */}
|
||||
<DropdownMenuShortcut>{isMac ? `${mod}${shift}D` : `Alt+${shift}D`}</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
{canExpandPane && (
|
||||
<DropdownMenuItem onSelect={onToggleExpand}>
|
||||
|
||||
@@ -106,4 +106,53 @@ describe('resolveTerminalShortcutAction', () => {
|
||||
resolveTerminalShortcutAction(event({ key: 'r', code: 'KeyR', ctrlKey: true }), false)
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('lets Ctrl+D pass through as EOF on non-Mac, requires Shift for split (#586)', () => {
|
||||
// Ctrl+D without Shift on Windows/Linux must NOT trigger split — it's EOF
|
||||
expect(
|
||||
resolveTerminalShortcutAction(event({ key: 'd', code: 'KeyD', ctrlKey: true }), false)
|
||||
).toBeNull()
|
||||
|
||||
// Ctrl+Shift+D on Windows/Linux splits the pane right (vertical)
|
||||
expect(
|
||||
resolveTerminalShortcutAction(
|
||||
event({ key: 'd', code: 'KeyD', ctrlKey: true, shiftKey: true }),
|
||||
false
|
||||
)
|
||||
).toEqual({ type: 'splitActivePane', direction: 'vertical' })
|
||||
|
||||
// Alt+Shift+D on Windows/Linux splits the pane down (horizontal)
|
||||
expect(
|
||||
resolveTerminalShortcutAction(
|
||||
event({ key: 'd', code: 'KeyD', altKey: true, shiftKey: true }),
|
||||
false
|
||||
)
|
||||
).toEqual({ type: 'splitActivePane', direction: 'horizontal' })
|
||||
|
||||
// Alt+Shift+D should NOT trigger split-down on Mac (Mac uses Cmd+Shift+D)
|
||||
expect(
|
||||
resolveTerminalShortcutAction(
|
||||
event({ key: 'd', code: 'KeyD', altKey: true, shiftKey: true }),
|
||||
true
|
||||
)
|
||||
).toBeNull()
|
||||
|
||||
// Alt+D (no Shift) on Windows/Linux must pass through for readline forward-word-delete
|
||||
expect(
|
||||
resolveTerminalShortcutAction(event({ key: 'd', code: 'KeyD', altKey: true }), false)
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('keeps Cmd+D and Cmd+Shift+D for split on macOS', () => {
|
||||
expect(
|
||||
resolveTerminalShortcutAction(event({ key: 'd', code: 'KeyD', metaKey: true }), true)
|
||||
).toEqual({ type: 'splitActivePane', direction: 'vertical' })
|
||||
|
||||
expect(
|
||||
resolveTerminalShortcutAction(
|
||||
event({ key: 'd', code: 'KeyD', metaKey: true, shiftKey: true }),
|
||||
true
|
||||
)
|
||||
).toEqual({ type: 'splitActivePane', direction: 'horizontal' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -58,13 +58,39 @@ export function resolveTerminalShortcutAction(
|
||||
}
|
||||
|
||||
if (lowerKey === 'd') {
|
||||
return {
|
||||
type: 'splitActivePane',
|
||||
direction: event.shiftKey ? 'horizontal' : 'vertical'
|
||||
if (isMac) {
|
||||
return {
|
||||
type: 'splitActivePane',
|
||||
direction: event.shiftKey ? 'horizontal' : 'vertical'
|
||||
}
|
||||
}
|
||||
// Why: on Windows/Linux, Ctrl+D is the standard EOF signal for terminals.
|
||||
// Binding Ctrl+D to split-pane would swallow EOF and break shell workflows
|
||||
// (see #586). Only Ctrl+Shift+D triggers split on non-Mac platforms;
|
||||
// Ctrl+D (without Shift) falls through to the terminal as normal input.
|
||||
if (event.shiftKey) {
|
||||
return { type: 'splitActivePane', direction: 'vertical' }
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// Why: on Windows/Linux, Alt+Shift+D splits the pane down (horizontal).
|
||||
// This lives outside the mod+!alt block above because it uses Alt instead
|
||||
// of Ctrl, following the Windows Terminal convention for split shortcuts
|
||||
// and avoiding the Ctrl+D / EOF conflict (see #586).
|
||||
if (
|
||||
!isMac &&
|
||||
!event.repeat &&
|
||||
!event.metaKey &&
|
||||
!event.ctrlKey &&
|
||||
event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.key.toLowerCase() === 'd'
|
||||
) {
|
||||
return { type: 'splitActivePane', direction: 'horizontal' }
|
||||
}
|
||||
|
||||
if (
|
||||
!event.metaKey &&
|
||||
!event.ctrlKey &&
|
||||
|
||||
Reference in New Issue
Block a user