source dump of claude code
at main 63 lines 2.6 kB view raw
1import { 2 type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 3 logEvent, 4} from '../services/analytics/index.js' 5import { loadKeybindingsSync } from './loadUserBindings.js' 6import { getBindingDisplayText } from './resolver.js' 7import type { KeybindingContextName } from './types.js' 8 9// TODO(keybindings-migration): Remove fallback parameter after migration is 10// complete and we've confirmed no 'keybinding_fallback_used' events are being 11// logged. The fallback exists as a safety net during migration - if bindings 12// fail to load or an action isn't found, we fall back to hardcoded values. 13// Once stable, callers should be able to trust that getBindingDisplayText 14// always returns a value for known actions, and we can remove this defensive 15// pattern. 16 17// Track which action+context pairs have already logged a fallback event 18// to avoid duplicate events from repeated calls in non-React contexts. 19const LOGGED_FALLBACKS = new Set<string>() 20 21/** 22 * Get the display text for a configured shortcut without React hooks. 23 * Use this in non-React contexts (commands, services, etc.). 24 * 25 * This lives in its own module (not useShortcutDisplay.ts) so that 26 * non-React callers like query/stopHooks.ts don't pull React into their 27 * module graph via the sibling hook. 28 * 29 * @param action - The action name (e.g., 'app:toggleTranscript') 30 * @param context - The keybinding context (e.g., 'Global') 31 * @param fallback - Fallback text if binding not found 32 * @returns The configured shortcut display text 33 * 34 * @example 35 * const expandShortcut = getShortcutDisplay('app:toggleTranscript', 'Global', 'ctrl+o') 36 * // Returns the user's configured binding, or 'ctrl+o' as default 37 */ 38export function getShortcutDisplay( 39 action: string, 40 context: KeybindingContextName, 41 fallback: string, 42): string { 43 const bindings = loadKeybindingsSync() 44 const resolved = getBindingDisplayText(action, context, bindings) 45 if (resolved === undefined) { 46 const key = `${action}:${context}` 47 if (!LOGGED_FALLBACKS.has(key)) { 48 LOGGED_FALLBACKS.add(key) 49 logEvent('tengu_keybinding_fallback_used', { 50 action: 51 action as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 52 context: 53 context as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 54 fallback: 55 fallback as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 56 reason: 57 'action_not_found' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 58 }) 59 } 60 return fallback 61 } 62 return resolved 63}