11use crate :: {
2- core:: { cache:: sync_cache, types:: OutputFormat } ,
2+ core:: { cache:: sync_cache, display :: truncate_string , types:: OutputFormat } ,
33 utils:: error:: { Error , Result } ,
44} ;
55use std:: io:: { self , Write } ;
6+ use tabled:: { Table , Tabled } ;
7+
8+ #[ derive( Tabled ) ]
9+ struct OwnerDisplay {
10+ #[ tabled( rename = "Owner" ) ]
11+ identifier : String ,
12+ #[ tabled( rename = "Type" ) ]
13+ owner_type : String ,
14+ #[ tabled( rename = "Files" ) ]
15+ file_count : usize ,
16+ #[ tabled( rename = "Sample Files" ) ]
17+ sample_files : String ,
18+ }
619
720/// Display aggregated owner statistics and associations
821pub ( crate ) fn run (
@@ -14,41 +27,17 @@ pub(crate) fn run(
1427 // Load the cache
1528 let cache = sync_cache ( repo, cache_file) ?;
1629
30+ // Sort owners by number of files they own (descending)
31+ let mut owners_with_counts: Vec < _ > = cache. owners_map . iter ( ) . collect ( ) ;
32+ owners_with_counts. sort_by ( |a, b| b. 1 . len ( ) . cmp ( & a. 1 . len ( ) ) ) ;
33+
1734 // Process the owners from the cache
1835 match format {
1936 OutputFormat :: Text => {
20- // Column widths for the table
21- let owner_width = 35 ; // For owner identifiers
22- let type_width = 10 ; // For owner type
23- let count_width = 10 ; // For file count
24- let file_width = 45 ; // For sample files
25-
26- println ! (
27- "==============================================================================="
28- ) ;
29- println ! (
30- " {:<owner_width$} {:<type_width$} {:<count_width$} {:<file_width$}" ,
31- "Owner" ,
32- "Type" ,
33- "Files" ,
34- "Sample Files" ,
35- owner_width = owner_width,
36- type_width = type_width,
37- count_width = count_width,
38- file_width = file_width
39- ) ;
40- println ! (
41- "==============================================================================="
42- ) ;
43-
44- if cache. owners_map . is_empty ( ) {
45- println ! ( " No owners found in the codebase." ) ;
46- } else {
47- // Sort owners by number of files they own (descending)
48- let mut owners_with_counts: Vec < _ > = cache. owners_map . iter ( ) . collect ( ) ;
49- owners_with_counts. sort_by ( |a, b| b. 1 . len ( ) . cmp ( & a. 1 . len ( ) ) ) ;
50-
51- for ( owner, paths) in owners_with_counts {
37+ // Create table data
38+ let table_data: Vec < OwnerDisplay > = owners_with_counts
39+ . iter ( )
40+ . map ( |( owner, paths) | {
5241 // Prepare sample file list
5342 let file_samples = if paths. is_empty ( ) {
5443 "None" . to_string ( )
@@ -71,37 +60,37 @@ pub(crate) fn run(
7160 display
7261 } ;
7362
74- // Trim the owner identifier if too long
75- let owner_display = if owner. identifier . len ( ) > owner_width {
76- format ! ( "{}..." , & owner. identifier[ 0 ..owner_width - 3 ] )
77- } else {
78- owner. identifier . clone ( )
79- } ;
63+ OwnerDisplay {
64+ identifier : truncate_string ( & owner. identifier , 35 ) ,
65+ owner_type : format ! ( "{:?}" , owner. owner_type) ,
66+ file_count : paths. len ( ) ,
67+ sample_files : truncate_string ( & file_samples, 45 ) ,
68+ }
69+ } )
70+ . collect ( ) ;
71+
72+ // Get terminal width, fallback to 80 if unavailable
73+ let terminal_width =
74+ if let Some ( ( terminal_size:: Width ( w) , _) ) = terminal_size:: terminal_size ( ) {
75+ w as usize
76+ } else {
77+ 80
78+ } ;
79+
80+ let mut table = Table :: new ( table_data) ;
81+ table
82+ . with ( tabled:: settings:: Style :: modern ( ) )
83+ . with ( tabled:: settings:: Width :: wrap (
84+ terminal_width. saturating_sub ( 4 ) ,
85+ ) )
86+ . with ( tabled:: settings:: Padding :: new ( 1 , 1 , 0 , 0 ) ) ;
8087
81- println ! (
82- " {:<owner_width$} {:<type_width$} {:<count_width$} {:<file_width$}" ,
83- owner_display,
84- owner. owner_type,
85- paths. len( ) ,
86- file_samples,
87- owner_width = owner_width,
88- type_width = type_width,
89- count_width = count_width,
90- file_width = file_width
91- ) ;
92- }
93- }
94- println ! (
95- "==============================================================================="
96- ) ;
97- println ! ( " Total: {} owners" , cache. owners_map. len( ) ) ;
98- println ! (
99- "==============================================================================="
100- ) ;
88+ println ! ( "{}" , table) ;
89+ println ! ( "Total: {} owners" , cache. owners_map. len( ) ) ;
10190 }
10291 OutputFormat :: Json => {
10392 // Convert to a more friendly JSON structure
104- let owners_data: Vec < _ > = cache . owners_map . iter ( )
93+ let owners_data: Vec < _ > = owners_with_counts . iter ( )
10594 . map ( |( owner, paths) | {
10695 serde_json:: json!( {
10796 "identifier" : owner. identifier,
@@ -116,7 +105,7 @@ pub(crate) fn run(
116105 }
117106 OutputFormat :: Bincode => {
118107 let encoded =
119- bincode:: serde:: encode_to_vec ( & cache . owners_map , bincode:: config:: standard ( ) )
108+ bincode:: serde:: encode_to_vec ( & owners_with_counts , bincode:: config:: standard ( ) )
120109 . map_err ( |e| Error :: new ( & format ! ( "Serialization error: {}" , e) ) ) ?;
121110
122111 // Write raw binary bytes to stdout
@@ -126,9 +115,5 @@ pub(crate) fn run(
126115 }
127116 }
128117
129- println ! (
130- "Owners listing completed - {} owners found" ,
131- cache. owners_map. len( )
132- ) ;
133118 Ok ( ( ) )
134119}
0 commit comments