diff options
Diffstat (limited to 'packages/cli/src/ui/components/InputPrompt.tsx')
| -rw-r--r-- | packages/cli/src/ui/components/InputPrompt.tsx | 124 |
1 files changed, 3 insertions, 121 deletions
diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx index 6192fb8c..9f15b56d 100644 --- a/packages/cli/src/ui/components/InputPrompt.tsx +++ b/packages/cli/src/ui/components/InputPrompt.tsx @@ -10,13 +10,12 @@ import { Colors } from '../colors.js'; import { SuggestionsDisplay } from './SuggestionsDisplay.js'; import { useInputHistory } from '../hooks/useInputHistory.js'; import { TextBuffer } from './shared/text-buffer.js'; -import { cpSlice, cpLen, toCodePoints } from '../utils/textUtils.js'; +import { cpSlice, cpLen } from '../utils/textUtils.js'; import chalk from 'chalk'; import stringWidth from 'string-width'; import { useShellHistory } from '../hooks/useShellHistory.js'; import { useCompletion } from '../hooks/useCompletion.js'; import { useKeypress, Key } from '../hooks/useKeypress.js'; -import { isAtCommand, isSlashCommand } from '../utils/commandUtils.js'; import { CommandContext, SlashCommand } from '../commands/types.js'; import { Config } from '@google/gemini-cli-core'; import { @@ -59,53 +58,9 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ }) => { const [justNavigatedHistory, setJustNavigatedHistory] = useState(false); - // Check if cursor is after @ or / without unescaped spaces - const isCursorAfterCommandWithoutSpace = useCallback(() => { - const [row, col] = buffer.cursor; - const currentLine = buffer.lines[row] || ''; - - // Convert current line to code points for Unicode-aware processing - const codePoints = toCodePoints(currentLine); - - // Search backwards from cursor position within the current line only - for (let i = col - 1; i >= 0; i--) { - const char = codePoints[i]; - - if (char === ' ') { - // Check if this space is escaped by counting backslashes before it - let backslashCount = 0; - for (let j = i - 1; j >= 0 && codePoints[j] === '\\'; j--) { - backslashCount++; - } - - // If there's an odd number of backslashes, the space is escaped - const isEscaped = backslashCount % 2 === 1; - - if (!isEscaped) { - // Found unescaped space before @ or /, return false - return false; - } - // If escaped, continue searching backwards - } else if (char === '@' || char === '/') { - // Found @ or / without unescaped space in between - return true; - } - } - - return false; - }, [buffer.cursor, buffer.lines]); - - const shouldShowCompletion = useCallback( - () => - (isAtCommand(buffer.text) || isSlashCommand(buffer.text)) && - isCursorAfterCommandWithoutSpace(), - [buffer.text, isCursorAfterCommandWithoutSpace], - ); - const completion = useCompletion( - buffer.text, + buffer, config.getTargetDir(), - shouldShowCompletion(), slashCommands, commandContext, config, @@ -159,78 +114,6 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ setJustNavigatedHistory, ]); - const completionSuggestions = completion.suggestions; - const handleAutocomplete = useCallback( - (indexToUse: number) => { - if (indexToUse < 0 || indexToUse >= completionSuggestions.length) { - return; - } - const query = buffer.text; - const suggestion = completionSuggestions[indexToUse].value; - - if (query.trimStart().startsWith('/')) { - const hasTrailingSpace = query.endsWith(' '); - const parts = query - .trimStart() - .substring(1) - .split(/\s+/) - .filter(Boolean); - - let isParentPath = false; - // If there's no trailing space, we need to check if the current query - // is already a complete path to a parent command. - if (!hasTrailingSpace) { - let currentLevel: readonly SlashCommand[] | undefined = slashCommands; - for (let i = 0; i < parts.length; i++) { - const part = parts[i]; - const found: SlashCommand | undefined = currentLevel?.find( - (cmd) => cmd.name === part || cmd.altNames?.includes(part), - ); - - if (found) { - if (i === parts.length - 1 && found.subCommands) { - isParentPath = true; - } - currentLevel = found.subCommands as - | readonly SlashCommand[] - | undefined; - } else { - // Path is invalid, so it can't be a parent path. - currentLevel = undefined; - break; - } - } - } - - // Determine the base path of the command. - // - If there's a trailing space, the whole command is the base. - // - If it's a known parent path, the whole command is the base. - // - Otherwise, the base is everything EXCEPT the last partial part. - const basePath = - hasTrailingSpace || isParentPath ? parts : parts.slice(0, -1); - const newValue = `/${[...basePath, suggestion].join(' ')}`; - - buffer.setText(newValue); - } else { - const atIndex = query.lastIndexOf('@'); - if (atIndex === -1) return; - const pathPart = query.substring(atIndex + 1); - const lastSlashIndexInPath = pathPart.lastIndexOf('/'); - let autoCompleteStartIndex = atIndex + 1; - if (lastSlashIndexInPath !== -1) { - autoCompleteStartIndex += lastSlashIndexInPath + 1; - } - buffer.replaceRangeByOffset( - autoCompleteStartIndex, - buffer.text.length, - suggestion, - ); - } - resetCompletionState(); - }, - [resetCompletionState, buffer, completionSuggestions, slashCommands], - ); - // Handle clipboard image pasting with Ctrl+V const handleClipboardImage = useCallback(async () => { try { @@ -337,7 +220,7 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ ? 0 // Default to the first if none is active : completion.activeSuggestionIndex; if (targetIndex < completion.suggestions.length) { - handleAutocomplete(targetIndex); + completion.handleAutocomplete(targetIndex); } } return; @@ -459,7 +342,6 @@ export const InputPrompt: React.FC<InputPromptProps> = ({ setShellModeActive, onClearScreen, inputHistory, - handleAutocomplete, handleSubmitAndClear, shellHistory, handleClipboardImage, |
