From dbf4c3a37c55b8e14c9fefd1f839d3555072e17b Mon Sep 17 00:00:00 2001 From: Evan Senter Date: Fri, 18 Apr 2025 18:29:27 +0100 Subject: Revert "Including a test harness for it, and making sure the cursor is always at the end." This reverts commit 97db77997fd6369031d2f1cf750051999fb0b5b5. --- packages/cli/src/ui/App.tsx | 96 ++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 37 deletions(-) (limited to 'packages/cli/src/ui/App.tsx') diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx index 5a88c90b..cda748f4 100644 --- a/packages/cli/src/ui/App.tsx +++ b/packages/cli/src/ui/App.tsx @@ -1,12 +1,11 @@ import React, { useState, useEffect, useMemo } from 'react'; -import { Box, Text } from 'ink'; +import { Box, Text, useInput } from 'ink'; import fs from 'fs'; import path from 'path'; import os from 'os'; import type { HistoryItem } from './types.js'; import { useGeminiStream } from './hooks/useGeminiStream.js'; import { useLoadingIndicator } from './hooks/useLoadingIndicator.js'; -import { useInputHistory } from './hooks/useInputHistory.js'; import Header from './components/Header.js'; import Tips from './components/Tips.js'; import HistoryDisplay from './components/HistoryDisplay.js'; @@ -23,8 +22,11 @@ interface AppProps { } const App = ({ directory }: AppProps) => { + const [query, setQuery] = useState(''); const [history, setHistory] = useState([]); const [startupWarnings, setStartupWarnings] = useState([]); + const [historyIndex, setHistoryIndex] = useState(-1); + const [originalQueryBeforeNav, setOriginalQueryBeforeNav] = useState(''); const { streamingState, submitQuery, initError } = useGeminiStream(setHistory); const { elapsedTime, currentLoadingPhrase } = @@ -32,54 +34,34 @@ const App = ({ directory }: AppProps) => { const userMessages = useMemo(() => { return history - .filter( - (item): item is HistoryItem & { type: 'user'; text: string } => - item.type === 'user' && - typeof item.text === 'string' && - item.text.trim() !== '', - ) - .map((item) => item.text); + .filter((item): item is HistoryItem & { type: 'user'; text: string } => + item.type === 'user' && typeof item.text === 'string' && item.text.trim() !== '' + ) + .map(item => item.text); }, [history]); useEffect(() => { try { if (fs.existsSync(warningsFilePath)) { + console.log('[App] Found warnings file:', warningsFilePath); const warningsContent = fs.readFileSync(warningsFilePath, 'utf-8'); - setStartupWarnings( - warningsContent.split('\n').filter((line) => line.trim() !== ''), - ); + setStartupWarnings(warningsContent.split('\n').filter(line => line.trim() !== '')); try { - fs.unlinkSync(warningsFilePath); + fs.unlinkSync(warningsFilePath); } catch (unlinkErr: any) { - console.warn( - `[App] Warning: Could not delete warnings file: ${unlinkErr.message}`, - ); + console.warn(`[App] Warning: Could not delete warnings file: ${unlinkErr.message}`); } + } else { + console.log('[App] No warnings file found.'); } } catch (err: any) { - console.error( - `[App] Error checking/reading warnings file: ${err.message}`, - ); + console.error(`[App] Error checking/reading warnings file: ${err.message}`); } }, []); - const isWaitingForToolConfirmation = history.some( - (item) => - item.type === 'tool_group' && - item.tools.some((tool) => tool.confirmationDetails !== undefined), - ); - const isInputActive = - streamingState === StreamingState.Idle && - !initError && - !isWaitingForToolConfirmation; - - const { query, setQuery, resetHistoryNav, inputKey } = useInputHistory({ - userMessages, - isActive: isInputActive, - }); - const handleInputSubmit = (value: PartListUnion) => { - resetHistoryNav(); + setHistoryIndex(-1); + setOriginalQueryBeforeNav(''); submitQuery(value) .then(() => { setQuery(''); @@ -107,6 +89,47 @@ const App = ({ directory }: AppProps) => { } }, [initError, history]); + const isWaitingForToolConfirmation = history.some( + (item) => + item.type === 'tool_group' && + item.tools.some((tool) => tool.confirmationDetails !== undefined), + ); + const isInputActive = streamingState === StreamingState.Idle && !initError; + + useInput((input, key) => { + if (!isInputActive || isWaitingForToolConfirmation) { + return; + } + + if (key.upArrow) { + if (userMessages.length === 0) return; + if (historyIndex === -1) { + setOriginalQueryBeforeNav(query); + } + const nextIndex = Math.min(historyIndex + 1, userMessages.length - 1); + if (nextIndex !== historyIndex) { + setHistoryIndex(nextIndex); + setQuery(userMessages[userMessages.length - 1 - nextIndex]); + } + } else if (key.downArrow) { + if (historyIndex < 0) return; + const nextIndex = Math.max(historyIndex - 1, -1); + setHistoryIndex(nextIndex); + if (nextIndex === -1) { + setQuery(originalQueryBeforeNav); + } else { + setQuery(userMessages[userMessages.length - 1 - nextIndex]); + } + } else { + if (input || key.backspace || key.delete || key.leftArrow || key.rightArrow) { + if (historyIndex !== -1) { + setHistoryIndex(-1); + setOriginalQueryBeforeNav(''); + } + } + } + }, { isActive: isInputActive }); + return (
@@ -170,13 +193,12 @@ const App = ({ directory }: AppProps) => { /> - {!isWaitingForToolConfirmation && ( + {!isWaitingForToolConfirmation && isInputActive && ( )} -- cgit v1.2.3