feat: add searchExcludeDirs setting for @ file autocomplete blacklist (#1202)
Implements the directory blacklist feature from #660 (incomplete items 3-4). Users can now configure directories to exclude from the @ file picker and fuzzy search via settings.json: { "searchExcludeDirs": ["node_modules", ".git", "dist", "build"] } Changes: - settings-manager.ts: added searchExcludeDirs setting with get/set - autocomplete.ts (pi-tui): CombinedAutocompleteProvider accepts excludeDirs option, filters excluded directory names in both readdir-based and native fuzzy search paths - interactive-mode.ts: passes searchExcludeDirs to the provider The native fd fuzzy search already respects .gitignore. This setting covers directories that aren't gitignored but shouldn't appear in autocomplete (e.g., large vendor dirs, build outputs in projects without comprehensive .gitignore). Fixes #1190
This commit is contained in:
parent
3c50cbb504
commit
0f97f938f7
3 changed files with 34 additions and 2 deletions
|
|
@ -141,6 +141,7 @@ export interface Settings {
|
|||
editorPaddingX?: number; // Horizontal padding for input editor (default: 0)
|
||||
autocompleteMaxVisible?: number; // Max visible items in autocomplete dropdown (default: 5)
|
||||
respectGitignoreInPicker?: boolean; // When false, @ file picker shows gitignored files (default: true)
|
||||
searchExcludeDirs?: string[]; // Directories to exclude from @ file search (e.g., ["node_modules", ".git", "dist"])
|
||||
showHardwareCursor?: boolean; // Show terminal cursor while still positioning it for IME
|
||||
markdown?: MarkdownSettings;
|
||||
memory?: MemorySettings;
|
||||
|
|
@ -1041,6 +1042,16 @@ export class SettingsManager {
|
|||
this.save();
|
||||
}
|
||||
|
||||
getSearchExcludeDirs(): string[] {
|
||||
return this.settings.searchExcludeDirs ?? [];
|
||||
}
|
||||
|
||||
setSearchExcludeDirs(dirs: string[]): void {
|
||||
this.globalSettings.searchExcludeDirs = dirs.filter(Boolean);
|
||||
this.markModified("searchExcludeDirs");
|
||||
this.save();
|
||||
}
|
||||
|
||||
getCodeBlockIndent(): string {
|
||||
return this.settings.markdown?.codeBlockIndent ?? " ";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,7 +367,10 @@ export class InteractiveMode {
|
|||
this.autocompleteProvider = new CombinedAutocompleteProvider(
|
||||
[...slashCommands, ...templateCommands, ...extensionCommands, ...skillCommandList],
|
||||
process.cwd(),
|
||||
{ respectGitignore: this.settingsManager.getRespectGitignoreInPicker() },
|
||||
{
|
||||
respectGitignore: this.settingsManager.getRespectGitignoreInPicker(),
|
||||
excludeDirs: this.settingsManager.getSearchExcludeDirs(),
|
||||
},
|
||||
);
|
||||
this.defaultEditor.setAutocompleteProvider(this.autocompleteProvider);
|
||||
if (this.editor !== this.defaultEditor) {
|
||||
|
|
|
|||
|
|
@ -131,21 +131,27 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|||
private commands: (SlashCommand | AutocompleteItem)[];
|
||||
private basePath: string;
|
||||
private respectGitignore: boolean;
|
||||
private excludeDirs: Set<string>;
|
||||
|
||||
constructor(
|
||||
commands: (SlashCommand | AutocompleteItem)[] = [],
|
||||
basePath: string = process.cwd(),
|
||||
options?: { respectGitignore?: boolean },
|
||||
options?: { respectGitignore?: boolean; excludeDirs?: string[] },
|
||||
) {
|
||||
this.commands = commands;
|
||||
this.basePath = basePath;
|
||||
this.respectGitignore = options?.respectGitignore ?? true;
|
||||
this.excludeDirs = new Set(options?.excludeDirs ?? []);
|
||||
}
|
||||
|
||||
setRespectGitignore(value: boolean): void {
|
||||
this.respectGitignore = value;
|
||||
}
|
||||
|
||||
setExcludeDirs(dirs: string[]): void {
|
||||
this.excludeDirs = new Set(dirs.filter(Boolean));
|
||||
}
|
||||
|
||||
getSuggestions(
|
||||
lines: string[],
|
||||
cursorLine: number,
|
||||
|
|
@ -485,6 +491,11 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Skip excluded directories
|
||||
if (this.excludeDirs.has(entry.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if entry is a directory (or a symlink pointing to a directory)
|
||||
let isDirectory = entry.isDirectory();
|
||||
if (!isDirectory && entry.isSymbolicLink()) {
|
||||
|
|
@ -578,6 +589,13 @@ export class CombinedAutocompleteProvider implements AutocompleteProvider {
|
|||
for (const { path: entryPath, isDirectory } of result.matches) {
|
||||
// Native module includes trailing / for directories
|
||||
const pathWithoutSlash = isDirectory ? entryPath.slice(0, -1) : entryPath;
|
||||
|
||||
// Skip paths that start with or contain an excluded directory
|
||||
if (this.excludeDirs.size > 0) {
|
||||
const segments = pathWithoutSlash.split("/");
|
||||
if (segments.some(seg => this.excludeDirs.has(seg))) continue;
|
||||
}
|
||||
|
||||
const displayPath = scopedQuery
|
||||
? this.scopedPathForDisplay(scopedQuery.displayBase, pathWithoutSlash)
|
||||
: pathWithoutSlash;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue