summaryrefslogtreecommitdiff
path: root/packages/cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src')
-rw-r--r--packages/cli/src/ui/App.tsx5
-rw-r--r--packages/cli/src/ui/components/InputPrompt.tsx42
-rw-r--r--packages/cli/src/ui/hooks/useCompletion.ts23
-rw-r--r--packages/cli/src/ui/utils/commandUtils.ts9
4 files changed, 62 insertions, 17 deletions
diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx
index 5ddf13db..194a18cf 100644
--- a/packages/cli/src/ui/App.tsx
+++ b/packages/cli/src/ui/App.tsx
@@ -26,7 +26,7 @@ import { ConsoleOutput } from './components/ConsolePatcher.js';
import { HistoryItemDisplay } from './components/HistoryItemDisplay.js';
import { useCompletion } from './hooks/useCompletion.js';
import { SuggestionsDisplay } from './components/SuggestionsDisplay.js';
-import { isAtCommand } from './utils/commandUtils.js';
+import { isAtCommand, isSlashCommand } from './utils/commandUtils.js';
interface AppProps {
config: Config;
@@ -96,7 +96,8 @@ export const App = ({ config, settings, cliVersion }: AppProps) => {
const completion = useCompletion(
query,
config.getTargetDir(),
- isInputActive && isAtCommand(query),
+ isInputActive && (isAtCommand(query) || isSlashCommand(query)),
+ slashCommands,
);
// --- Render Logic ---
diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx
index fbf84766..1c8cff4d 100644
--- a/packages/cli/src/ui/components/InputPrompt.tsx
+++ b/packages/cli/src/ui/components/InputPrompt.tsx
@@ -47,25 +47,37 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
return;
}
const selectedSuggestion = suggestions[activeSuggestionIndex];
- const atIndex = query.lastIndexOf('@');
- if (atIndex === -1) return;
+ const trimmedQuery = query.trimStart();
- // Find the part of the query after the '@'
- const pathPart = query.substring(atIndex + 1);
- // Find the last slash within that part
- const lastSlashIndexInPath = pathPart.lastIndexOf('/');
-
- let base = '';
- if (lastSlashIndexInPath === -1) {
- // No slash after '@', replace everything after '@'
- base = query.substring(0, atIndex + 1);
+ if (trimmedQuery.startsWith('/')) {
+ // Handle / command completion
+ const slashIndex = query.indexOf('/');
+ const base = query.substring(0, slashIndex + 1);
+ const newValue = base + selectedSuggestion.value;
+ setQuery(newValue);
} else {
- // Slash found, keep everything up to and including the last slash
- base = query.substring(0, atIndex + 1 + lastSlashIndexInPath + 1);
+ // Handle @ command completion
+ const atIndex = query.lastIndexOf('@');
+ if (atIndex === -1) return;
+
+ // Find the part of the query after the '@'
+ const pathPart = query.substring(atIndex + 1);
+ // Find the last slash within that part
+ const lastSlashIndexInPath = pathPart.lastIndexOf('/');
+
+ let base = '';
+ if (lastSlashIndexInPath === -1) {
+ // No slash after '@', replace everything after '@'
+ base = query.substring(0, atIndex + 1);
+ } else {
+ // Slash found, keep everything up to and including the last slash
+ base = query.substring(0, atIndex + 1 + lastSlashIndexInPath + 1);
+ }
+
+ const newValue = base + selectedSuggestion.value;
+ setQuery(newValue);
}
- const newValue = base + selectedSuggestion.value;
- setQuery(newValue);
resetCompletion(); // Hide suggestions after selection
setInputKey((k) => k + 1); // Increment key to force re-render and cursor reset
}, [
diff --git a/packages/cli/src/ui/hooks/useCompletion.ts b/packages/cli/src/ui/hooks/useCompletion.ts
index 07a71630..31c59bcf 100644
--- a/packages/cli/src/ui/hooks/useCompletion.ts
+++ b/packages/cli/src/ui/hooks/useCompletion.ts
@@ -12,6 +12,8 @@ import {
MAX_SUGGESTIONS_TO_SHOW,
Suggestion,
} from '../components/SuggestionsDisplay.js';
+import { SlashCommand } from './slashCommandProcessor.js';
+
export interface UseCompletionReturn {
suggestions: Suggestion[];
activeSuggestionIndex: number;
@@ -29,6 +31,7 @@ export function useCompletion(
query: string,
cwd: string,
isActive: boolean,
+ slashCommands: SlashCommand[],
): UseCompletionReturn {
const [suggestions, setSuggestions] = useState<Suggestion[]>([]);
const [activeSuggestionIndex, setActiveSuggestionIndex] =
@@ -111,6 +114,26 @@ export function useCompletion(
return;
}
+ const trimmedQuery = query.trimStart(); // Trim leading whitespace
+
+ // --- Handle Slash Command Completion ---
+ if (trimmedQuery.startsWith('/')) {
+ const partialCommand = trimmedQuery.substring(1);
+ const filteredSuggestions = slashCommands
+ .map((cmd) => cmd.name)
+ .filter((name) => name.startsWith(partialCommand))
+ .map((name) => ({ label: name, value: name }))
+ .sort();
+
+ setSuggestions(filteredSuggestions);
+ setShowSuggestions(filteredSuggestions.length > 0);
+ setActiveSuggestionIndex(-1);
+ setVisibleStartIndex(0);
+ setIsLoadingSuggestions(false);
+ return;
+ }
+
+ // --- Handle At Command Completion ---
const atIndex = query.lastIndexOf('@');
if (atIndex === -1) {
resetCompletionState();
diff --git a/packages/cli/src/ui/utils/commandUtils.ts b/packages/cli/src/ui/utils/commandUtils.ts
index 64046658..bcae7b6c 100644
--- a/packages/cli/src/ui/utils/commandUtils.ts
+++ b/packages/cli/src/ui/utils/commandUtils.ts
@@ -16,6 +16,15 @@ export const isAtCommand = (query: string): boolean =>
// Check if starts with @ OR has a space, then @, then a non-space character.
query.startsWith('@') || /\s@\S/.test(query);
+/**
+ * Checks if a query string potentially represents an '/' command.
+ * It triggers if the query starts with '/'
+ *
+ * @param query The input query string.
+ * @returns True if the query looks like an '/' command, false otherwise.
+ */
+export const isSlashCommand = (query: string): boolean => query.startsWith('/');
+
const control_symbols: string[] = ['/', '@', '!', '?', '$'];
/**
* Returns the first word of query with optional leading slash, ampersand, bang.