diff options
| author | Ayesha Shafique <[email protected]> | 2025-08-04 00:53:24 +0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-08-03 19:53:24 +0000 |
| commit | 072d8ba2899f2601dad6d4b0333fdcb80555a7dd (patch) | |
| tree | a8333f75184889929b844c115c5fb93555abdf62 /packages/cli/src/ui/hooks/useReverseSearchCompletion.tsx | |
| parent | 03ed37d0dc2b5e2077b53073517abaab3d24d9c2 (diff) | |
feat: Add reverse search capability for shell commands (#4793)
Diffstat (limited to 'packages/cli/src/ui/hooks/useReverseSearchCompletion.tsx')
| -rw-r--r-- | packages/cli/src/ui/hooks/useReverseSearchCompletion.tsx | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/packages/cli/src/ui/hooks/useReverseSearchCompletion.tsx b/packages/cli/src/ui/hooks/useReverseSearchCompletion.tsx new file mode 100644 index 00000000..1cc7e602 --- /dev/null +++ b/packages/cli/src/ui/hooks/useReverseSearchCompletion.tsx @@ -0,0 +1,91 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { useEffect, useCallback } from 'react'; +import { useCompletion } from './useCompletion.js'; +import { TextBuffer } from '../components/shared/text-buffer.js'; +import { Suggestion } from '../components/SuggestionsDisplay.js'; + +export interface UseReverseSearchCompletionReturn { + suggestions: Suggestion[]; + activeSuggestionIndex: number; + visibleStartIndex: number; + showSuggestions: boolean; + isLoadingSuggestions: boolean; + navigateUp: () => void; + navigateDown: () => void; + handleAutocomplete: (i: number) => void; + resetCompletionState: () => void; +} + +export function useReverseSearchCompletion( + buffer: TextBuffer, + shellHistory: readonly string[], + reverseSearchActive: boolean, +): UseReverseSearchCompletionReturn { + const { + suggestions, + activeSuggestionIndex, + visibleStartIndex, + showSuggestions, + isLoadingSuggestions, + + setSuggestions, + setShowSuggestions, + setActiveSuggestionIndex, + resetCompletionState, + navigateUp, + navigateDown, + } = useCompletion(); + + // whenever reverseSearchActive is on, filter history + useEffect(() => { + if (!reverseSearchActive) { + resetCompletionState(); + return; + } + const q = buffer.text.toLowerCase(); + const matches = shellHistory.reduce<Suggestion[]>((acc, cmd) => { + const idx = cmd.toLowerCase().indexOf(q); + if (idx !== -1) { + acc.push({ label: cmd, value: cmd, matchedIndex: idx }); + } + return acc; + }, []); + setSuggestions(matches); + setShowSuggestions(matches.length > 0); + setActiveSuggestionIndex(matches.length > 0 ? 0 : -1); + }, [ + buffer.text, + shellHistory, + reverseSearchActive, + resetCompletionState, + setActiveSuggestionIndex, + setShowSuggestions, + setSuggestions, + ]); + + const handleAutocomplete = useCallback( + (i: number) => { + if (i < 0 || i >= suggestions.length) return; + buffer.setText(suggestions[i].value); + resetCompletionState(); + }, + [buffer, suggestions, resetCompletionState], + ); + + return { + suggestions, + activeSuggestionIndex, + visibleStartIndex, + showSuggestions, + isLoadingSuggestions, + navigateUp, + navigateDown, + handleAutocomplete, + resetCompletionState, + }; +} |
