summaryrefslogtreecommitdiff
path: root/packages/cli/src
diff options
context:
space:
mode:
authorMiguel Solorio <[email protected]>2025-05-14 16:01:29 -0700
committerGitHub <[email protected]>2025-05-14 16:01:29 -0700
commit416813452eafd4b9497fe7f4b36d5000b51c969d (patch)
treeeda5d0d94fa20dfe822cca492b88d9d5f7e36bf0 /packages/cli/src
parent89aa1cad41eefc4e1e7e4b3cb9d4a495707dd33e (diff)
Improvements to suggestions & slash commands (#344)
Co-authored-by: N. Taylor Mullen <[email protected]>
Diffstat (limited to 'packages/cli/src')
-rw-r--r--packages/cli/src/ui/App.tsx2
-rw-r--r--packages/cli/src/ui/components/InputPrompt.tsx1
-rw-r--r--packages/cli/src/ui/components/SuggestionsDisplay.tsx28
-rw-r--r--packages/cli/src/ui/hooks/slashCommandProcessor.ts2
-rw-r--r--packages/cli/src/ui/hooks/useCompletion.ts38
5 files changed, 46 insertions, 25 deletions
diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx
index 5fb36480..758ddb28 100644
--- a/packages/cli/src/ui/App.tsx
+++ b/packages/cli/src/ui/App.tsx
@@ -314,7 +314,7 @@ export const App = ({
resetCompletion={completion.resetCompletionState}
/>
{completion.showSuggestions && (
- <Box marginTop={1}>
+ <Box>
<SuggestionsDisplay
suggestions={completion.suggestions}
activeIndex={completion.activeSuggestionIndex}
diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx
index 8ec67ec7..1c3d2a07 100644
--- a/packages/cli/src/ui/components/InputPrompt.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.tsx
@@ -76,6 +76,7 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
const newValue = base + selectedSuggestion.value;
onChangeAndMoveCursor(newValue);
onSubmit(newValue); // Execute the command
+ onChangeAndMoveCursor(''); // Clear query after submit
} else {
// Handle @ command completion
const atIndex = query.lastIndexOf('@');
diff --git a/packages/cli/src/ui/components/SuggestionsDisplay.tsx b/packages/cli/src/ui/components/SuggestionsDisplay.tsx
index ba25f2b6..3f2094bb 100644
--- a/packages/cli/src/ui/components/SuggestionsDisplay.tsx
+++ b/packages/cli/src/ui/components/SuggestionsDisplay.tsx
@@ -9,6 +9,7 @@ import { Colors } from '../colors.js';
export interface Suggestion {
label: string;
value: string;
+ description?: string;
}
interface SuggestionsDisplayProps {
suggestions: Suggestion[];
@@ -29,7 +30,7 @@ export function SuggestionsDisplay({
}: SuggestionsDisplayProps) {
if (isLoading) {
return (
- <Box borderStyle="round" paddingX={1} width={width}>
+ <Box paddingX={1} width={width}>
<Text color="gray">Loading suggestions...</Text>
</Box>
);
@@ -48,20 +49,29 @@ export function SuggestionsDisplay({
const visibleSuggestions = suggestions.slice(startIndex, endIndex);
return (
- <Box borderStyle="round" flexDirection="column" paddingX={1} width={width}>
+ <Box flexDirection="column" paddingX={1} width={width}>
{scrollOffset > 0 && <Text color={Colors.Foreground}>▲</Text>}
{visibleSuggestions.map((suggestion, index) => {
const originalIndex = startIndex + index;
const isActive = originalIndex === activeIndex;
+ const textColor = isActive ? Colors.AccentPurple : Colors.SubtleComment;
+
return (
- <Text
- key={`${suggestion}-${originalIndex}`}
- color={isActive ? Colors.Background : Colors.Foreground}
- backgroundColor={isActive ? Colors.AccentBlue : undefined}
- >
- {suggestion.label}
- </Text>
+ <Box key={`${suggestion}-${originalIndex}`} width={width}>
+ <Box flexDirection="row">
+ <Box width={20} flexShrink={0}>
+ <Text color={textColor}>{suggestion.label}</Text>
+ </Box>
+ {suggestion.description ? (
+ <Box flexGrow={1}>
+ <Text color={textColor} wrap="wrap">
+ {suggestion.description}
+ </Text>
+ </Box>
+ ) : null}
+ </Box>
+ </Box>
);
})}
{endIndex < suggestions.length && <Text color="gray">▼</Text>}
diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts
index e2b478e2..7ce3ae86 100644
--- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts
+++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts
@@ -94,7 +94,7 @@ export const useSlashCommandProcessor = (
{
name: 'quit',
altName: 'exit',
- description: '',
+ description: 'exit the cli',
action: (_value: PartListUnion | string) => {
onDebugMessage('Quitting. Good-bye.');
process.exit(0);
diff --git a/packages/cli/src/ui/hooks/useCompletion.ts b/packages/cli/src/ui/hooks/useCompletion.ts
index 1c693f71..622dc4c4 100644
--- a/packages/cli/src/ui/hooks/useCompletion.ts
+++ b/packages/cli/src/ui/hooks/useCompletion.ts
@@ -119,20 +119,30 @@ export function useCompletion(
// --- Handle Slash Command Completion ---
if (trimmedQuery.startsWith('/')) {
const partialCommand = trimmedQuery.substring(1);
- const commands = slashCommands
- .map((cmd) => cmd.name)
- .concat(
- slashCommands
- .map((cmd) => cmd.altName)
- .filter((cmd) => cmd !== undefined),
- );
-
- const filteredSuggestions = commands
- .filter((name) => name.startsWith(partialCommand))
- // Filter out ? and any other single character commands
- .filter((name) => name.length > 1)
- .map((name) => ({ label: name, value: name }))
- .sort();
+ const filteredSuggestions = slashCommands
+ .filter(
+ (cmd) =>
+ cmd.name.startsWith(partialCommand) ||
+ cmd.altName?.startsWith(partialCommand),
+ )
+ // Filter out ? and any other single character commands unless it's the only char
+ .filter((cmd) => {
+ const nameMatch = cmd.name.startsWith(partialCommand);
+ const altNameMatch = cmd.altName?.startsWith(partialCommand);
+ if (partialCommand.length === 1) {
+ return nameMatch || altNameMatch; // Allow single char match if query is single char
+ }
+ return (
+ (nameMatch && cmd.name.length > 1) ||
+ (altNameMatch && cmd.altName && cmd.altName.length > 1)
+ );
+ })
+ .map((cmd) => ({
+ label: cmd.name, // Always show the main name as label
+ value: cmd.name, // Value should be the main command name for execution
+ description: cmd.description,
+ }))
+ .sort((a, b) => a.label.localeCompare(b.label));
setSuggestions(filteredSuggestions);
setShowSuggestions(filteredSuggestions.length > 0);