diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index d56d54a..2a599a4 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -16,6 +16,35 @@ function isFuzzyMatch(candidate: string, query: string) {
return true;
}
+function getCurrentPartial(input: string) {
+ const trimmed = input.trim();
+ if (!trimmed) return "";
+ if (trimmed.endsWith("/")) return "";
+ const idx = trimmed.lastIndexOf("/");
+ return idx >= 0 ? trimmed.slice(idx + 1) : trimmed;
+}
+
+function renderHighlightedMatch(text: string, query: string) {
+ if (!query) return text;
+ let qIndex = 0;
+ const lowerQuery = query.toLowerCase();
+ return text.split("").map((char, index) => {
+ const isMatch =
+ qIndex < lowerQuery.length && char.toLowerCase() === lowerQuery[qIndex];
+ if (isMatch) {
+ qIndex += 1;
+ }
+ return (
+
+ {char}
+
+ );
+ });
+}
+
function App() {
const [projectPath, setProjectPath] = React.useState(null);
const [errorMsg, setErrorMsg] = React.useState(null);
@@ -125,18 +154,21 @@ function App() {
setMatchList(list);
}
- computeSuggestion().catch((error) => {
- console.error(error);
- if (!active) return;
- setCompletionError(
- error instanceof Error
- ? error.message
- : "Failed to compute suggestion.",
- );
- });
+ const debounceId = window.setTimeout(() => {
+ computeSuggestion().catch((error) => {
+ console.error(error);
+ if (!active) return;
+ setCompletionError(
+ error instanceof Error
+ ? error.message
+ : "Failed to compute suggestion.",
+ );
+ });
+ }, 60);
return () => {
active = false;
+ window.clearTimeout(debounceId);
};
}, [pathInput, homeDir]);
@@ -195,6 +227,8 @@ function App() {
}
}
+ const currentPartial = getCurrentPartial(pathInput);
+
return (
- {match.name}/
+ {renderHighlightedMatch(match.name, currentPartial)}/
);
})}