getCompletions function
Generate autocomplete suggestions for a partial @-mention.
Implementation
Future<List<MentionSuggestion>> getCompletions(
String partial, {
required String workingDirectory,
int maxResults = 20,
}) async {
final suggestions = <MentionSuggestion>[];
// Determine if it looks like a git ref.
if (partial.startsWith('branch:') ||
partial.startsWith('commit:') ||
partial.startsWith('tag:')) {
final colonIdx = partial.indexOf(':');
final refType = partial.substring(0, colonIdx);
final refPartial = partial.substring(colonIdx + 1);
final branches = await _getGitRefs(refType, refPartial, workingDirectory);
suggestions.addAll(branches);
return suggestions.take(maxResults).toList();
}
// URL partial — no completions.
if (partial.startsWith('http://') || partial.startsWith('https://')) {
return [];
}
// File / directory completion.
final resolved = _resolvePartialForCompletion(partial, workingDirectory);
final parentDir = _parentDirectory(resolved);
final prefix = _baseName(resolved).toLowerCase();
try {
final dir = Directory(parentDir);
if (await dir.exists()) {
await for (final entity in dir.list(followLinks: true)) {
final name = _baseName(entity.path);
if (name.startsWith('.') && !partial.contains('/.')) {
continue; // skip hidden
}
if (prefix.isNotEmpty && !name.toLowerCase().startsWith(prefix)) {
continue;
}
final isDir = entity is Directory;
final relativePath = _makeRelative(entity.path, workingDirectory);
final ext = isDir ? null : _extension(name);
suggestions.add(
MentionSuggestion(
display: name + (isDir ? '/' : ''),
completion: '@$relativePath${isDir ? '/' : ''}',
type: isDir ? MentionType.directory : MentionType.file,
description: isDir ? 'directory' : ext,
),
);
}
}
} catch (_) {
// Permission denied or other FS error — return empty.
}
// Also suggest matching commands if partial looks like one.
if (!partial.contains('/') && !partial.contains('.')) {
for (final cmd in knownCommands) {
if (cmd.startsWith(partial.toLowerCase())) {
suggestions.add(
MentionSuggestion(
display: '/$cmd',
completion: '/$cmd ',
type: MentionType.command,
description: 'command',
),
);
}
}
}
// Sort: directories first, then files, then commands.
suggestions.sort((a, b) {
final typeOrder = a.type.index.compareTo(b.type.index);
if (typeOrder != 0) return typeOrder;
return a.display.toLowerCase().compareTo(b.display.toLowerCase());
});
return suggestions.take(maxResults).toList();
}