| 41 | ignore: z.array(z.string()).describe("List of glob patterns to ignore").optional(), |
| 42 | }), |
| 43 | async execute(params) { |
| 44 | const searchPath = path.resolve(Instance.directory, params.path || ".") |
| 45 | |
| 46 | const ignoreGlobs = IGNORE_PATTERNS.map((p) => `!${p}*`).concat(params.ignore?.map((p) => `!${p}`) || []) |
| 47 | const files = [] |
| 48 | for await (const file of Ripgrep.files({ cwd: searchPath, glob: ignoreGlobs })) { |
| 49 | files.push(file) |
| 50 | if (files.length >= LIMIT) break |
| 51 | } |
| 52 | |
| 53 | // Build directory structure |
| 54 | const dirs = new Set<string>() |
| 55 | const filesByDir = new Map<string, string[]>() |
| 56 | |
| 57 | for (const file of files) { |
| 58 | const dir = path.dirname(file) |
| 59 | const parts = dir === "." ? [] : dir.split("/") |
| 60 | |
| 61 | // Add all parent directories |
| 62 | for (let i = 0; i <= parts.length; i++) { |
| 63 | const dirPath = i === 0 ? "." : parts.slice(0, i).join("/") |
| 64 | dirs.add(dirPath) |
| 65 | } |
| 66 | |
| 67 | // Add file to its directory |
| 68 | if (!filesByDir.has(dir)) filesByDir.set(dir, []) |
| 69 | filesByDir.get(dir)!.push(path.basename(file)) |
| 70 | } |
| 71 | |
| 72 | function renderDir(dirPath: string, depth: number): string { |
| 73 | const indent = " ".repeat(depth) |
| 74 | let output = "" |
| 75 | |
| 76 | if (depth > 0) { |
| 77 | output += `${indent}${path.basename(dirPath)}/\n` |
| 78 | } |
| 79 | |
| 80 | const childIndent = " ".repeat(depth + 1) |
| 81 | const children = Array.from(dirs) |
| 82 | .filter((d) => path.dirname(d) === dirPath && d !== dirPath) |
| 83 | .sort() |
| 84 | |
| 85 | // Render subdirectories first |
| 86 | for (const child of children) { |
| 87 | output += renderDir(child, depth + 1) |
| 88 | } |
| 89 | |
| 90 | // Render files |
| 91 | const files = filesByDir.get(dirPath) || [] |
| 92 | for (const file of files.sort()) { |
| 93 | output += `${childIndent}${file}\n` |
| 94 | } |
| 95 | |
| 96 | return output |
| 97 | } |
| 98 | |
| 99 | const output = `${searchPath}/\n` + renderDir(".", 0) |
| 100 | |