Skip to content

Commit 4be9a33

Browse files
committed
Merge remote-tracking branch 'main' into wkk_fern-documentation
Signed-off-by: Will Killian <wkillian@nvidia.com>
2 parents f2ea0c9 + a550c28 commit 4be9a33

2 files changed

Lines changed: 75 additions & 14 deletions

File tree

crates/cli/src/banner.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,15 @@
1414
1515
use 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.
2019
const 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
3231
const 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

3736
const 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

crates/cli/tests/coverage/banner_tests.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,30 @@ fn render_frame_settled_contains_figlet_glyphs() {
88
let frame = render_frame(false);
99
// ANSI Shadow figlet uses filled blocks and box-drawing corners.
1010
assert!(frame.contains('█'), "frame missing figlet block glyph");
11+
assert!(
12+
!frame.contains("_/=|") && !frame.contains("|=\\_") && !frame.contains("╔██╗██╗"),
13+
"frame should not include flag columns"
14+
);
1115
assert!(
1216
frame.contains('╗') || frame.contains('╔'),
1317
"frame missing figlet corners"
1418
);
1519
}
1620

21+
#[test]
22+
fn figlet_rows_are_centered_as_one_block() {
23+
let frame = render_frame(false);
24+
let rows = frame_grid_rows(&frame);
25+
let figlet_rows = &rows[1..=FIGLET_ROWS];
26+
let left_edges: Vec<usize> = figlet_rows.iter().map(|row| first_art_col(row)).collect();
27+
let expected_left_edge = (frame_inner_width(&frame) - banner_art_width()) / 2;
28+
29+
assert!(
30+
left_edges.iter().all(|edge| *edge == expected_left_edge),
31+
"figlet rows should share centered left edge {expected_left_edge}; got {left_edges:?}"
32+
);
33+
}
34+
1735
#[test]
1836
fn render_frame_plain_mode_has_no_ansi_escapes() {
1937
let frame = render_frame(false);
@@ -66,3 +84,27 @@ fn docked_frame_includes_version_tag() {
6684
"docked frame should not include a bullet dot before the version"
6785
);
6886
}
87+
88+
fn frame_grid_rows(frame: &str) -> Vec<&str> {
89+
frame
90+
.lines()
91+
.filter(|line| line.starts_with('│') && line.ends_with('│'))
92+
.map(|line| line.trim_matches('│'))
93+
.collect()
94+
}
95+
96+
fn frame_inner_width(frame: &str) -> usize {
97+
frame
98+
.lines()
99+
.find(|line| line.starts_with('╭'))
100+
.expect("frame should include a top border")
101+
.trim_matches(['╭', '╮'])
102+
.chars()
103+
.count()
104+
}
105+
106+
fn first_art_col(row: &str) -> usize {
107+
row.chars()
108+
.position(|ch| !ch.is_whitespace())
109+
.expect("figlet row should contain art")
110+
}

0 commit comments

Comments
 (0)