use std::borrow::Cow;
use std::fmt::Write as _;
use std::io::IsTerminal;
const CRAB: [&str; 43] = [
"...................oooooooooo..oooooooooo...................",
"...................owwwwwwhho..owwwwwwhho...................",
"...................owwwwwwhho..owwwwwwhho...................",
"...................owwwwwwhho..owwwwwwhho...................",
"...................ohhhhkkhho..ohhhhkkhho...................",
"...................ohhhhkkhho..ohhhhkkhho...................",
"...................ohhkkkkhho..ohhkkkkhho...................",
"...................ohhkkkkhho..ohhkkkkhho...................",
"...................ohhkkkdhho..ohhkkkdhho...................",
"...................ophhhhhhhoooophhhhhhho...................",
".................whohhhhhhhhoppohhhhhhhho...................",
"...oooo.........wphooooooooooppoooooooooo............oooo...",
"..o.mmmoooo....wwphhhpppppppwppppppppppmooo......oooommmoo..",
".o.phhhpmmo...pwwwhhhpppppppwppppppppppmmmoo.....omphhhpmoo.",
"o.mpppppmmo..ppwwwwwwwwwwwwwwpppppwwwwwbmmmoo....ompppppmmoo",
"oompppppmmo..ppwwwwwwwwwwwwwwpppppwwwwwbbmmmoo...ompppppmm.o",
"o.mmmmmmmbo..pppwwwwwwwwwwwwpppppppppbwwbbmmmoo..ombmmmmmmoo",
"oommmmmmmmo..ppppwwwwwwwwwwppppppppppbwwbbbmmmo..ommmmmmmmo.",
".ommmmmmmmoooppppppppppppppppppppppppbwwbbbmmmoo.ommmmmmmmo.",
".o.dmmmmmo.ooppppppppddppppppppppppppbwwmmbmmmoo.o.mmmmmmdo.",
"..o.omm.ooobobppppppppppmmppppppppppbbbbbbdddddoooo.omm.oo..",
"...ooo.o..obobbppppppppppppppppppppbbddbbbdddddoopoooo.o....",
".....oo...ooobbbbppppppppppppppppbbbbbbbbbdddddodoo..oo.....",
"...........oobbbbbrrrrpppppppppbbbbbbbrrrrdddddooo..........",
"............obbbbbpprrbbbbkbbbbbkbbbbbrrdddddddo............",
"............ombbbbbbbbbbbbbkkkkkbbbbbbbbbbdddddo............",
"............oombbbbbbbbbbbbbbbbbbbbbbbbbbmddddoo............",
"............oommbbbbbbbbbbbbbbbbbbbbbbbbmmddddoo............",
".............ommmbbbbbbbbbbbbbbbbbbbbbbmmmddddo.............",
".............oommmmbbbbbbbbbbbbbbbbbbmmmmmdddoo.............",
"..............oommmmmbbbbbbbbbbbbbbmmmmmmmddoo..............",
"...............oommmmmmmmmmmmmmmmmmmmmmmmmdoo...............",
"................oommmmmmmmmmmmmmmmmmmmmmmmoo................",
".................ooommmmmmmmmdddddddddddooooo...............",
"................oobooommmmmmmdddddddddooooodo...............",
"...............ooboo.oooommmmddddddoooooo.odoo..............",
"..............ooboo..oooooooooooooooodoo..oodoo.............",
"..............oboo....oopoo........oboo....oopoo............",
".............oobo......oopo.......oobo......oopo............",
"............ooboo.......opoo.....ooboo.......opoo...........",
"........owwwwooo........ooowwowwwwooo........ooowwwwo.......",
"........obbbboo..........ooppobbbboo..........ooppppo.......",
"........oooooo............ooooooooo............oooooo.......",
];
const TAGLINE: &str = "Google tools from the terminal, at maximum performance";
const ASCII_BANNER: &str = concat!(
env!("CARGO_PKG_VERSION"),
"\n\n",
" _~^~^~^~_\n",
" \\) / (o) (o) \\ (/\n",
" '_ \\_/ _'\n",
" \\ '-----' /\n",
"Google tools from the terminal, at maximum performance",
);
fn rgb(cell: char) -> Option<[u8; 3]> {
Some(match cell {
'o' => [0x3B, 0x1D, 0x0B],
's' => [0x7C, 0x2D, 0x12],
'd' => [0xC2, 0x41, 0x0C],
'm' => [0xEA, 0x58, 0x0C],
'b' => [0xF9, 0x73, 0x16],
'p' => [0xFF, 0x8A, 0x3D],
'w' => [0xFF, 0xD9, 0xB0],
'h' => [0xFF, 0xF3, 0xE4],
'k' => [0x1A, 0x12, 0x0B],
'r' => [0xEA, 0x43, 0x35],
_ => return None,
})
}
pub fn version_banner() -> Cow<'static, str> {
if !graphics_enabled() {
return Cow::Borrowed(ASCII_BANNER);
}
let mut banner = String::with_capacity(ASCII_BANNER.len() + CRAB.len() * 64);
banner.push_str(env!("CARGO_PKG_VERSION"));
banner.push_str("\n\n");
render_truecolor(&mut banner);
banner.push('\n');
banner.push_str(TAGLINE);
Cow::Owned(banner)
}
fn graphics_enabled() -> bool {
if std::env::var_os("NO_COLOR").is_some() {
return false;
}
if std::env::var("CLICOLOR_FORCE").is_ok_and(|force| force != "0") {
return true;
}
std::io::stdout().is_terminal() && truecolor_signalled(terminal_signals())
}
fn terminal_signals() -> (Option<String>, Option<String>, bool) {
let term = std::env::var("TERM").ok().filter(|value| !value.is_empty());
let colorterm = std::env::var("COLORTERM").ok().filter(|v| !v.is_empty());
(term, colorterm, windows_terminal())
}
fn truecolor_signalled(signals: (Option<String>, Option<String>, bool)) -> bool {
let (term, colorterm, windows_terminal) = signals;
if term.as_deref() == Some("dumb") {
return false;
}
if matches!(colorterm.as_deref(), Some("truecolor" | "24bit")) {
return true;
}
if let Some(term) = term.as_deref()
&& (term.contains("direct") || term.contains("truecolor"))
{
return true;
}
if cfg!(windows) {
return windows_terminal;
}
false
}
#[cfg(windows)]
fn windows_terminal() -> bool {
std::env::var_os("WT_SESSION").is_some()
}
#[cfg(not(windows))]
fn windows_terminal() -> bool {
false
}
fn render_truecolor(out: &mut String) {
let mut foreground: Option<[u8; 3]> = None;
let mut background: Option<[u8; 3]> = None;
for pair in CRAB.chunks(2) {
let top = pair[0].as_bytes();
let bottom = pair.get(1).map(|row| row.as_bytes());
for column in 0..CRAB[0].len() {
let top_pixel = rgb(top[column] as char);
let bottom_pixel = bottom.and_then(|row| rgb(row[column] as char));
if foreground != top_pixel {
foreground = top_pixel;
set_colour(out, 38, top_pixel);
}
if background != bottom_pixel {
background = bottom_pixel;
set_colour(out, 48, bottom_pixel);
}
out.push(if top_pixel.is_none() && bottom_pixel.is_none() {
' '
} else {
UPPER_HALF_BLOCK
});
}
out.push_str(RESET);
out.push('\n');
}
}
fn set_colour(out: &mut String, layer: u8, pixel: Option<[u8; 3]>) {
match pixel {
Some([red, green, blue]) => {
let _ = write!(out, "\u{1b}[{layer};2;{red};{green};{blue}m");
}
None => {
let _ = write!(out, "\u{1b}[{}m", layer + 1);
}
}
}
const UPPER_HALF_BLOCK: char = '\u{2580}';
const RESET: &str = "\u{1b}[0m";
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_pixel_cell_maps_to_a_colour() {
for (row_index, row) in CRAB.iter().enumerate() {
for (column_index, cell) in row.chars().enumerate() {
if cell != '.' && rgb(cell).is_none() {
panic!("CRAB[{row_index}][{column_index}] = {cell:?} has no palette arm");
}
}
}
}
#[test]
fn the_map_is_a_rectangular_grid() {
assert!(!CRAB.is_empty());
let width = CRAB[0].len();
for row in CRAB {
assert_eq!(row.len(), width, "ragged crab row: {row:?}");
}
assert_eq!(CRAB.len().div_ceil(2), 22);
}
#[test]
fn the_colour_render_draws_every_row_as_a_reset_terminated_line() {
let mut rendered = String::new();
render_truecolor(&mut rendered);
let lines: Vec<&str> = rendered.lines().collect();
assert_eq!(lines.len(), CRAB.len().div_ceil(2));
let widest = lines[CRAB.len() / 2 - 1];
assert!(widest.contains(UPPER_HALF_BLOCK));
for line in lines {
assert!(line.ends_with(RESET), "row not reset: {line:?}");
assert!(line.contains(UPPER_HALF_BLOCK));
}
}
#[test]
fn truecolor_is_detected_from_the_documented_signals() {
let absent = (None, None, false);
assert!(!truecolor_signalled(absent));
assert!(truecolor_signalled((None, Some("truecolor".into()), false)));
assert!(truecolor_signalled((None, Some("24bit".into()), false)));
assert!(truecolor_signalled((
Some("foot-direct".into()),
None,
false
)));
assert!(!truecolor_signalled((
Some("xterm-kitty".into()),
None,
false
)));
assert!(truecolor_signalled((
Some("xterm-kitty".into()),
Some("truecolor".into()),
false
)));
assert!(!truecolor_signalled((None, Some(String::new()), false)));
assert!(!truecolor_signalled((
Some("dumb".into()),
Some("truecolor".into()),
false
)));
}
#[test]
fn the_plain_banner_keeps_semver_first_and_the_crab_intact() {
let banner = version_banner();
let first_line = banner.lines().next().expect("banner has a first line");
assert_eq!(first_line, env!("CARGO_PKG_VERSION"));
assert!(banner.contains("(o) (o)"));
assert!(banner.contains("\\_/"));
assert!(banner.ends_with(TAGLINE));
}
}