@@ -94,9 +94,69 @@ fn gen_manpage<T: Args>(
9494 cmd
9595 } ;
9696
97+ // Generate the manpage to a buffer first so we can post-process it
98+ let mut buffer = Vec :: new ( ) ;
9799 let man = Man :: new ( command) ;
98- man. render ( & mut io:: stdout ( ) )
99- . expect ( "Man page generation failed" ) ;
100+ man. render ( & mut buffer) . expect ( "Man page generation failed" ) ;
101+
102+ // Convert to string for processing
103+ let mut manpage = String :: from_utf8 ( buffer) . expect ( "Invalid UTF-8 in manpage" ) ;
104+
105+ // Fix the TH line: remove version info from date field and uppercase the command name
106+ if let Some ( th_pos) = manpage. find ( ".TH " ) {
107+ if let Some ( line_end) = manpage[ th_pos..] . find ( '\n' ) {
108+ let th_line = & manpage[ th_pos..th_pos + line_end] ;
109+ // Parse the TH line parts
110+ let parts: Vec < & str > = th_line. split_whitespace ( ) . collect ( ) ;
111+ if parts. len ( ) >= 2 {
112+ let cmd_name = parts[ 1 ] . to_uppercase ( ) ;
113+ // Reconstruct TH line with uppercase command name and no date
114+ let new_th = format ! ( ".TH {} 1" , cmd_name) ;
115+ manpage. replace_range ( th_pos..th_pos + line_end, & new_th) ;
116+ }
117+ }
118+ }
119+
120+ // Remove trailing whitespace from all lines and fix .br issues
121+ let lines: Vec < String > = manpage
122+ . lines ( )
123+ . map ( |line| line. trim_end ( ) . to_string ( ) )
124+ . collect ( ) ;
125+
126+ // Fix .br paragraph macro issues
127+ let mut fixed_lines = Vec :: new ( ) ;
128+ let mut skip_next_br = false ;
129+
130+ for i in 0 ..lines. len ( ) {
131+ let line = & lines[ i] ;
132+
133+ if line == ".br" {
134+ // Check for problematic patterns with .br
135+ let prev_is_br = i > 0 && lines[ i - 1 ] == ".br" ;
136+ let next_is_empty_then_br =
137+ i + 2 < lines. len ( ) && lines[ i + 1 ] . is_empty ( ) && lines[ i + 2 ] == ".br" ;
138+ let prev_is_empty_with_br = i >= 2 && lines[ i - 1 ] . is_empty ( ) && lines[ i - 2 ] == ".br" ;
139+
140+ // Skip redundant .br in these patterns
141+ if skip_next_br || prev_is_br || next_is_empty_then_br || prev_is_empty_with_br {
142+ skip_next_br = false ;
143+ continue ;
144+ }
145+
146+ // If this .br is followed by empty line and another .br, skip the second one
147+ if next_is_empty_then_br {
148+ skip_next_br = true ;
149+ }
150+ }
151+
152+ fixed_lines. push ( line. clone ( ) ) ;
153+ }
154+
155+ manpage = fixed_lines. join ( "\n " ) ;
156+ manpage. push ( '\n' ) ;
157+
158+ // Write the processed manpage to stdout
159+ io:: stdout ( ) . write_all ( manpage. as_bytes ( ) ) . unwrap ( ) ;
100160 io:: stdout ( ) . flush ( ) . unwrap ( ) ;
101161 process:: exit ( 0 ) ;
102162}
0 commit comments