Flamehaven commited on
Commit
2d58037
ยท
1 Parent(s): 8f95629

feat: Create CLI-BLUPRINTER tool for project reporting

Browse files
pyproject.toml CHANGED
@@ -42,6 +42,7 @@ Homepage = "https://github.com/Flamehaven/CRoM-Context-Rot-Mitigation--Efficient
42
  [project.scripts]
43
  "crom-demo" = "crom_efficientllm.demo:main"
44
  "crom-bench" = "crom_efficientllm.cli:main"
 
45
 
46
  [tool.setuptools]
47
  package-dir = {"" = "src"}
 
42
  [project.scripts]
43
  "crom-demo" = "crom_efficientllm.demo:main"
44
  "crom-bench" = "crom_efficientllm.cli:main"
45
+ "cli-bluprinter" = "crom_efficientllm.bluprinter:main"
46
 
47
  [tool.setuptools]
48
  package-dir = {"" = "src"}
src/crom_efficientllm/bluprinter.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import argparse
3
+ from pathlib import Path
4
+ from typing import List, Set
5
+
6
+ # ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ์™ธํ•  ๋””๋ ‰ํ† ๋ฆฌ ๋ฐ ํŒŒ์ผ ํŒจํ„ด
7
+ DEFAULT_EXCLUDES = {
8
+ "__pycache__",
9
+ ".git",
10
+ ".pytest_cache",
11
+ ".vscode",
12
+ ".idea",
13
+ "node_modules",
14
+ ".env",
15
+ "*.pyc",
16
+ "*.pyo",
17
+ "*.egg-info",
18
+ "dist",
19
+ "build",
20
+ }
21
+
22
+ def generate_tree(directory: Path, excludes: Set[str]) -> (str, List[Path]):
23
+ """๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ ํŠธ๋ฆฌ์™€ ํŒŒ์ผ ๋ชฉ๋ก์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค."""
24
+ tree_str = f"```\n{directory.name}/\n"
25
+ file_paths = []
26
+
27
+ def build_tree(current_path: Path, prefix: str = ""):
28
+ nonlocal tree_str
29
+ # listdir๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ๊ฒฝ๋กœ์˜ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
30
+ try:
31
+ entries = sorted(os.listdir(current_path))
32
+ except FileNotFoundError:
33
+ return
34
+
35
+ # ํ•„ํ„ฐ๋ง: ์ œ์™ธ ๋ชฉ๋ก์— ํฌํ•จ๋œ ํ•ญ๋ชฉ์„ ๊ฑธ๋Ÿฌ๋ƒ…๋‹ˆ๋‹ค.
36
+ filtered_entries = []
37
+ for entry in entries:
38
+ if entry not in excludes:
39
+ # ์—ฌ๊ธฐ์„œ ์ถ”๊ฐ€์ ์ธ glob ํŒจํ„ด ๋งค์นญ์„ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
40
+ filtered_entries.append(entry)
41
+
42
+ for i, entry in enumerate(filtered_entries):
43
+ is_last = i == (len(filtered_entries) - 1)
44
+ connector = "โ””โ”€โ”€ " if is_last else "โ”œโ”€โ”€ "
45
+ tree_str += f"{prefix}{connector}{entry}\n"
46
+
47
+ new_path = current_path / entry
48
+ if new_path.is_dir():
49
+ new_prefix = prefix + (" " if is_last else "โ”‚ ")
50
+ build_tree(new_path, new_prefix)
51
+ else:
52
+ file_paths.append(new_path)
53
+
54
+ build_tree(directory)
55
+ tree_str += "```\n"
56
+ return tree_str, file_paths
57
+
58
+ def get_file_content(file_path: Path) -> str:
59
+ """ํŒŒ์ผ ๋‚ด์šฉ์„ ์ฝ์–ด์˜ต๋‹ˆ๋‹ค. ํ…์ŠคํŠธ ํŒŒ์ผ์ด ์•„๋‹ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค."""
60
+ try:
61
+ with file_path.open("r", encoding="utf-8") as f:
62
+ return f.read()
63
+ except Exception:
64
+ return "[Error: Could not read file content, possibly a binary file.]\n"
65
+
66
+ def main():
67
+ parser = argparse.ArgumentParser(description="Generate a project blueprint in a single Markdown file.")
68
+ parser.add_argument("--input-dir", type=str, required=True, help="The root directory of the project to scan.")
69
+ parser.add_argument("--output-file", type=str, default="project_blueprint.md", help="The name of the output Markdown file.")
70
+ args = parser.parse_args()
71
+
72
+ input_path = Path(args.input_dir).resolve()
73
+ output_path = Path(args.output_file).resolve()
74
+
75
+ print(f"Scanning project at: {input_path}")
76
+
77
+ # 1. ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ ๋ฐ ํŒŒ์ผ ๋ชฉ๋ก ์ƒ์„ฑ
78
+ tree_structure, file_paths = generate_tree(input_path, DEFAULT_EXCLUDES)
79
+
80
+ # 2. ์ตœ์ข… ๋ฆฌํฌํŠธ ์ƒ์„ฑ
81
+ with output_path.open("w", encoding="utf-8") as f:
82
+ f.write(f"# Project Blueprint: {input_path.name}\n\n")
83
+ f.write("## 1. Project Directory Tree\n\n")
84
+ f.write(tree_structure)
85
+ f.write("\n## 2. File Contents\n\n")
86
+
87
+ for path in file_paths:
88
+ print(f" - Processing: {path.relative_to(input_path)}")
89
+ f.write(f"---\n### **File:** `{path}`\n")
90
+
91
+ # ํŒŒ์ผ ํ™•์žฅ์ž์— ๋”ฐ๋ผ ์ฝ”๋“œ ๋ธ”๋ก ์–ธ์–ด ์ง€์ •
92
+ lang = path.suffix.lstrip('.')
93
+ if not lang:
94
+ lang = "text"
95
+
96
+ f.write(f"```{lang}\n")
97
+ f.write(get_file_content(path))
98
+ f.write(f"\n```\n\n")
99
+
100
+ print(f"\nSuccessfully generated project blueprint at: {output_path}")
101
+
102
+ if __name__ == "__main__":
103
+ main()