1414
1515use std:: io:: IsTerminal ;
1616
17- /// Filled-block NeMo Relay figlet with a per-row right shift so the letters lean italic. Six
18- /// content rows; the renderer prepends one blank row above and appends one below for spacing
19- /// and the docked version tag.
17+ /// Filled-block NeMo Relay figlet generated with ANSI Shadow. Six content rows; the renderer
18+ /// prepends one blank row above and appends one below for spacing and the docked version tag.
2019const BANNER_LINES : & [ & str ] = & [
21- " ███╗ ██╗███████╗███╗ ███╗ ██████╗ ███████╗██╗ █ █████╗ ██╗ ██╗" ,
22- " ████╗ ██║██╔════╝████╗ ████║██╔═══██╗ ██╔════ ╝██║ ██╔═══ ██╗██║ ██║ " ,
23- " ██╔██╗ ██║█████╗ ██╔████╔██║██║ ██║ █████╗ ██║ ██║ ██║██║ █╗██║ " ,
24- " ██║╚██╗██║██╔══╝ ██║╚██╔╝██║██║ ██║ ██╔══╝ ██║ ██║ ██║██║██║██║ " ,
25- " ██║ ╚████║███████╗██║ ╚═╝ ██║╚██████╔╝ ██║ ██ █████╗╚ ██████╔╝╚███╔███╔╝ " ,
26- " ╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═ ═════╝ ╚═════╝ ╚══╝╚═ ═╝" ,
20+ "███╗ ██╗███████╗███╗ ███╗ ██████╗ ██████╗ ███████╗██╗ █████╗ ██╗ ██╗" ,
21+ "████╗ ██║██╔════╝████╗ ████║██╔═══██╗ ██╔══██╗██╔════ ╝██║ ██╔══██╗╚██╗ ██╔╝ " ,
22+ "██╔██╗ ██║█████╗ ██╔████╔██║██║ ██║ ██████╔╝█████ ╗ ██║ ███████║ ╚████╔╝ " ,
23+ "██║╚██╗██║██╔══╝ ██║╚██╔╝██║██║ ██║ ██╔══██╗██╔══ ╝ ██║ ██╔══██ ║ ╚██╔╝ " ,
24+ "██║ ╚████║███████╗██║ ╚═╝ ██║╚██████╔╝ ██║ ██║ ███████╗ ███████╗██║ ██║ ██║ " ,
25+ "╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚ ══════╝ ╚══════╝╚═╝ ╚═╝ ╚ ═╝" ,
2726] ;
2827
2928/// Banner geometry (visual rows including the top and bottom spacing rails).
@@ -32,7 +31,7 @@ const BOTTOM_RAIL: usize = FIGLET_ROWS + 1; // row index of the row below the fi
3231const TOTAL_ROWS : usize = FIGLET_ROWS + 2 ; // top rail + 6 figlet rows + bottom rail
3332
3433/// Version tag position, measured in columns.
35- const COL_END : usize = 92 ; // right edge below "Flow"
34+ const COL_END : usize = 92 ; // version tag dock
3635
3736const MIN_WIDTH : usize = 105 ;
3837
@@ -141,15 +140,35 @@ fn build_grid(width: usize) -> Vec<Vec<char>> {
141140 // Empty top rail, the 6 figlet rows, and an empty bottom rail. Each cell is a single char
142141 // because the figlet's block and box glyphs render as one display column in target terminals.
143142 let mut grid = Vec :: with_capacity ( TOTAL_ROWS ) ;
143+ let art_width = banner_art_width ( ) ;
144+ let start_col = width. saturating_sub ( art_width) / 2 ;
144145 grid. push ( vec ! [ ' ' ; width] ) ;
145- grid. extend ( BANNER_LINES . iter ( ) . map ( |line| padded_row ( line, width) ) ) ;
146+ grid. extend (
147+ BANNER_LINES
148+ . iter ( )
149+ . map ( |line| padded_row ( line, width, start_col) ) ,
150+ ) ;
146151 grid. push ( vec ! [ ' ' ; width] ) ;
147152 grid
148153}
149154
150- fn padded_row ( line : & str , width : usize ) -> Vec < char > {
151- let mut row: Vec < char > = line. chars ( ) . collect ( ) ;
152- row. resize ( width, ' ' ) ;
155+ fn banner_art_width ( ) -> usize {
156+ BANNER_LINES
157+ . iter ( )
158+ . map ( |line| line. chars ( ) . count ( ) )
159+ . max ( )
160+ . unwrap_or ( 0 )
161+ }
162+
163+ fn padded_row ( line : & str , width : usize , start_col : usize ) -> Vec < char > {
164+ let mut row = vec ! [ ' ' ; width] ;
165+
166+ for ( index, ch) in line. chars ( ) . enumerate ( ) {
167+ if let Some ( cell) = row. get_mut ( start_col + index) {
168+ * cell = ch;
169+ }
170+ }
171+
153172 row
154173}
155174
0 commit comments