use terminal_size::{terminal_size, Width};
use super::colors::*;
const DEFAULT_TERMINAL_WIDTH: u16 = 80;
const MIN_BANNER_WIDTH: usize = 20;
const MAX_BANNER_WIDTH: usize = 80;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BannerColor {
Cyan,
Green,
Red,
Yellow,
}
impl BannerColor {
pub fn ansi_code(&self) -> &'static str {
match self {
BannerColor::Cyan => CYAN,
BannerColor::Green => GREEN,
BannerColor::Red => RED,
BannerColor::Yellow => YELLOW,
}
}
}
fn get_terminal_width_for_banner() -> usize {
terminal_size()
.map(|(Width(w), _)| w as usize)
.unwrap_or(DEFAULT_TERMINAL_WIDTH as usize)
}
pub fn print_phase_banner(phase_name: &str, color: BannerColor) {
let terminal_width = get_terminal_width_for_banner();
let banner_width = terminal_width.clamp(MIN_BANNER_WIDTH, MAX_BANNER_WIDTH);
let phase_with_spaces = format!(" {} ", phase_name);
let phase_len = phase_with_spaces.chars().count();
let remaining = banner_width.saturating_sub(phase_len);
let left_padding = remaining / 2;
let right_padding = remaining - left_padding;
let color_code = color.ansi_code();
println!(
"{}{BOLD}{}{}{}{}",
color_code,
"━".repeat(left_padding),
phase_with_spaces,
"━".repeat(right_padding),
RESET
);
}
pub fn print_phase_footer(color: BannerColor) {
let terminal_width = get_terminal_width_for_banner();
let banner_width = terminal_width.clamp(MIN_BANNER_WIDTH, MAX_BANNER_WIDTH);
let color_code = color.ansi_code();
println!("{}{BOLD}{}{RESET}", color_code, "━".repeat(banner_width));
println!();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_banner_color_ansi_codes() {
assert_eq!(BannerColor::Cyan.ansi_code(), CYAN);
assert_eq!(BannerColor::Green.ansi_code(), GREEN);
assert_eq!(BannerColor::Red.ansi_code(), RED);
assert_eq!(BannerColor::Yellow.ansi_code(), YELLOW);
}
#[test]
fn test_banner_color_equality() {
assert_eq!(BannerColor::Cyan, BannerColor::Cyan);
assert_ne!(BannerColor::Cyan, BannerColor::Green);
}
#[test]
fn test_get_terminal_width_returns_valid_width() {
let width = get_terminal_width_for_banner();
assert!(width >= MIN_BANNER_WIDTH);
}
#[test]
fn test_banner_width_clamping() {
assert!(MIN_BANNER_WIDTH < MAX_BANNER_WIDTH);
assert_eq!(MIN_BANNER_WIDTH, 20);
assert_eq!(MAX_BANNER_WIDTH, 80);
}
#[test]
fn test_print_phase_banner_all_colors_and_phases() {
let test_cases: &[(&str, BannerColor)] = &[
("RUNNING", BannerColor::Cyan),
("REVIEWING", BannerColor::Cyan),
("CORRECTING", BannerColor::Yellow),
("COMMITTING", BannerColor::Cyan),
("SUCCESS", BannerColor::Green),
("FAILURE", BannerColor::Red),
];
for (phase_name, color) in test_cases {
print_phase_banner(phase_name, *color);
}
}
#[test]
fn test_print_phase_banner_edge_cases() {
print_phase_banner("", BannerColor::Cyan);
print_phase_banner(
"THIS_IS_A_VERY_LONG_PHASE_NAME_THAT_EXCEEDS_NORMAL_LENGTH",
BannerColor::Cyan,
);
}
}