@@ -33,6 +33,37 @@ class TOONGenerator:
3333 SPECIAL_CHARS = re .compile (r'[:\"\\\[\]\{\}\n\t\r,]' )
3434 LOOKS_LIKE_LITERAL = re .compile (r'^(true|false|null|-?\d+\.?\d*([eE][+-]?\d+)?|-)$' )
3535
36+ LANGUAGE_ABBREVIATIONS = {
37+ 'python' : 'py' ,
38+ 'javascript' : 'js' ,
39+ 'typescript' : 'ts' ,
40+ 'tsx' : 'tsx' ,
41+ 'jsx' : 'jsx' ,
42+ 'java' : 'java' ,
43+ 'kotlin' : 'kt' ,
44+ 'go' : 'go' ,
45+ 'rust' : 'rs' ,
46+ 'c' : 'c' ,
47+ 'cpp' : 'cpp' ,
48+ 'c++' : 'cpp' ,
49+ 'csharp' : 'cs' ,
50+ 'c#' : 'cs' ,
51+ 'php' : 'php' ,
52+ 'ruby' : 'rb' ,
53+ 'swift' : 'swift' ,
54+ 'scala' : 'scala' ,
55+ 'bash' : 'sh' ,
56+ 'shell' : 'sh' ,
57+ 'sql' : 'sql' ,
58+ 'yaml' : 'yaml' ,
59+ 'json' : 'json' ,
60+ 'toml' : 'toml' ,
61+ 'markdown' : 'md' ,
62+ 'html' : 'html' ,
63+ 'css' : 'css' ,
64+ 'dockerfile' : 'docker' ,
65+ }
66+
3667 def __init__ (self , delimiter : str = ',' , use_tabs : bool = False ):
3768 """
3869 Initialize TOON generator.
@@ -46,7 +77,27 @@ def __init__(self, delimiter: str = ',', use_tabs: bool = False):
4677 # parsers/LLMs can read them. Use comma-separated headers regardless of row delimiter.
4778 self .delim_marker = ','
4879
49- def generate (self , project : ProjectInfo , detail : str = 'standard' ) -> str :
80+ def _short_lang (self , lang : str ) -> str :
81+ lang_norm = (lang or '' ).strip ().lower ()
82+ return self .LANGUAGE_ABBREVIATIONS .get (lang_norm , lang )
83+
84+ def _compress_module_path (self , path : str , prev_dir : str | None ) -> tuple [str , str ]:
85+ """Compress repeated directory prefixes for module summary tables.
86+
87+ If consecutive modules are in the same directory, emit './<basename>' instead
88+ of repeating '<dir>/<basename>'. The first entry for a directory stays as the
89+ full path.
90+ """
91+ p = (path or '' )
92+ if '/' not in p :
93+ return p , ''
94+
95+ cur_dir , base = p .rsplit ('/' , 1 )
96+ if prev_dir is not None and cur_dir == prev_dir :
97+ return f"./{ base } " , cur_dir
98+ return p , cur_dir
99+
100+ def generate (self , project : ProjectInfo , detail : str = 'standard' , no_repeat_name : bool = False ) -> str :
50101 """
51102 Generate TOON format from ProjectInfo.
52103
@@ -71,26 +122,33 @@ def generate(self, project: ProjectInfo, detail: str = 'standard') -> str:
71122
72123 # Languages as primitive array
73124 if project .languages :
74- lang_items = [f"{ k } :{ v } " for k , v in project .languages .items ()]
125+ lang_items = [f"{ self . _short_lang ( k ) } :{ v } " for k , v in project .languages .items ()]
75126 lines .append (f" languages[{ len (lang_items )} ]: { self .delimiter .join (lang_items )} " )
76127
77128 # Modules - tabular format for efficiency
78129 if project .modules :
79130 lines .append ("" )
80- lines .extend (self ._generate_modules (project .modules , detail ))
131+ lines .extend (self ._generate_modules (project .modules , detail , no_repeat_name = no_repeat_name ))
81132
82133 return '\n ' .join (lines )
83134
84- def _generate_modules (self , modules : List [ModuleInfo ], detail : str ) -> List [str ]:
135+ def _generate_modules (self , modules : List [ModuleInfo ], detail : str , no_repeat_name : bool = False ) -> List [str ]:
85136 """Generate modules section."""
86137 lines = []
87138
88139 # Module summary as tabular array
89140 lines .append (f"modules[{ len (modules )} ]{{path{ self .delim_marker } lang{ self .delim_marker } lines{ self .delim_marker } kb}}:" )
141+ prev_dir : str | None = None
90142 for m in modules :
91- path = self ._quote (m .path )
143+ if no_repeat_name :
144+ path_out , prev_dir = self ._compress_module_path (m .path , prev_dir )
145+ else :
146+ path_out = m .path
147+ path = self ._quote (path_out )
92148 kb = round ((getattr (m , 'file_bytes' , 0 ) or 0 ) / 1024 , 1 )
93- lines .append (f" { path } { self .delimiter } { m .language } { self .delimiter } { m .lines_code } { self .delimiter } { kb } " )
149+ lines .append (
150+ f" { path } { self .delimiter } { self ._short_lang (m .language )} { self .delimiter } { m .lines_code } { self .delimiter } { kb } "
151+ )
94152
95153 # Detailed module info
96154 if detail in ('standard' , 'full' ):
0 commit comments