|
| 1 | +import { Command } from "commander"; |
| 2 | +import { access } from "node:fs/promises"; |
| 3 | +import { resolve } from "node:path"; |
| 4 | + |
| 5 | +import CONFIG from "@/config"; |
1 | 6 | import { buildTree } from "@/tree"; |
| 7 | +import type { CLIOptions } from "@/types/types"; |
| 8 | + |
| 9 | +function parseDepth(value: string): number | "inf" { |
| 10 | + if (value === "inf") { |
| 11 | + return "inf"; |
| 12 | + } |
| 13 | + const num = parseInt(value, 10); |
| 14 | + if (isNaN(num) || num < 0) { |
| 15 | + console.error( |
| 16 | + `Error: Invalid depth value "${value}". Must be a positive number or "inf".` |
| 17 | + ); |
| 18 | + process.exit(1); |
| 19 | + } |
| 20 | + return num; |
| 21 | +} |
| 22 | + |
| 23 | +function collectIgnorePatterns(value: string, previous: string[]): string[] { |
| 24 | + return previous.concat([value]); |
| 25 | +} |
2 | 26 |
|
3 | 27 | export async function main() { |
| 28 | + const program = new Command(); |
| 29 | + |
| 30 | + program |
| 31 | + .name(CONFIG.APP.NAME) |
| 32 | + .description(CONFIG.APP.DESCRIPTION) |
| 33 | + .version( |
| 34 | + `TreeEx v${CONFIG.APP.VERSION}`, |
| 35 | + "-v, --version", |
| 36 | + "Show version number" |
| 37 | + ) |
| 38 | + .argument("[path]", "Path to analyze", ".") |
| 39 | + .option( |
| 40 | + "-d, --depth <level>", |
| 41 | + `Maximum depth level (use "inf" for unlimited)`, |
| 42 | + String(CONFIG.DEFAULT_VALUES.MAX_DEPTH) |
| 43 | + ) |
| 44 | + .option( |
| 45 | + "-i, --ignore <pattern>", |
| 46 | + "Additional glob pattern to ignore (can be used multiple times)", |
| 47 | + collectIgnorePatterns, |
| 48 | + [] |
| 49 | + ) |
| 50 | + .option("--no-default-ignore", "Disable default ignore patterns") |
| 51 | + .addHelpText("after", CONFIG.ARGS.HELP_TEXT); |
| 52 | + |
| 53 | + program.parse(); |
| 54 | + |
| 55 | + const options = program.opts<CLIOptions>(); |
| 56 | + const targetPath = resolve(program.args[0] ?? "."); |
4 | 57 | try { |
| 58 | + // Verify path exists and is accessible |
| 59 | + try { |
| 60 | + await access(targetPath); |
| 61 | + } catch { |
| 62 | + console.error( |
| 63 | + `Error: Path "${targetPath}" does not exist or is not accessible.` |
| 64 | + ); |
| 65 | + process.exit(1); |
| 66 | + } |
| 67 | + |
| 68 | + // Build ignore patterns |
| 69 | + const ignorePatterns: string[] = []; |
| 70 | + // Commander's --no-default-ignore sets options.defaultIgnore to false. |
| 71 | + // If --no-default-ignore is NOT present, options.defaultIgnore is true (default). |
| 72 | + if (options.defaultIgnore) { |
| 73 | + ignorePatterns.push(...CONFIG.DEFAULT_VALUES.IGNORES); |
| 74 | + } |
| 75 | + if (options.ignore && Array.isArray(options.ignore)) { |
| 76 | + ignorePatterns.push(...options.ignore); |
| 77 | + } |
| 78 | + |
| 79 | + // Parse depth |
| 80 | + const depth = parseDepth(options.depth); |
| 81 | + |
5 | 82 | // Build and output tree |
6 | 83 | const tree = await buildTree({ |
7 | | - path: ".", |
| 84 | + path: targetPath, |
8 | 85 | options: { |
9 | | - depth: "inf", |
| 86 | + depth: depth, |
| 87 | + ignore: ignorePatterns, |
10 | 88 | }, |
11 | 89 | }); |
12 | 90 |
|
|
0 commit comments