From 7de790fbf236193191a33482793ee3ec5943d62d Mon Sep 17 00:00:00 2001 From: Marat Boshernitsan Date: Tue, 3 Jun 2025 23:01:26 -0700 Subject: Fix several bugs in prompt history (#734) Co-authored-by: Marat Boshernitsan --- packages/cli/src/ui/components/InputPrompt.tsx | 36 +++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'packages/cli/src/ui/components/InputPrompt.tsx') diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx index c131f5e0..7e4c8c8b 100644 --- a/packages/cli/src/ui/components/InputPrompt.tsx +++ b/packages/cli/src/ui/components/InputPrompt.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { Text, Box, useInput, useStdin } from 'ink'; import { Colors } from '../colors.js'; import { SuggestionsDisplay } from './SuggestionsDisplay.js'; @@ -19,7 +19,7 @@ import { isAtCommand, isSlashCommand } from '../utils/commandUtils.js'; import { SlashCommand } from '../hooks/slashCommandProcessor.js'; import { Config } from '@gemini-code/core'; -interface InputPromptProps { +export interface InputPromptProps { onSubmit: (value: string) => void; userMessages: readonly string[]; onClearScreen: () => void; @@ -54,6 +54,8 @@ export const InputPrompt: React.FC = ({ ); const suggestionsWidth = Math.max(60, Math.floor(terminalSize.columns * 0.8)); + const [justNavigatedHistory, setJustNavigatedHistory] = useState(false); + const { stdin, setRawMode } = useStdin(); const buffer = useTextBuffer({ @@ -84,14 +86,35 @@ export const InputPrompt: React.FC = ({ [onSubmit, buffer, resetCompletionState], ); + const customSetTextAndResetCompletionSignal = useCallback( + (newText: string) => { + buffer.setText(newText); + setJustNavigatedHistory(true); + }, + [buffer, setJustNavigatedHistory], + ); + const inputHistory = useInputHistory({ userMessages, onSubmit: handleSubmitAndClear, isActive: !completion.showSuggestions, currentQuery: buffer.text, - onChange: buffer.setText, + onChange: customSetTextAndResetCompletionSignal, }); + // Effect to reset completion if history navigation just occurred and set the text + useEffect(() => { + if (justNavigatedHistory) { + resetCompletionState(); + setJustNavigatedHistory(false); + } + }, [ + justNavigatedHistory, + buffer.text, + resetCompletionState, + setJustNavigatedHistory, + ]); + const completionSuggestions = completion.suggestions; const handleAutocomplete = useCallback( (indexToUse: number) => { @@ -276,8 +299,8 @@ export const InputPrompt: React.FC = ({ // Standard arrow navigation within the buffer if (key.upArrow && !completion.showSuggestions) { if ( - buffer.visualCursor[0] === 0 && - buffer.visualScrollRow === 0 && + (buffer.allVisualLines.length === 1 || // Always navigate for single line + (buffer.visualCursor[0] === 0 && buffer.visualScrollRow === 0)) && inputHistory.navigateUp ) { inputHistory.navigateUp(); @@ -288,7 +311,8 @@ export const InputPrompt: React.FC = ({ } if (key.downArrow && !completion.showSuggestions) { if ( - buffer.visualCursor[0] === buffer.allVisualLines.length - 1 && + (buffer.allVisualLines.length === 1 || // Always navigate for single line + buffer.visualCursor[0] === buffer.allVisualLines.length - 1) && inputHistory.navigateDown ) { inputHistory.navigateDown(); -- cgit v1.2.3