1
+ # Copyright 2025 Baleine Jay
2
+ # Licensed under the Phicode Non-Commercial License (https://banes-lab.com/licensing)
3
+ # Commercial use requires a paid license. See link for details.
1
4
import os
2
5
3
- def save_tree_structure (include_paths , exclude_specifics = None , output_file = 'PROJECT_TREE.md' ):
4
- file_emojis = {
5
- '.py' : '🐍' ,
6
- '.js' : '📜' ,
7
- '.json' : '🔧' ,
8
- '.txt' : '📄' ,
9
- '.md' : '📝' ,
10
- '.html' : '🌐' ,
11
- '.css' : '🎨' ,
12
- '.jpg' : '🖼️' ,
13
- '.jpeg' : '🖼️' ,
14
- '.png' : '🖼️' ,
15
- '.gif' : '🖼️' ,
16
- '.ico' : '🖼️' ,
17
- '.mp3' : '🎵' ,
18
- '.wav' : '🎵' ,
19
- '.mp4' : '🎞️' ,
20
- '.pdf' : '📕' ,
21
- '.gdoc' : '🗄️' ,
22
- '.xlsx' : '🧮' ,
23
- '.psd' : '🖌️' ,
24
- '.φ' : '🔱' ,
25
- '.agent' : '🤖' ,
26
- '.vsix' : '🔌' ,
27
- }
28
-
29
- def get_file_emoji (filename ):
30
- filename_lower = filename .lower ()
31
-
32
- text_mapping = {
33
- 'readme' : '📘' ,
34
- 'license' : '⚖️' ,
35
- 'receipt' : '🧾' ,
36
- 'faq' : '❓' ,
37
- 'rules' : '📖' ,
38
- 'invitation' : '💌' ,
39
- 'agenda' : '📅' ,
40
- 'analytics' : '📈' ,
41
- 'brainstorming' : '🧠' ,
42
- 'insights' : '🔎' ,
43
- 'guidelines' : 'ℹ️' ,
44
- 'tools' : '🛠️' ,
45
- 'sponsor' : '💵' ,
46
- 'finished' : '✅' ,
47
- 'bot' : '🤖' ,
48
- 'data' : '📊' ,
49
- }
50
-
51
- for pattern , emoji in text_mapping .items ():
52
- if pattern in filename_lower :
53
- return emoji
54
-
55
- ext = os .path .splitext (filename )[1 ].lower ()
56
- return file_emojis .get (ext , '📄' )
57
-
58
- def should_exclude (path ):
59
- for excl in exclude_specifics :
60
- if excl in path :
61
- return True
62
- return False
63
-
64
- def walk_directory (directory , depth = 0 , prefix = '' ):
65
- if should_exclude (directory ):
66
- return []
67
-
68
- tree_lines = []
69
- try :
70
- entries = os .listdir (directory )
71
- except PermissionError :
72
- return [f"{ prefix } └─ 🔒 [Permission Denied: { os .path .basename (directory )} ]" ]
73
-
74
- entries = [entry for entry in entries if not should_exclude (os .path .join (directory , entry ))]
75
- total_entries = len (entries )
76
-
77
- for idx , entry in enumerate (entries ):
78
- full_path = os .path .join (directory , entry )
79
- is_last = idx == total_entries - 1
80
- symbol = '└─' if is_last else '├─'
81
- new_prefix = prefix + (' ' if is_last else '│ ' )
82
-
83
- if os .path .isdir (full_path ):
84
- emoji = '📂'
85
- tree_lines .append (f'{ prefix } { symbol } { emoji } { entry } ' )
86
- tree_lines .extend (walk_directory (full_path , depth + 1 , new_prefix ))
87
- else :
88
- emoji = get_file_emoji (entry )
89
- tree_lines .append (f'{ prefix } { symbol } { emoji } { entry } ' )
90
-
91
- return tree_lines
92
-
93
- all_tree_lines = []
94
- for path in include_paths :
95
- if should_exclude (path ):
96
- continue
97
-
98
- if os .path .isfile (path ):
99
- emoji = get_file_emoji (os .path .basename (path ))
100
- all_tree_lines .append (f'{ emoji } { os .path .basename (path )} ' )
101
- elif os .path .isdir (path ):
102
- dir_name = os .path .basename (path .rstrip (os .sep ))
103
- all_tree_lines .append (f'📂 { dir_name } ' )
104
- all_tree_lines .extend (walk_directory (path ))
6
+ SEPARATE_FILES = True
7
+ INCLUDE_PATHS = ['src' , 'pyproject.toml' , 'README.md' , 'LICENSE' , '.pypirc' , '.φc' ]
8
+ EXCLUDE_PATTERNS = ['phicode.egg-info' , '__pycache__' , '.(φ)cache' ]
9
+ OUTPUT_DIR = '.GENERATIONS'
10
+ OUTPUT_FILE = 'PROJECT_TREE.md'
11
+
12
+ FILE_EMOJIS = {
13
+ '.py' : '🐍' , '.js' : '📜' , '.json' : '🔧' , '.txt' : '📄' , '.md' : '📝' , '.html' : '🌐' ,
14
+ '.css' : '🎨' , '.jpg' : '🖼️' , '.jpeg' : '🖼️' , '.png' : '🖼️' , '.gif' : '🖼️' , '.ico' : '🖼️' ,
15
+ '.mp3' : '🎵' , '.wav' : '🎵' , '.mp4' : '🎞️' , '.pdf' : '📕' , '.gdoc' : '🗄️' , '.xlsx' : '🧮' ,
16
+ '.psd' : '🖌️' , '.φ' : '🔱' , '.agent' : '🤖' , '.vsix' : '🔌' ,
17
+ }
18
+
19
+ TEXT_PATTERNS = {
20
+ 'readme' : '📘' , 'license' : '⚖️' , 'receipt' : '🧾' , 'faq' : '❓' , 'rules' : '📖' ,
21
+ 'invitation' : '💌' , 'agenda' : '📅' , 'analytics' : '📈' , 'brainstorming' : '🧠' ,
22
+ 'insights' : '🔎' , 'guidelines' : 'ℹ️' , 'tools' : '🛠️' , 'sponsor' : '💵' ,
23
+ 'finished' : '✅' , 'bot' : '🤖' , 'data' : '📊' ,
24
+ }
25
+
26
+ def get_emoji (filename ):
27
+ filename_lower = filename .lower ()
28
+ for pattern , emoji in TEXT_PATTERNS .items ():
29
+ if pattern in filename_lower :
30
+ return emoji
31
+ return FILE_EMOJIS .get (os .path .splitext (filename )[1 ].lower (), '📄' )
32
+
33
+ def should_exclude (path ):
34
+ return any (excl in path for excl in EXCLUDE_PATTERNS )
35
+
36
+ def build_tree (directory , prefix = '' ):
37
+ if should_exclude (directory ):
38
+ return []
39
+
40
+ try :
41
+ entries = [e for e in os .listdir (directory ) if not should_exclude (os .path .join (directory , e ))]
42
+ except PermissionError :
43
+ return [f"{ prefix } └─ 🔒 [Permission Denied: { os .path .basename (directory )} ]" ]
44
+
45
+ lines = []
46
+ for i , entry in enumerate (entries ):
47
+ full_path = os .path .join (directory , entry )
48
+ is_last = i == len (entries ) - 1
49
+ symbol = '└─' if is_last else '├─'
50
+ new_prefix = prefix + (' ' if is_last else '│ ' )
51
+
52
+ if os .path .isdir (full_path ):
53
+ lines .append (f'{ prefix } { symbol } 📂 { entry } ' )
54
+ lines .extend (build_tree (full_path , new_prefix ))
105
55
else :
106
- all_tree_lines .append (f'❓ [Not found: { path } ] ' )
56
+ lines .append (f'{ prefix } { symbol } { get_emoji ( entry ) } { entry } ' )
107
57
108
- markdown_output = """<img src="https://banes-lab.com/assets/images/banes_lab/700px_Main_Animated.gif" width="70" />
58
+ return lines
109
59
110
- ## 📂 Project Structure
111
- ``` \n """ + ' \n ' . join ( all_tree_lines ) + ' \n ```'
60
+ def create_markdown ( lines , title = " Project Structure" ):
61
+ return f'''<img src="https://banes-lab.com/assets/images/banes_lab/700px_Main_Animated.gif" width="70" />
112
62
113
- with open (output_file , 'w' , encoding = 'utf-8' ) as f :
114
- f .write (markdown_output )
63
+ ## 📂 { title }
64
+ ```
65
+ { chr (10 ).join (lines )}
66
+ ```'''
115
67
116
- print (f'Folder structure has been saved to { output_file } ' )
68
+ def save_file (content , filename ):
69
+ output_path = os .path .join (OUTPUT_DIR , filename ) if SEPARATE_FILES else filename
117
70
71
+ if SEPARATE_FILES :
72
+ os .makedirs (OUTPUT_DIR , exist_ok = True )
118
73
119
- if __name__ == '__main__' :
120
- include_paths = [
121
- 'src' , 'pyproject.toml' , 'README.md' , 'LICENSE' , '.pypirc' , '.φc'
74
+ with open ( output_path , 'w' , encoding = 'utf-8' ) as f :
75
+ f . write ( content )
76
+ print ( f'Structure saved to { output_path } ' )
122
77
123
- ]
78
+ def process_all_subfolders (directory , parent_name = "" ):
79
+ if should_exclude (directory ):
80
+ return
124
81
125
- exclude_specifics = [
126
- 'phicode.egg-info' , '__pycache__' , '.(φ)cache'
127
- ]
128
- save_tree_structure (include_paths , exclude_specifics )
82
+ dir_name = os .path .basename (directory .rstrip (os .sep ))
83
+ full_name = f"{ parent_name } _{ dir_name } " if parent_name else dir_name
84
+
85
+ lines = [f'📂 { dir_name } ' ] + build_tree (directory )
86
+ content = create_markdown (lines , f"Folder: { directory } " )
87
+ save_file (content , f'Folder_{ full_name } .md' )
88
+
89
+ try :
90
+ for entry in os .listdir (directory ):
91
+ full_path = os .path .join (directory , entry )
92
+ if os .path .isdir (full_path ) and not should_exclude (full_path ):
93
+ process_all_subfolders (full_path , full_name )
94
+ except PermissionError :
95
+ pass
96
+
97
+ def main ():
98
+ if SEPARATE_FILES :
99
+ for path in INCLUDE_PATHS :
100
+ if should_exclude (path ):
101
+ continue
102
+
103
+ if os .path .isfile (path ):
104
+ lines = [f'{ get_emoji (os .path .basename (path ))} { os .path .basename (path )} ' ]
105
+ content = create_markdown (lines , f"File: { os .path .basename (path )} " )
106
+ base_name = os .path .splitext (os .path .basename (path ))[0 ]
107
+ save_file (content , f'File_{ base_name } .md' )
108
+ elif os .path .isdir (path ):
109
+ process_all_subfolders (path )
110
+ else :
111
+ lines = [f'❓ [Not found: { path } ]' ]
112
+ content = create_markdown (lines , f"Not Found: { path } " )
113
+ save_file (content , f'NotFound_{ os .path .basename (path )} .md' )
114
+ else :
115
+ all_lines = []
116
+ for path in INCLUDE_PATHS :
117
+ if should_exclude (path ):
118
+ continue
119
+
120
+ if os .path .isfile (path ):
121
+ all_lines .append (f'{ get_emoji (os .path .basename (path ))} { os .path .basename (path )} ' )
122
+ elif os .path .isdir (path ):
123
+ dir_name = os .path .basename (path .rstrip (os .sep ))
124
+ all_lines .append (f'📂 { dir_name } ' )
125
+ all_lines .extend (build_tree (path ))
126
+ else :
127
+ all_lines .append (f'❓ [Not found: { path } ]' )
128
+
129
+ content = create_markdown (all_lines )
130
+ save_file (content , OUTPUT_FILE )
131
+
132
+ if __name__ == '__main__' :
133
+ main ()
0 commit comments