Skip to content

Commit fcdf61b

Browse files
committed
feat!: remove includes/exludes and add filterFile/filterDirectory`
1 parent 529129b commit fcdf61b

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

builtin/source/file.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ type Detail = {
1212

1313
export type FileOptions = {
1414
/**
15-
* Patterns to include files matching specific paths.
15+
* A function to filter files based on their paths.
16+
*
17+
* If the function returns `false`, the file is excluded.
1618
*/
17-
includes?: RegExp[];
19+
filterFile?: (path: string) => boolean;
1820

1921
/**
20-
* Patterns to exclude files matching specific paths.
22+
* A function to filter directories based on their paths.
23+
*
24+
* If the function returns `false`, the directory is excluded.
2125
*/
22-
excludes?: RegExp[];
26+
filterDirectory?: (path: string) => boolean;
2327
};
2428

2529
/**
@@ -32,7 +36,11 @@ export type FileOptions = {
3236
* @returns A Source that generates items representing filtered files.
3337
*/
3438
export function file(options: Readonly<FileOptions> = {}): Source<Detail> {
35-
const { includes, excludes } = options;
39+
const {
40+
filterFile = () => true,
41+
filterDirectory = () => true,
42+
} = options;
43+
3644
return defineSource(async function* (denops, { args }, { signal }) {
3745
const root = removeTrailingSeparator(
3846
await denops.eval(
@@ -42,17 +50,12 @@ export function file(options: Readonly<FileOptions> = {}): Source<Detail> {
4250
);
4351
signal?.throwIfAborted();
4452

45-
const filter = (path: string) => {
46-
if (includes && !includes.some((p) => p.test(path))) {
47-
return false;
48-
} else if (excludes && excludes.some((p) => p.test(path))) {
49-
return false;
50-
}
51-
return true;
52-
};
53-
5453
// Enumerate files and apply filters
55-
for await (const [id, path] of enumerate(walk(root, filter, signal))) {
54+
for await (
55+
const [id, path] of enumerate(
56+
walk(root, filterFile, filterDirectory, signal),
57+
)
58+
) {
5659
yield {
5760
id,
5861
value: path,
@@ -64,13 +67,12 @@ export function file(options: Readonly<FileOptions> = {}): Source<Detail> {
6467

6568
async function* walk(
6669
root: string,
67-
filter: (path: string) => boolean,
70+
filterFile: (path: string) => boolean,
71+
filterDirectory: (path: string) => boolean,
6872
signal?: AbortSignal,
6973
): AsyncIterableIterator<string> {
7074
for await (const entry of Deno.readDir(root)) {
7175
const path = `${root}${SEPARATOR}${entry.name}`;
72-
// Skip files that do not match the filter
73-
if (!filter(path)) continue;
7476
// Follow symbolic links to recursively yield files
7577
let isDirectory = entry.isDirectory;
7678
if (entry.isSymlink) {
@@ -87,9 +89,13 @@ async function* walk(
8789
}
8890
// Recursively yield files from directories, or yield file details
8991
if (isDirectory) {
90-
yield* walk(path, filter, signal);
92+
if (filterDirectory(path)) {
93+
yield* walk(path, filterFile, filterDirectory, signal);
94+
}
9195
} else {
92-
yield path;
96+
if (filterFile(path)) {
97+
yield path;
98+
}
9399
}
94100
}
95101
}

0 commit comments

Comments
 (0)