MCPcopy
hub / github.com/codeaashu/claude-code / useTypeahead

Function useTypeahead

src/hooks/useTypeahead.tsx:353–1384  ·  view source on GitHub ↗
({
  commands,
  onInputChange,
  onSubmit,
  setCursorOffset,
  input,
  cursorOffset,
  mode,
  agents,
  setSuggestionsState,
  suggestionsState: {
    suggestions,
    selectedSuggestion,
    commandArgumentHint
  },
  suppressSuggestions = false,
  markAccepted,
  onModeChange
}: Props)

Source from the content-addressed store, hash-verified

351 * Hook for handling typeahead functionality for both commands and file paths
352 */
353export function useTypeahead({
354 commands,
355 onInputChange,
356 onSubmit,
357 setCursorOffset,
358 input,
359 cursorOffset,
360 mode,
361 agents,
362 setSuggestionsState,
363 suggestionsState: {
364 suggestions,
365 selectedSuggestion,
366 commandArgumentHint
367 },
368 suppressSuggestions = false,
369 markAccepted,
370 onModeChange
371}: Props): UseTypeaheadResult {
372 const {
373 addNotification
374 } = useNotifications();
375 const thinkingToggleShortcut = useShortcutDisplay('chat:thinkingToggle', 'Chat', 'alt+t');
376 const [suggestionType, setSuggestionType] = useState<SuggestionType>('none');
377
378 // Compute max column width from ALL commands once (not filtered results)
379 // This prevents layout shift when filtering
380 const allCommandsMaxWidth = useMemo(() => {
381 const visibleCommands = commands.filter(cmd => !cmd.isHidden);
382 if (visibleCommands.length === 0) return undefined;
383 const maxLen = Math.max(...visibleCommands.map(cmd => getCommandName(cmd).length));
384 return maxLen + 6; // +1 for "/" prefix, +5 for padding
385 }, [commands]);
386 const [maxColumnWidth, setMaxColumnWidth] = useState<number | undefined>(undefined);
387 const mcpResources = useAppState(s => s.mcp.resources);
388 const store = useAppStateStore();
389 const promptSuggestion = useAppState(s => s.promptSuggestion);
390 // PromptInput hides suggestion ghost text in teammate view — mirror that
391 // gate here so Tab/rightArrow can't accept what isn't displayed.
392 const isViewingTeammate = useAppState(s => !!s.viewingAgentTaskId);
393
394 // Access keybinding context to check for pending chord sequences
395 const keybindingContext = useOptionalKeybindingContext();
396
397 // State for inline ghost text (bash history completion - async)
398 const [inlineGhostText, setInlineGhostText] = useState<InlineGhostText | undefined>(undefined);
399
400 // Synchronous ghost text for prompt mode mid-input slash commands.
401 // Computed during render via useMemo to eliminate the one-frame flicker
402 // that occurs when using useState + useEffect (effect runs after render).
403 const syncPromptGhostText = useMemo((): InlineGhostText | undefined => {
404 if (mode !== 'prompt' || suppressSuggestions) return undefined;
405 const midInputCommand = findMidInputSlashCommand(input, cursorOffset);
406 if (!midInputCommand) return undefined;
407 const match = getBestCommandMatch(midInputCommand.partialCommand, commands);
408 if (!match) return undefined;
409 return {
410 text: match.suffix,

Callers 1

PromptInputFunction · 0.85

Calls 15

useShortcutDisplayFunction · 0.85
useAppStateFunction · 0.85
useAppStateStoreFunction · 0.85
findMidInputSlashCommandFunction · 0.85
getBestCommandMatchFunction · 0.85
getPreservedSelectionFunction · 0.85
isAgentSwarmsEnabledFunction · 0.85

Tested by

no test coverage detected