summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/hooks')
-rw-r--r--packages/cli/src/ui/hooks/useCompletion.test.ts2
-rw-r--r--packages/cli/src/ui/hooks/useCompletion.ts26
2 files changed, 27 insertions, 1 deletions
diff --git a/packages/cli/src/ui/hooks/useCompletion.test.ts b/packages/cli/src/ui/hooks/useCompletion.test.ts
index 7f2823c7..267bce13 100644
--- a/packages/cli/src/ui/hooks/useCompletion.test.ts
+++ b/packages/cli/src/ui/hooks/useCompletion.test.ts
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
+/** @vitest-environment jsdom */
+
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import type { Mocked } from 'vitest';
import { renderHook, act } from '@testing-library/react';
diff --git a/packages/cli/src/ui/hooks/useCompletion.ts b/packages/cli/src/ui/hooks/useCompletion.ts
index d3de5c6b..81acc992 100644
--- a/packages/cli/src/ui/hooks/useCompletion.ts
+++ b/packages/cli/src/ui/hooks/useCompletion.ts
@@ -28,6 +28,7 @@ export interface UseCompletionReturn {
visibleStartIndex: number;
showSuggestions: boolean;
isLoadingSuggestions: boolean;
+ isPerfectMatch: boolean;
setActiveSuggestionIndex: React.Dispatch<React.SetStateAction<number>>;
setShowSuggestions: React.Dispatch<React.SetStateAction<boolean>>;
resetCompletionState: () => void;
@@ -50,6 +51,7 @@ export function useCompletion(
const [showSuggestions, setShowSuggestions] = useState<boolean>(false);
const [isLoadingSuggestions, setIsLoadingSuggestions] =
useState<boolean>(false);
+ const [isPerfectMatch, setIsPerfectMatch] = useState<boolean>(false);
const resetCompletionState = useCallback(() => {
setSuggestions([]);
@@ -57,6 +59,7 @@ export function useCompletion(
setVisibleStartIndex(0);
setShowSuggestions(false);
setIsLoadingSuggestions(false);
+ setIsPerfectMatch(false);
}, []);
const navigateUp = useCallback(() => {
@@ -127,6 +130,9 @@ export function useCompletion(
const trimmedQuery = query.trimStart();
if (trimmedQuery.startsWith('/')) {
+ // Always reset perfect match at the beginning of processing.
+ setIsPerfectMatch(false);
+
const fullPath = trimmedQuery.substring(1);
const hasTrailingSpace = trimmedQuery.endsWith(' ');
@@ -183,6 +189,23 @@ export function useCompletion(
}
}
+ // Check for perfect, executable match
+ if (!hasTrailingSpace) {
+ if (leafCommand && partial === '' && leafCommand.action) {
+ // Case: /command<enter> - command has action, no sub-commands were suggested
+ setIsPerfectMatch(true);
+ } else if (currentLevel) {
+ // Case: /command subcommand<enter>
+ const perfectMatch = currentLevel.find(
+ (cmd) =>
+ (cmd.name === partial || cmd.altName === partial) && cmd.action,
+ );
+ if (perfectMatch) {
+ setIsPerfectMatch(true);
+ }
+ }
+ }
+
const depth = commandPathParts.length;
// Provide Suggestions based on the now-corrected context
@@ -223,7 +246,7 @@ export function useCompletion(
const perfectMatch = potentialSuggestions.find(
(s) => s.name === partial || s.altName === partial,
);
- if (perfectMatch && !perfectMatch.subCommands) {
+ if (perfectMatch && perfectMatch.action) {
potentialSuggestions = [];
}
}
@@ -534,6 +557,7 @@ export function useCompletion(
visibleStartIndex,
showSuggestions,
isLoadingSuggestions,
+ isPerfectMatch,
setActiveSuggestionIndex,
setShowSuggestions,
resetCompletionState,