Rank slash command autocomplete matches

This commit is contained in:
Mohamed Boudra
2026-05-27 13:40:49 +07:00
parent a630986d06
commit d594bce153
3 changed files with 82 additions and 8 deletions
@@ -0,0 +1,48 @@
import { compareMatchScores, type MatchScore, scoreTextFields } from "@/utils/score-match";
interface CommandAutocompleteEntry {
command: {
name: string;
aliases?: readonly string[];
};
}
interface ScoredCommandAutocompleteEntry<TEntry> {
entry: TEntry;
score: MatchScore;
}
function scoreCommandAutocompleteEntry(
entry: CommandAutocompleteEntry,
query: string,
): MatchScore | null {
return scoreTextFields(query, [entry.command.name, ...(entry.command.aliases ?? [])]);
}
export function filterAndRankCommandAutocompleteEntries<TEntry extends CommandAutocompleteEntry>(
entries: readonly TEntry[],
query: string,
): TEntry[] {
const normalizedQuery = query.trim().toLowerCase();
if (normalizedQuery.length === 0) {
return [...entries];
}
const scoredEntries: ScoredCommandAutocompleteEntry<TEntry>[] = [];
for (const entry of entries) {
const score = scoreCommandAutocompleteEntry(entry, normalizedQuery);
if (score) {
scoredEntries.push({ entry, score });
}
}
scoredEntries.sort((a, b) => {
const scoreComparison = compareMatchScores(a.score, b.score);
if (scoreComparison !== 0) {
return scoreComparison;
}
return a.entry.command.name.localeCompare(b.entry.command.name);
});
return scoredEntries.map((scored) => scored.entry);
}