use crate::theme::{colors_enabled, rule, ACCENT, ACCENT_DEEP, BOLD, FADE_RAMP, MUTED, PAD, RESET};
#[cfg(test)]
const LOGO_NAME: &str = "ALBATROSS";
const LOGO: &str = r" █████╗ ██╗ ██████╗ █████╗ ████████╗██████╗ ██████╗ ███████╗███████╗
██╔══██╗██║ ██╔══██╗██╔══██╗╚══██╔══╝██╔══██╗██╔═══██╗██╔════╝██╔════╝
███████║██║ ██████╔╝███████║ ██║ ██████╔╝██║ ██║███████╗███████╗
██╔══██║██║ ██╔══██╗██╔══██║ ██║ ██╔══██╗██║ ██║╚════██║╚════██║
██║ ██║███████╗██████╔╝██║ ██║ ██║ ██║ ██║╚██████╔╝███████║███████║
╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝";
pub struct BannerInfo<'a> {
pub model: &'a str,
pub backend: &'a str,
pub approval: &'a str,
}
fn row(label: &str, value: &str) -> String {
format!("{PAD}{MUTED}{label:<9}{RESET}{ACCENT}{value}{RESET}")
}
fn gradient_logo() -> String {
if !colors_enabled() {
return format!("{ACCENT_DEEP}{BOLD}{LOGO}{RESET}");
}
const CYAN_SEGMENT_END: usize = 8;
let lines: Vec<&str> = LOGO.lines().collect();
let last = lines.len().saturating_sub(1).max(1);
let mut out = String::new();
for (i, line) in lines.iter().enumerate() {
let idx = (i * CYAN_SEGMENT_END) / last;
out.push_str(&format!(
"{BOLD}\x1b[38;5;{}m{line}{RESET}\n",
FADE_RAMP[idx]
));
}
out
}
pub fn print_banner(info: BannerInfo<'_>) {
println!();
print!("{}", gradient_logo());
println!();
println!(
"{PAD}{BOLD}Albatross v{}{RESET} {MUTED}— a small, terminal-first coding harness{RESET}",
env!("CARGO_PKG_VERSION")
);
println!("{}", row("backend", info.backend));
println!("{}", row("model", info.model));
println!("{}", row("approval", info.approval));
println!("{}", rule());
println!(
"{PAD}{MUTED}/help{RESET} commands {MUTED}·{RESET} {MUTED}/backend /model{RESET} switch {MUTED}·{RESET} {MUTED}/exit{RESET} quit"
);
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Mutex;
static COLOR_SWITCH_TEST_LOCK: Mutex<()> = Mutex::new(());
fn with_colors(enabled: bool, f: impl FnOnce()) {
let _guard = COLOR_SWITCH_TEST_LOCK.lock().unwrap();
crate::theme::init(
if enabled {
crate::config::ColorMode::Always
} else {
crate::config::ColorMode::Never
},
false,
);
f();
crate::theme::init(crate::config::ColorMode::Always, false);
}
#[test]
fn gradient_logo_has_no_escapes_when_colors_disabled() {
with_colors(false, || {
let logo = gradient_logo();
assert!(!logo.contains('\x1b'));
assert!(logo.contains("███████╗")); assert_eq!(LOGO_NAME, "ALBATROSS");
});
}
#[test]
fn albatross_wordmark_has_uniform_rows() {
let widths = LOGO
.lines()
.map(|line| line.chars().count())
.collect::<Vec<_>>();
assert_eq!(widths.len(), 6);
assert!(widths.windows(2).all(|pair| pair[0] == pair[1]));
}
#[test]
fn gradient_logo_colors_every_line_when_enabled() {
with_colors(true, || {
let logo = gradient_logo();
let line_count = LOGO.lines().count();
assert_eq!(logo.matches("\x1b[38;5;").count(), line_count);
});
}
}