summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks/useInputHistory.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/hooks/useInputHistory.ts')
-rw-r--r--packages/cli/src/ui/hooks/useInputHistory.ts92
1 files changed, 92 insertions, 0 deletions
diff --git a/packages/cli/src/ui/hooks/useInputHistory.ts b/packages/cli/src/ui/hooks/useInputHistory.ts
new file mode 100644
index 00000000..bdd02e36
--- /dev/null
+++ b/packages/cli/src/ui/hooks/useInputHistory.ts
@@ -0,0 +1,92 @@
+import { useState, useCallback } from 'react';
+import { useInput } from 'ink';
+
+interface UseInputHistoryProps {
+ userMessages: readonly string[]; // Use readonly string[] instead
+ isActive: boolean; // To enable/disable the useInput hook
+}
+
+interface UseInputHistoryReturn {
+ query: string;
+ setQuery: React.Dispatch<React.SetStateAction<string>>;
+ resetHistoryNav: () => void;
+ inputKey: number; // Key to force input reset
+}
+
+export function useInputHistory({
+ userMessages,
+ isActive,
+}: UseInputHistoryProps): UseInputHistoryReturn {
+ const [query, setQuery] = useState('');
+ const [historyIndex, setHistoryIndex] = useState<number>(-1); // -1 means current query
+ const [originalQueryBeforeNav, setOriginalQueryBeforeNav] =
+ useState<string>('');
+ const [inputKey, setInputKey] = useState<number>(0); // Add key state
+
+ const resetHistoryNav = useCallback(() => {
+ setHistoryIndex(-1);
+ setOriginalQueryBeforeNav('');
+ // Don't reset inputKey here, only on explicit nav actions
+ }, []);
+
+ useInput(
+ (input, key) => {
+ // Do nothing if the hook is not active
+ if (!isActive) {
+ return;
+ }
+
+ if (key.upArrow) {
+ if (userMessages.length === 0) return;
+ // Store current query if starting navigation
+ if (historyIndex === -1) {
+ setOriginalQueryBeforeNav(query);
+ }
+ const nextIndex = Math.min(historyIndex + 1, userMessages.length - 1);
+ if (nextIndex !== historyIndex) {
+ setHistoryIndex(nextIndex);
+ const newValue = userMessages[userMessages.length - 1 - nextIndex];
+ setQuery(newValue);
+ setInputKey(k => k + 1); // Increment key on navigation change
+ }
+ } else if (key.downArrow) {
+ if (historyIndex < 0) return; // Already at the bottom
+ const nextIndex = Math.max(historyIndex - 1, -1);
+ setHistoryIndex(nextIndex);
+ if (nextIndex === -1) {
+ // Restore original query
+ setQuery(originalQueryBeforeNav);
+ setInputKey(k => k + 1); // Increment key on navigation change
+ } else {
+ // Set query based on reversed index
+ const newValue = userMessages[userMessages.length - 1 - nextIndex];
+ setQuery(newValue);
+ setInputKey(k => k + 1); // Increment key on navigation change
+ }
+ } else {
+ // If user types anything other than arrows, reset history navigation state
+ // This check might be too broad, adjust if handling more special keys
+ if (
+ input ||
+ key.backspace ||
+ key.delete ||
+ key.leftArrow ||
+ key.rightArrow
+ ) {
+ if (historyIndex !== -1) {
+ resetHistoryNav();
+ // Note: The actual input change is handled by the component using setQuery/onChange
+ }
+ }
+ }
+ },
+ { isActive }, // Pass isActive to useInput
+ );
+
+ return {
+ query,
+ setQuery, // Return setQuery directly for flexibility
+ resetHistoryNav,
+ inputKey, // Return the key
+ };
+}