mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-22 00:05:51 +00:00
feat: 将 keybinding 纳入 ink 管辖
This commit is contained in:
@@ -4,7 +4,7 @@ import {
|
||||
useExitOnCtrlCDWithKeybindings,
|
||||
} from '../hooks/useExitOnCtrlCD.js'
|
||||
import { Box, Text } from '../index.js'
|
||||
import { useKeybinding } from './keybindings.js'
|
||||
import { useKeybinding } from '../keybindings/useKeybinding.js'
|
||||
import type { Theme } from './theme-types.js'
|
||||
import { ConfigurableShortcutHint } from './ConfigurableShortcutHint.js'
|
||||
import { Byline } from './Byline.js'
|
||||
|
||||
@@ -14,7 +14,7 @@ import ScrollBox from '../components/ScrollBox.js'
|
||||
import type { KeyboardEvent } from '../core/events/keyboard-event.js'
|
||||
import { stringWidth } from '../core/stringWidth.js'
|
||||
import { Box, Text } from '../index.js'
|
||||
import { useKeybindings } from './keybindings.js'
|
||||
import { useKeybindings } from '../keybindings/useKeybinding.js'
|
||||
import type { Theme } from './theme-types.js'
|
||||
|
||||
type TabsProps = {
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* Minimal stub of the keybinding system for the standalone @anthropic/ink package.
|
||||
*
|
||||
* The full keybinding system (src/keybindings/) depends on KeybindingContext,
|
||||
* KeybindingRegistry, and chord handling. This stub provides the same hook
|
||||
* interfaces (useKeybinding / useKeybindings) but routes directly through
|
||||
* useInput, matching common key sequences to action names.
|
||||
*
|
||||
* Only the keybindings used by theme components are mapped:
|
||||
* - confirm:no → Escape
|
||||
* - tabs:next → Tab / Right arrow
|
||||
* - tabs:previous → Shift+Tab / Left arrow
|
||||
*/
|
||||
|
||||
import { useCallback } from 'react'
|
||||
import useInput from '../hooks/use-input.js'
|
||||
import type { Key } from '../core/events/input-event.js'
|
||||
|
||||
type Options = {
|
||||
context?: string
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
/** Maps action names to key matching logic. */
|
||||
const ACTION_MATCHERS: Record<
|
||||
string,
|
||||
(input: string, key: Key) => boolean
|
||||
> = {
|
||||
'confirm:no': (_input, key) => key.escape === true,
|
||||
'tabs:next': (input, key) =>
|
||||
(key.tab && !key.shift) || (key.rightArrow && !key.shift),
|
||||
'tabs:previous': (_input, key) =>
|
||||
(key.tab && key.shift) || (key.leftArrow && !key.shift),
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a single keybinding action handler.
|
||||
*/
|
||||
export function useKeybinding(
|
||||
action: string,
|
||||
handler: () => void | false | Promise<void>,
|
||||
options: Options = {},
|
||||
): void {
|
||||
const { isActive = true } = options
|
||||
|
||||
const handleInput = useCallback(
|
||||
(input: string, key: Key) => {
|
||||
if (!isActive) return
|
||||
const matcher = ACTION_MATCHERS[action]
|
||||
if (matcher && matcher(input, key)) {
|
||||
if (handler() !== false) {
|
||||
// consumed
|
||||
}
|
||||
}
|
||||
},
|
||||
[action, handler, isActive],
|
||||
)
|
||||
|
||||
useInput(handleInput, { isActive })
|
||||
}
|
||||
|
||||
/**
|
||||
* Register multiple keybinding action handlers in one hook.
|
||||
*/
|
||||
export function useKeybindings(
|
||||
handlers: Record<string, () => void | false | Promise<void>>,
|
||||
options: Options = {},
|
||||
): void {
|
||||
const { isActive = true } = options
|
||||
|
||||
const handleInput = useCallback(
|
||||
(input: string, key: Key) => {
|
||||
if (!isActive) return
|
||||
for (const [action, handler] of Object.entries(handlers)) {
|
||||
const matcher = ACTION_MATCHERS[action]
|
||||
if (matcher && matcher(input, key)) {
|
||||
if (handler() !== false) {
|
||||
break // consumed, stop checking other handlers
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[handlers, isActive],
|
||||
)
|
||||
|
||||
useInput(handleInput, { isActive })
|
||||
}
|
||||
Reference in New Issue
Block a user