Skip to content

Commit 7e02845

Browse files
committed
added depth and ignore files cmd arg support
1 parent 5536567 commit 7e02845

6 files changed

Lines changed: 153 additions & 22 deletions

File tree

bun.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@
2424
"peerDependencies": {
2525
"typescript": "^5"
2626
},
27+
"keywords": [
28+
"cli",
29+
"directory",
30+
"tree",
31+
"json",
32+
"filesystem",
33+
"tool"
34+
],
2735
"author": "Pratik Dev",
28-
"license": "MIT"
36+
"license": "MIT",
37+
"dependencies": {
38+
"commander": "^14.0.2"
39+
}
2940
}

src/cli.ts

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,90 @@
1+
import { Command } from "commander";
2+
import { access } from "node:fs/promises";
3+
import { resolve } from "node:path";
4+
5+
import CONFIG from "@/config";
16
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+
}
226

327
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] ?? ".");
457
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+
582
// Build and output tree
683
const tree = await buildTree({
7-
path: ".",
84+
path: targetPath,
885
options: {
9-
depth: "inf",
86+
depth: depth,
87+
ignore: ignorePatterns,
1088
},
1189
});
1290

src/config.ts

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,49 @@
1+
const DEFAULT_VALUES = {
2+
MAX_DEPTH: 20,
3+
IGNORES: [
4+
".git",
5+
"node_modules",
6+
"build",
7+
"dist",
8+
"out",
9+
".svn",
10+
".hg",
11+
".CVS",
12+
".DS_Store",
13+
"vendor",
14+
".vscode",
15+
],
16+
};
17+
118
const CONFIG = {
2-
DEFAULT: {
3-
MAX_DEPTH: 20,
4-
IGNORES: [
5-
".git",
6-
"node_modules",
7-
"build",
8-
"dist",
9-
"out",
10-
".svn",
11-
".hg",
12-
".CVS",
13-
".DS_Store",
14-
"vendor",
15-
".vscode",
16-
],
19+
APP: {
20+
NAME: "TreeEx",
21+
DESCRIPTION: "Directory tree analyzer with JSON output",
22+
VERSION: "1.0.0",
1723
},
18-
};
24+
ARGS: {
25+
HELP_TEXT: `
26+
Default Ignore Patterns:
27+
${DEFAULT_VALUES.IGNORES.join(", ")}
28+
29+
Examples:
30+
$ treeEx Analyze current directory
31+
$ treeEx ./src Analyze ./src directory
32+
$ treeEx --depth 5 Limit depth to 5 levels
33+
$ treeEx --depth inf Unlimited depth
34+
$ treeEx -i "*.log" Ignore all .log files
35+
$ treeEx --no-default-ignore Don't ignore default patterns
36+
37+
Output:
38+
JSON tree structure with the following format:
39+
{
40+
"name": "directory-name",
41+
"type": "directory",
42+
"children": [...]
43+
}
44+
`,
45+
},
46+
DEFAULT_VALUES,
47+
} as const;
1948

2049
export default CONFIG;

src/tree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ export async function buildTree({
9191
path,
9292
options = {},
9393
}: BuildTreeParams): Promise<Node> {
94-
const ignorePatterns = options.ignore ?? CONFIG.DEFAULT.IGNORES;
95-
const maxDepth = options.depth ?? CONFIG.DEFAULT.MAX_DEPTH;
94+
const ignorePatterns = options.ignore ?? CONFIG.DEFAULT_VALUES.IGNORES;
95+
const maxDepth = options.depth ?? CONFIG.DEFAULT_VALUES.MAX_DEPTH;
9696

9797
return await traverseDirectory({
9898
currentPath: path,

src/types/types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@ export interface Node {
1111
* CLI options for the TreeEx command
1212
*/
1313
export interface TreeExOptions {
14-
path: string;
1514
depth: number | "inf";
1615
ignore: string[];
1716
}
17+
18+
/**
19+
* CLI options parsed from command line arguments
20+
*/
21+
export interface CLIOptions {
22+
depth: string;
23+
ignore: string[];
24+
defaultIgnore: boolean; // This will be true by default, and false if --no-default-ignore is used
25+
}

0 commit comments

Comments
 (0)