cstat/demo_glossary.rs

2124 lines
86 KiB
Rust
Raw Permalink Normal View History

// rustc demo_glossary.rs -o demo_glossary && ./demo_glossary
// Full glossary of terminal rendering primitives
fn main() {
println!("\n{}", "═".repeat(70));
println!(" TERMINAL RENDERING GLOSSARY — COMPLETE CATALOG");
println!("{}\n", "═".repeat(70));
section_pixel_blocks();
section_line_drawing();
section_color_and_style();
section_palettes();
section_chart_primitives();
section_text_symbols();
section_layout_patterns();
section_terminal_features();
section_distribution_viz();
section_comparison_viz();
section_relational_viz();
section_matrix_grid_viz();
section_part_to_whole_viz();
section_temporal_viz();
section_text_integrated_viz();
}
// ── Helpers ──────────────────────────────────────────────────────────
fn fg(r: u8, g: u8, b: u8, text: &str) -> String {
format!("\x1b[38;2;{};{};{}m{}\x1b[0m", r, g, b, text)
}
fn bg(r: u8, g: u8, b: u8, text: &str) -> String {
format!("\x1b[48;2;{};{};{}m{}\x1b[0m", r, g, b, text)
}
fn fgbg(fr: u8, fgg: u8, fb: u8, br: u8, bgg: u8, bb: u8, text: &str) -> String {
format!("\x1b[38;2;{};{};{}m\x1b[48;2;{};{};{}m{}\x1b[0m", fr, fgg, fb, br, bgg, bb, text)
}
fn lerp(c1: (u8,u8,u8), c2: (u8,u8,u8), t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
(
(c1.0 as f64 + (c2.0 as f64 - c1.0 as f64) * t) as u8,
(c1.1 as f64 + (c2.1 as f64 - c1.1 as f64) * t) as u8,
(c1.2 as f64 + (c2.2 as f64 - c1.2 as f64) * t) as u8,
)
}
fn heat(t: f64) -> (u8,u8,u8) {
if t < 0.5 { lerp((80,200,120),(240,200,60),t*2.0) }
else { lerp((240,200,60),(220,60,60),(t-0.5)*2.0) }
}
fn viridis(t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
let s = [(0.0,(68,1,84)),(0.25,(59,82,139)),(0.5,(33,145,140)),(0.75,(94,201,98)),(1.0,(253,231,37))];
for i in 0..s.len()-1 { if t <= s[i+1].0 { return lerp(s[i].1,s[i+1].1,(t-s[i].0)/(s[i+1].0-s[i].0)); } }
s[4].1
}
fn magma(t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
let s = [(0.0,(0,0,4)),(0.25,(81,18,124)),(0.5,(183,55,121)),(0.75,(252,137,97)),(1.0,(252,253,191))];
for i in 0..s.len()-1 { if t <= s[i+1].0 { return lerp(s[i].1,s[i+1].1,(t-s[i].0)/(s[i+1].0-s[i].0)); } }
s[4].1
}
fn inferno(t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
let s = [(0.0,(0,0,4)),(0.25,(87,16,110)),(0.5,(188,55,84)),(0.75,(249,142,9)),(1.0,(252,255,164))];
for i in 0..s.len()-1 { if t <= s[i+1].0 { return lerp(s[i].1,s[i+1].1,(t-s[i].0)/(s[i+1].0-s[i].0)); } }
s[4].1
}
fn plasma(t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
let s = [(0.0,(13,8,135)),(0.25,(126,3,168)),(0.5,(204,71,120)),(0.75,(248,149,64)),(1.0,(240,249,33))];
for i in 0..s.len()-1 { if t <= s[i+1].0 { return lerp(s[i].1,s[i+1].1,(t-s[i].0)/(s[i+1].0-s[i].0)); } }
s[4].1
}
fn cividis(t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
let s = [(0.0,(0,32,77)),(0.25,(60,77,110)),(0.5,(127,127,127)),(0.75,(186,173,107)),(1.0,(255,234,70))];
for i in 0..s.len()-1 { if t <= s[i+1].0 { return lerp(s[i].1,s[i+1].1,(t-s[i].0)/(s[i+1].0-s[i].0)); } }
s[4].1
}
fn coolwarm(t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
let s = [(0.0,(59,76,192)),(0.25,(124,159,230)),(0.5,(221,221,221)),(0.75,(230,145,113)),(1.0,(180,4,38))];
for i in 0..s.len()-1 { if t <= s[i+1].0 { return lerp(s[i].1,s[i+1].1,(t-s[i].0)/(s[i+1].0-s[i].0)); } }
s[4].1
}
fn turbo(t: f64) -> (u8,u8,u8) {
let t = t.clamp(0.0, 1.0);
let s = [(0.0,(48,18,59)),(0.17,(69,117,180)),(0.33,(64,190,166)),(0.5,(145,224,79)),(0.67,(241,187,41)),(0.83,(237,105,37)),(1.0,(122,4,3))];
for i in 0..s.len()-1 { if t <= s[i+1].0 { return lerp(s[i].1,s[i+1].1,(t-s[i].0)/(s[i+1].0-s[i].0)); } }
s[6].1
}
fn heading(id: &str, title: &str) {
println!("\n\x1b[1;96m╔{}╗\x1b[0m", "═".repeat(68));
println!("\x1b[1;96m║\x1b[0m \x1b[1;97m{}\x1b[0m. \x1b[1;93m{:<62}\x1b[0m\x1b[1;96m║\x1b[0m", id, title);
println!("\x1b[1;96m╚{}╝\x1b[0m\n", "═".repeat(68));
}
fn sub(id: &str, name: &str, desc: &str) {
println!(" \x1b[1;33m{}.\x1b[0m \x1b[1m{}\x1b[0m", id, name);
println!(" \x1b[2m{}\x1b[0m", desc);
}
// =====================================================================
// A. PIXEL/BLOCK ELEMENTS
// =====================================================================
fn section_pixel_blocks() {
heading("A", "PIXEL / BLOCK ELEMENTS");
// A1: Horizontal fractional blocks
sub("A1", "Horizontal Fractional Blocks", "Sub-character bar precision (8 levels per cell)");
println!(" chars: █ ▉ ▊ ▋ ▌ ▍ ▎ ▏");
print!(" demo: ");
let fracs = ['█','▉','▊','▋','▌','▍','▎','▏'];
for (i, &c) in fracs.iter().enumerate() {
let t = i as f64 / 7.0;
let (r,g,b) = heat(1.0 - t);
print!("{}", fg(r,g,b, &format!("{} ", c)));
}
println!();
print!(" bar: ");
for i in 0..30 {
let t = i as f64 / 29.0;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b,"█"));
}
print!("{}",fg(94,201,98,"▌"));
println!(" ← fractional end cap");
println!();
// A2: Vertical block elements (sparkline chars)
sub("A2", "Vertical Block Elements", "Height encoding (8 levels per cell, used in sparklines)");
println!(" chars: ▁ ▂ ▃ ▄ ▅ ▆ ▇ █");
let vblocks = ['▁','▂','▃','▄','▅','▆','▇','█'];
print!(" demo: ");
let vals = [1,3,5,8,6,4,7,8,5,3,2,4,6,8,7,5,3,2,1,3,5,7,8,6,4,2,1,2,4,6];
for &v in &vals {
let t = v as f64 / 8.0;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, &vblocks[(v-1) as usize].to_string()));
}
println!();
println!();
// A3: Half blocks
sub("A3", "Half Blocks (▀ ▄)", "2 vertical pixels per cell — doubles vertical resolution");
println!(" chars: ▀ (upper) ▄ (lower) █ (both)");
print!(" demo: ");
// Show a mini gradient with 2 rows packed per line
for i in 0..30 {
let t_top = i as f64 / 29.0;
let t_bot = (i as f64 + 0.5) / 29.0;
let top = viridis(t_top);
let bot = viridis(t_bot.min(1.0));
print!("{}", fgbg(top.0,top.1,top.2, bot.0,bot.1,bot.2, "▀"));
}
println!(" ← 2 color rows in 1 line");
// Show as mini heatmap
print!(" matrix: ");
let cells = [[0.1,0.3,0.8,0.9],[0.2,0.5,0.7,0.4],[0.6,0.2,0.1,0.3],[0.9,0.8,0.4,0.2]];
for pair in cells.chunks(2) {
for col in 0..4 {
let top = viridis(pair[0][col]);
let bot = if pair.len() > 1 { viridis(pair[1][col]) } else { (0,0,0) };
print!("{}", fgbg(top.0,top.1,top.2, bot.0,bot.1,bot.2, "▀▀"));
}
print!(" ");
}
println!("← 4×4 matrix in 2 lines");
println!();
// A4: Quadrant blocks
sub("A4", "Quadrant Blocks", "2×2 pixel grid per cell (4 sub-pixels)");
println!(" chars: ▖ ▗ ▘ ▙ ▚ ▛ ▜ ▝ ▌ ▐ ▀ ▄ █ (space)");
let quads = [' ','▘','▝','▀','▖','▌','▞','▛','▗','▚','▐','▜','▄','▙','▟','█'];
print!(" all: ");
for (i, &q) in quads.iter().enumerate() {
let t = i as f64 / 15.0;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, &format!("{} ", q)));
}
println!();
print!(" pattern:");
let pattern = "▘▀▜█▛▀▘ ▖▄▟█▙▄▖ ";
for ch in pattern.chars() {
print!("{}", fg(100,180,255, &ch.to_string()));
}
println!();
println!();
// A5: Braille patterns
sub("A5", "Braille Patterns", "2×4 pixel grid per cell (8 sub-pixels, 256 combinations)");
println!(" base: U+2800, bits: ⠁⠂⠄⡀ (left col) ⠈⠐⠠⢀ (right col)");
print!(" gradient: ");
let braille_densities: [u8; 9] = [0x00, 0x40, 0x44, 0x64, 0x66, 0x76, 0x77, 0xF7, 0xFF];
for &b in &braille_densities {
let ch = char::from_u32(0x2800 + b as u32).unwrap();
print!("{} ", fg(100,180,255, &ch.to_string()));
}
println!(" (empty → full)");
// Mini scatter
print!(" scatter: ");
let mut seed: u64 = 42;
let mut canvas = [[0u8; 25]; 6]; // 6 rows × 25 cols of braille cells
for _ in 0..120 {
seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
let x = ((seed >> 33) as f64 / u32::MAX as f64 * 50.0) as usize; // pixel x
seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
let raw_y = (seed >> 33) as f64 / u32::MAX as f64;
let y = (raw_y * raw_y * 24.0) as usize; // pixel y, clustered low
let cx = x / 2; let cy = y / 4;
if cx < 25 && cy < 6 {
let lx = x % 2; let ly = y % 4;
let bit = match (lx, ly) { (0,0)=>0,(0,1)=>1,(0,2)=>2,(0,3)=>6,(1,0)=>3,(1,1)=>4,(1,2)=>5,(1,3)=>7,_=>0 };
canvas[cy][cx] |= 1 << bit;
}
}
for row in 0..6 {
if row > 0 { print!(" "); }
for col in 0..25 {
let ch = char::from_u32(0x2800 + canvas[row][col] as u32).unwrap();
if canvas[row][col] == 0 { print!("\x1b[2m·\x1b[0m"); }
else { print!("{}", fg(80,200,120, &ch.to_string())); }
}
println!();
}
println!();
// A6: Shade blocks
sub("A6", "Shade/Fill Blocks", "4 density levels for area fills and backgrounds");
println!(" chars: ░ (light 25%) ▒ (medium 50%) ▓ (dark 75%) █ (full)");
print!(" demo: ");
let shades = ['░','▒','▓','█'];
for &s in &shades {
let t = match s { '░'=>0.25,'▒'=>0.5,'▓'=>0.75,_=>1.0 };
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, &format!("{}{}{} ", s, s, s)));
}
println!();
// Show as background fill
print!(" fill: ");
print!("{}",bg(40,40,60," empty "));
print!("{}",bg(60,60,80," ░░░25%░░░ "));
print!("{}",bg(80,80,100," ▒▒50%▒▒ "));
print!("{}",bg(100,100,120," ▓▓75%▓▓ "));
print!("{}",bg(120,120,140," ██100%██ "));
println!();
println!();
// A7: Block sextants (Unicode 13.0)
sub("A7", "Block Sextants (Unicode 13.0+)", "2×3 pixel grid per cell (64 combinations). Newer — check terminal support.");
println!(" chars: 🬀🬁🬂🬃🬄🬅🬆🬇🬈🬉🬊🬋🬌🬍🬎🬏🬐🬑🬒🬓🬔🬕🬖🬗🬘🬙🬚🬛🬜🬝🬞🬟🬠🬡🬢🬣🬤🬥🬦🬧🬨🬩🬪🬫🬬🬭🬮🬯🬰🬱🬲🬳🬴🬵🬶🬷🬸🬹🬺🬻");
print!(" sample: ");
let sextants = ['🬀','🬁','🬃','🬇','🬏','🬟','🬯','🬻'];
for &s in &sextants {
print!("{} ", fg(100,180,255, &s.to_string()));
}
println!(" (empty → full, may not render in all terminals)");
println!();
// A8: Left/Right half blocks
sub("A8", "Left/Right Half Blocks", "2 horizontal pixels per cell");
println!(" chars: ▌ (left half) ▐ (right half)");
print!(" demo: ");
for i in 0..20 {
let t = i as f64 / 19.0;
let left = viridis(t);
let right = viridis((t + 0.025).min(1.0));
print!("{}", fgbg(left.0,left.1,left.2, right.0,right.1,right.2, "▌"));
}
println!(" ← 40 color columns in 20 chars");
println!();
}
// =====================================================================
// B. LINE DRAWING
// =====================================================================
fn section_line_drawing() {
heading("B", "LINE / BOX DRAWING");
sub("B1", "Thin Lines", "Standard box-drawing (current cstat style)");
println!(" ┌───┬───┐");
println!(" │ │ │");
println!(" ├───┼───┤");
println!(" │ │ │");
println!(" └───┴───┘");
println!();
sub("B2", "Rounded Corners", "Softer look, same weight");
println!(" ╭───┬───╮");
println!(" │ │ │");
println!(" ├───┼───┤");
println!(" │ │ │");
println!(" ╰───┴───╯");
println!();
sub("B3", "Heavy/Thick Lines", "For emphasis or outer borders");
println!(" ┏━━━┳━━━┓");
println!(" ┃ ┃ ┃");
println!(" ┣━━━╋━━━┫");
println!(" ┃ ┃ ┃");
println!(" ┗━━━┻━━━┛");
println!();
sub("B4", "Double Lines", "For major section boundaries");
println!(" ╔═══╦═══╗");
println!(" ║ ║ ║");
println!(" ╠═══╬═══╣");
println!(" ║ ║ ║");
println!(" ╚═══╩═══╝");
println!();
sub("B5", "Mixed Weight", "Heavy outer, thin inner — visual hierarchy");
println!(" ┏━━━┯━━━┓");
println!(" ┃ │ ┃");
println!(" ┠───┼───┨");
println!(" ┃ │ ┃");
println!(" ┗━━━┷━━━┛");
println!();
sub("B6", "Dashed/Dotted Lines", "For optional/weak connections");
println!(" ╌╌╌ dashed thin ┄┄┄ dotted thin");
println!(" ╍╍╍ dashed heavy ┅┅┅ dotted heavy");
println!(" ┆ dashed thin vert ┇ dashed heavy vert");
println!(" ┈┈┈ more dotted ┉┉┉ more dashed heavy");
println!();
sub("B7", "Diagonal Lines", "For crossings, X marks, slashes");
println!(" chars: ╱ ╲ ╳");
println!(" ╱╲╱╲╱╲ ╳╳╳╳");
println!(" ╲╱╲╱╲╱ ╳╳╳╳");
println!();
sub("B8", "Arc Corners", "For connecting curved paths");
println!(" ╭─╮ ╭──────╮");
println!(" │ │ │ text │");
println!(" │ ╰────╯ │");
println!(" ╰─────────────╯");
println!();
}
// =====================================================================
// C. COLOR AND STYLE
// =====================================================================
fn section_color_and_style() {
heading("C", "COLOR & STYLE MODES");
sub("C1", "Basic 8-Color", "Maximum compatibility (current cstat approach)");
print!(" ");
for (name, code) in [("black",30),("red",31),("green",32),("yellow",33),("blue",34),("magenta",35),("cyan",36),("white",37)] {
print!("\x1b[{}m{}\x1b[0m ", code, name);
}
println!();
println!();
sub("C2", "Bright/Bold 8-Color", "16 colors total with bright variants");
print!(" ");
for code in 90..=97 {
print!("\x1b[{}m████\x1b[0m", code);
}
println!();
println!();
sub("C3", "256-Color (8-bit)", "Wider palette, good compatibility");
print!(" ");
for i in (16..232).step_by(6) {
print!("\x1b[38;5;{}m█\x1b[0m", i);
}
println!();
print!(" ");
for i in 232..=255 {
print!("\x1b[38;5;{}m█\x1b[0m", i);
}
println!(" ← grayscale ramp");
println!();
sub("C4", "True Color (24-bit)", "16.7 million colors, smooth gradients");
print!(" ");
for i in 0..60 {
let t = i as f64 / 59.0;
let r = (t * 255.0) as u8;
let g = ((1.0 - (t - 0.5).abs() * 2.0).max(0.0) * 255.0) as u8;
let b = ((1.0 - t) * 255.0) as u8;
print!("{}", fg(r, g, b, "█"));
}
println!();
println!();
sub("C5", "Text Styles", "Decorations available via ANSI SGR codes");
println!(" \x1b[1mbold\x1b[0m \x1b[2mdim\x1b[0m \x1b[3mitalic\x1b[0m \x1b[4munderline\x1b[0m \x1b[9mstrikethrough\x1b[0m \x1b[7mreverse\x1b[0m \x1b[53moverline\x1b[0m");
println!();
sub("C6", "Colored Underlines", "Underline with independent color (modern terminals)");
println!(" \x1b[4m\x1b[58;2;255;80;80mred underline\x1b[0m \x1b[4m\x1b[58;2;80;255;80mgreen underline\x1b[0m \x1b[4m\x1b[58;2;80;80;255mblue underline\x1b[0m");
println!(" \x1b[4:3m\x1b[58;2;255;180;0mcurly/wavy underline\x1b[0m \x1b[4:4m\x1b[58;2;100;200;255mdotted underline\x1b[0m \x1b[4:5m\x1b[58;2;200;100;255mdashed underline\x1b[0m");
println!();
sub("C7", "Combined Foreground + Background", "Text on colored backgrounds for cells/badges");
print!(" ");
print!("{} ", fgbg(255,255,255, 220,60,60, " CRITICAL "));
print!("{} ", fgbg(0,0,0, 240,200,60, " WARNING "));
print!("{} ", fgbg(255,255,255, 80,200,120, " OK "));
print!("{} ", fgbg(200,200,200, 60,60,80, " INFO "));
println!();
println!();
}
// =====================================================================
// D. COLOR PALETTES
// =====================================================================
fn section_palettes() {
heading("D", "COLOR PALETTES");
let palettes: Vec<(&str, fn(f64)->(u8,u8,u8), &str)> = vec![
("heat", heat, "red←bad good→green (current intent, but smooth)"),
("viridis", viridis, "perceptually uniform, colorblind-safe"),
("magma", magma, "dark→hot, high contrast on dark backgrounds"),
("inferno", inferno, "similar to magma, more yellow"),
("plasma", plasma, "purple→yellow, vivid"),
("cividis", cividis, "blue→yellow, fully colorblind-safe"),
("coolwarm",coolwarm, "diverging: blue=low, neutral=mid, red=high"),
("turbo", turbo, "rainbow-like, high contrast (not perceptually uniform)"),
];
for (i, (name, pal, desc)) in palettes.iter().enumerate() {
print!(" \x1b[1;33mD{}.\x1b[0m {:<10}", i+1, name);
for j in 0..50 {
let t = j as f64 / 49.0;
let (r,g,b) = pal(t);
print!("{}", fg(r,g,b, "█"));
}
println!();
println!(" \x1b[2m{}\x1b[0m", desc);
}
println!("\n \x1b[1;33mD9.\x1b[0m \x1b[1mCustom semantic\x1b[0m");
println!(" \x1b[2mMap meaning to color, not just position\x1b[0m");
print!(" ");
// Semantic: green=safe, yellow=caution, red=danger, with smooth blending
let semantic = [(0.0,(40,160,80)),(0.3,(40,160,80)),(0.5,(220,200,40)),(0.7,(220,200,40)),(0.85,(200,60,60)),(1.0,(200,60,60))];
for j in 0..50 {
let t = j as f64 / 49.0;
let mut c = semantic[0].1;
for k in 0..semantic.len()-1 {
if t >= semantic[k].0 && t <= semantic[k+1].0 {
let local = (t - semantic[k].0) / (semantic[k+1].0 - semantic[k].0);
c = lerp(semantic[k].1, semantic[k+1].1, local);
break;
}
}
print!("{}", fg(c.0,c.1,c.2, "█"));
}
println!(" safe──caution──danger");
println!();
}
// =====================================================================
// E. CHART PRIMITIVES
// =====================================================================
fn section_chart_primitives() {
heading("E", "CHART / VISUALIZATION PRIMITIVES");
// E1: Horizontal bar variants
sub("E1", "Horizontal Bar Variants", "Different fill styles for bars");
let _w = 30.0_f64;
let fills: [(&str, &str); 6] = [
("solid", "█"),
("shade-grad",""), // special
("dotted", "⣿"),
("hash", "▓"),
("half", "▌"),
("pipe", "┃"),
];
for (name, ch) in &fills {
print!(" {:<12}", name);
if *name == "shade-grad" {
let shades = ['░','▒','▓','█'];
for i in 0..30 {
let t = i as f64 / 29.0;
let idx = (t * 3.0).round() as usize;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, &shades[idx.min(3)].to_string()));
}
} else {
for i in 0..30 {
let t = i as f64 / 29.0;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, ch));
}
}
println!();
}
println!();
// E2: Stacked bars
sub("E2", "Stacked Bars", "Multiple values in one bar row");
let stacks = [
("module_a", vec![(12, (80,200,120)), (8, (100,180,255)), (3, (240,200,60))]),
("module_b", vec![(20, (80,200,120)), (5, (100,180,255)), (1, (240,200,60))]),
("module_c", vec![(6, (80,200,120)), (15,(100,180,255)), (10,(240,200,60))]),
];
for (name, segments) in &stacks {
print!(" {:<12}", name);
for (len, (r,g,b)) in segments {
print!("{}", fg(*r,*g,*b, &"█".repeat(*len)));
}
println!();
}
print!(" {:<12}", "");
print!("{} code ", fg(80,200,120, "██"));
print!("{} tests ", fg(100,180,255, "██"));
print!("{} docs", fg(240,200,60, "██"));
println!();
println!();
// E3: Grouped bars
sub("E3", "Grouped Bars", "Side-by-side comparison per category");
let groups = [("v1.0", 15), ("v1.1", 22), ("v2.0", 18)];
let colors = [(220,80,80),(80,200,120),(100,180,255)];
for (i, (label, val)) in groups.iter().enumerate() {
let (r,g,b) = colors[i];
println!(" {:<6} {} {}", label, fg(r,g,b, &"█".repeat(*val)), val);
}
println!();
// E4: Vertical bars (column chart)
sub("E4", "Vertical Column Charts", "Bottom-up using vertical block chars");
let col_vals = [3,7,5,8,4,6,2,7,5,3,6,8,4,5,7,3];
let max_h = 8;
for row in (1..=max_h).rev() {
print!(" ");
for &v in &col_vals {
if v >= row {
let t = v as f64 / max_h as f64;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, "██"));
} else if v == row - 1 {
// fractional top
let t = v as f64 / max_h as f64;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, "▄ "));
} else {
print!(" ");
}
}
println!();
}
print!(" ");
for _ in &col_vals { print!("──"); }
println!();
println!();
// E5: Gauge/meter
sub("E5", "Gauge / Progress Meter", "Bounded bar with track");
let gauges = [("Health", 0.78), ("Coverage", 0.45), ("Coupling", 0.92)];
for (label, val) in &gauges {
let filled = (*val * 25.0) as usize;
let empty = 25 - filled;
let (r,g,b) = heat(*val);
let bar = format!("{}{}",
fg(r,g,b, &"█".repeat(filled)),
"\x1b[2m░\x1b[0m".repeat(empty));
println!(" {:<12} [{}] {:>5.1}%", label, bar, val * 100.0);
}
println!();
// E6: Waffle/grid chart
sub("E6", "Waffle Chart", "Grid of filled/empty squares showing proportion");
let total = 100;
let filled_count = 73;
print!(" 73/100: ");
for i in 0..total {
if i > 0 && i % 25 == 0 { print!(" "); }
if i < filled_count {
let t = i as f64 / total as f64;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, "■"));
} else {
print!("\x1b[2m□\x1b[0m");
}
}
println!();
println!();
// E7: Dot matrix / LED digits
sub("E7", "Large Numeral Display", "Big digits for hero metrics using braille/blocks");
// Simple 3x5 font
let digits_3x5: [&[&str]; 10] = [
&["▄█▄","█ █","█ █","█ █","▀█▀"], // 0
&[" █ "," █ "," █ "," █ "," █ "], // 1
&["▄█▄"," █","▄█▄","█ ","▀█▀"], // 2
&["▄█▄"," █","▄█▄"," █","▀█▀"], // 3
&["█ █","█ █","▀█▀"," █"," █"], // 4
&["▀█▀","█ ","▀█▀"," █","▄█▄"], // 5
&["▄█▄","█ ","██▄","█ █","▀█▀"], // 6
&["▀█▀"," █"," █"," █"," █"], // 7
&["▄█▄","█ █","▄█▄","█ █","▀█▀"], // 8
&["▄█▄","█ █","▀██"," █","▀█▀"], // 9
];
let number = [7, 8]; // display "78"
for row in 0..5 {
print!(" ");
for &d in &number {
print!("{} ", fg(253,231,37, digits_3x5[d][row]));
}
println!();
}
println!(" \x1b[2m(hero score display)\x1b[0m");
println!();
// E8: Flame chart style
sub("E8", "Flame / Waterfall Bars", "Nested indented colored bars showing hierarchy/depth");
let flames = [
(0, "main()", 40),
(1, "analyze()", 35),
(2, "parse_all()", 20),
(3, "parse_file()", 15),
(2, "compute_metrics()", 12),
(1, "render()", 5),
];
for (depth, name, width) in &flames {
let indent = " ".repeat(*depth);
let t = *depth as f64 / 3.0;
let (r,g,b) = inferno(0.3 + t * 0.5);
print!(" {}", indent);
for _ in 0..*width { print!("{}", fg(r,g,b, "▓")); }
println!(" {}", name);
}
println!();
// E9: Trend arrows / indicators
sub("E9", "Trend Indicators", "Compact directional symbols for changes");
println!(" ↑ ↗ → ↘ ↓ (arrows)");
println!(" ▲ △ ▶ ▽ ▼ (triangles)");
println!(" {} {} {} {} {}",
fg(220,60,60, "▲+15%"),
fg(220,60,60, "↑ 8%"),
fg(150,150,150, "→ 0%"),
fg(80,200,120, "↓ 3%"),
fg(80,200,120, "▼-12%"),
);
println!();
// E10: Area under sparkline
sub("E10", "Filled Sparklines", "Sparkline with area fill underneath");
let spark_vals = [2,4,3,6,8,7,5,8,6,4,3,5,7,8,6,4,2,3,5,7,6,4,3,2,4,6,7,5,3,2];
let max_v = 8;
let blocks = ['▁','▂','▃','▄','▅','▆','▇','█'];
print!(" line: ");
for &v in &spark_vals {
let t = v as f64 / max_v as f64;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, &blocks[((v-1) as usize).min(7)].to_string()));
}
println!();
print!(" filled: ");
for &v in &spark_vals {
let t = v as f64 / max_v as f64;
let top = viridis(t);
let bot = viridis(t * 0.5);
print!("{}", fgbg(top.0,top.1,top.2, bot.0,bot.1,bot.2, &blocks[((v-1) as usize).min(7)].to_string()));
}
println!();
println!();
// E11: Box plot
sub("E11", "Inline Box Plot", "Min, Q1, median, Q3, max in one line");
// ├──────┤ ╞══════╡ │ ┣━━━╋━━━┫
print!(" ");
print!("\x1b[2m├──────\x1b[0m");
print!("{}", fg(100,180,255, "┤█████████"));
print!("{}", fg(253,231,37, "│"));
print!("{}", fg(100,180,255, "██████████┤"));
print!("\x1b[2m──────────┤\x1b[0m");
println!();
println!(" \x1b[2mmin Q1 med Q3 max\x1b[0m");
println!();
// E12: Dot strip / strip plot
sub("E12", "Dot/Strip Plot", "Individual data points on a number line");
print!(" \x1b[2m0\x1b[0m");
let dots = [3,5,5,6,8,8,8,12,14,15,15,16,18,22,25,30];
let max_d = 35;
let mut line = vec![' '; max_d + 1];
for &d in &dots {
line[d] = '●';
}
for (i, &ch) in line.iter().enumerate() {
if ch == '●' {
let t = i as f64 / max_d as f64;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, "●"));
} else {
print!("\x1b[2m·\x1b[0m");
}
}
println!(" \x1b[2m{}\x1b[0m", max_d);
println!();
}
// =====================================================================
// F. TEXT & SYMBOL ELEMENTS
// =====================================================================
fn section_text_symbols() {
heading("F", "TEXT & SYMBOL ELEMENTS");
sub("F1", "Status Indicators", "Semantic symbols for pass/fail/warn states");
println!(" {} pass {} fail {} warn {} info {} skip {} pending",
fg(80,200,120, "✓"),
fg(220,60,60, "✗"),
fg(240,200,60, "⚠"),
fg(100,180,255, "ℹ"),
fg(150,150,150, "⊘"),
fg(200,200,200, "◌"),
);
println!(" {} {} {} {} {} {}",
fg(80,200,120, "●"),
fg(220,60,60, "●"),
fg(240,200,60, "●"),
fg(100,180,255, "●"),
fg(150,150,150, "○"),
fg(200,200,200, "◐"),
);
println!();
sub("F2", "Bullets & List Markers", "For ranked lists, trees, enumerations");
println!(" • ◦ ‣ ⁃ ▸ ▹ ▪ ▫ ◆ ◇ ◈ ❖");
println!();
sub("F3", "Arrows & Connectors", "For flow, relationships, direction");
println!(" → ← ↑ ↓ ↔ ↕ ↗ ↘ ↙ ↖");
println!(" ⟶ ⟵ ⟷ ⇒ ⇐ ⇔ ⇨ ⇦");
println!(" ↳ ↱ ↰ ↲ (turns)");
println!(" ➜ ➤ ▶ ◀ (filled)");
println!();
sub("F4", "Superscript & Subscript Numbers", "For footnotes, exponents, indices");
println!(" super: ⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ⁺ ⁻ ⁼ ⁽ ⁾ ⁿ");
println!(" sub: ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎");
println!(" usage: O(n²) σ₃=1.2 f⁽ⁿ⁾");
println!();
sub("F5", "Mathematical Symbols", "For formulas, stats, annotations");
println!(" μ σ Σ Π ∫ ∂ ∇ √ ∞ ≈ ≠ ≤ ≥ ± ÷ × ∈ ∉ ⊂ ⊃ ∪ ∩ ∅ ∀ ∃");
println!(" usage: μ=12.3 σ=4.1 n=312 Σ=3847");
println!();
sub("F6", "Stars & Ratings", "For scores, quality ratings");
print!(" ");
for i in 0..5 {
if i < 3 { print!("{}", fg(253,231,37, "★")); }
else { print!("{}", fg(80,80,80, "☆")); }
}
println!(" 3/5 stars");
print!(" ");
// Fractional rating with half star
for i in 0..5 {
if i < 3 { print!("{}", fg(253,231,37, "★")); }
else if i == 3 { print!("{}",fg(253,231,37,"⯪")); }
else { print!("{}", fg(80,80,80, "☆")); }
}
println!(" 3.5/5 stars");
println!();
sub("F7", "Enclosed/Circled Characters", "For labels, badges, numbered references");
println!(" numbers: ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩");
println!(" filled: ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿");
println!(" letters: Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ ⓐ ⓑ ⓒ ⓓ ⓔ");
println!();
sub("F8", "Dice & Cards", "Fun alternative for small integer values");
println!(" dice: ⚀ ⚁ ⚂ ⚃ ⚄ ⚅ (1-6)");
println!();
sub("F9", "Separators & Ornaments", "Section dividers beyond plain lines");
println!(" ─ ═ ━ ╌ ╍ ┄ ┅ ┈ ┉");
println!(" ····· ‧‧‧‧‧ ⋯⋯⋯⋯⋯ …………");
print!(" ");
for i in 0..50 {
let t = i as f64 / 49.0;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, "─"));
}
println!();
print!(" ");
for i in 0..50 {
let t = i as f64 / 49.0;
let (r,g,b) = magma(t);
if i % 2 == 0 { print!("{}", fg(r,g,b, "═")); }
else { print!("{}", fg(r,g,b, " ")); }
}
println!();
println!();
}
// =====================================================================
// G. LAYOUT PATTERNS
// =====================================================================
fn section_layout_patterns() {
heading("G", "LAYOUT PATTERNS");
sub("G1", "Side-by-Side Panels", "Two data views sharing one row of terminal lines");
let left = vec![
"╭──── Stats ────╮",
"│ Files: 47 │",
"│ Funcs: 312 │",
"│ LoC: 12,847 │",
"╰────────────────╯",
];
let right = vec![
"╭──── Health ───╮",
"│ Score: 78% │",
"│ Trend: ↗ │",
"│ Grade: B+ │",
"╰────────────────╯",
];
for i in 0..left.len() {
println!(" {} {}", left[i], right.get(i).unwrap_or(&""));
}
println!();
sub("G2", "Tree / Indent View", "Hierarchical data with connecting lines");
let tree = [
("src/", 0, false),
("├── main.rs", 1, false),
("├── render.rs", 1, false),
("├── analysis/", 1, false),
("│ ├── loc.rs", 2, false),
("│ ├── complexity.rs", 2, false),
("│ └── deps/", 2, false),
("│ ├── mod.rs", 3, false),
("│ └── render.rs",3, true),
("└── summary/", 1, false),
(" ├── mod.rs", 2, false),
(" └── sections.rs",2, true),
];
for (line, depth, _is_last) in &tree {
let t = *depth as f64 / 3.0;
let (r,g,b) = viridis(t * 0.8 + 0.2);
println!(" {}", fg(r,g,b, line));
}
println!();
sub("G3", "Tab-Style Headers", "Section navigation indicators");
print!(" ");
print!("{}", fgbg(0,0,0, 100,180,255, " Summary "));
print!("{}", fgbg(200,200,200, 40,40,50, " LoC "));
print!("{}", fgbg(200,200,200, 40,40,50, " Complexity "));
print!("{}", fgbg(200,200,200, 40,40,50, " Deps "));
print!("{}", fgbg(200,200,200, 40,40,50, " Graph "));
println!();
print!(" ");
print!("{}", fg(100,180,255, "━━━━━━━━━"));
print!("{}", fg(60,60,70, "╸────────────╺────────────╸──────╺───────╸"));
println!();
println!();
sub("G4", "Inline Key-Value with Separators", "Compact horizontal metadata");
print!(" ");
print!("{}", fg(100,180,255, "47"));
print!(" files \x1b[2m│\x1b[0m ");
print!("{}", fg(100,180,255, "312"));
print!(" functions \x1b[2m│\x1b[0m ");
print!("{}", fg(100,180,255, "12,847"));
print!(" LoC \x1b[2m│\x1b[0m ");
print!("complexity μ=");
print!("{}", fg(240,200,60, "8.3"));
println!();
println!();
sub("G5", "Badge / Pill Labels", "Highlighted inline labels");
print!(" ");
print!("{}", fgbg(255,255,255, 180,60,60, " critical "));
print!(" ");
print!("{}", fgbg(0,0,0, 240,200,60, " moderate "));
print!(" ");
print!("{}", fgbg(255,255,255, 60,160,80, " healthy "));
print!(" ");
print!("{}", fgbg(200,200,200, 60,60,80, " neutral "));
print!(" ");
print!("{}", fgbg(255,255,255, 100,100,180, " info "));
println!();
println!();
sub("G6", "Nested Boxes", "Boxes within boxes for grouped data");
println!(" ╭─── Module: render ────────────────────╮");
println!(" │ ╭── Functions ──────╮ ╭── Stats ──╮ │");
println!(" │ │ terminal_width() │ │ LoC: 174 │ │");
println!(" │ │ visible_len() │ │ CC: 3.2 │ │");
println!(" │ │ bar_color() │ │ Deps: 4 │ │");
println!(" │ ╰──────────────────╯ ╰──────────╯ │");
println!(" ╰───────────────────────────────────────╯");
println!();
sub("G7", "Responsive Column Width", "Adapt layout to terminal width (already partially done)");
println!(" \x1b[2mNarrow (<60): single column, truncated labels\x1b[0m");
println!(" \x1b[2mMedium (60-100): standard layout\x1b[0m");
println!(" \x1b[2mWide (>100): side-by-side panels, expanded labels\x1b[0m");
println!();
}
// =====================================================================
// H. TERMINAL FEATURES
// =====================================================================
fn section_terminal_features() {
heading("H", "TERMINAL-LEVEL FEATURES");
sub("H1", "Clickable Hyperlinks (OSC 8)", "Terminal links to files/URLs — click to open");
println!(" \x1b]8;;file:///workspace/src/render.rs\x1b\\src/render.rs:42\x1b]8;;\x1b\\ ← try clicking (supported: iTerm2, WezTerm, Windows Terminal, Kitty, etc.)");
println!(" \x1b]8;;https://example.com\x1b\\https://example.com\x1b]8;;\x1b\\");
println!();
sub("H2", "In-Place Updates (Cursor Movement)", "Overwrite previous output for live-feel");
println!(" \\x1b[nA = move up n lines \\x1b[nB = move down");
println!(" \\x1b[nC = move right n cols \\x1b[nD = move left");
println!(" \\x1b[2K = clear current line \\r = carriage return");
println!(" \x1b[2mUseful for: progress bars, status updates, animation\x1b[0m");
println!();
sub("H3", "Terminal Title (OSC 2)", "Set the terminal window/tab title");
println!(" \\x1b]2;cstat — analyzing project\\x07");
println!(" \x1b[2mSets window title to reflect current operation\x1b[0m");
println!();
sub("H4", "Alternate Screen Buffer", "Switch to full-screen mode and back");
println!(" \\x1b[?1049h = enter alternate screen");
println!(" \\x1b[?1049l = leave alternate screen");
println!(" \x1b[2mUseful for: a full-screen dashboard mode without losing scroll history\x1b[0m");
println!();
sub("H5", "Sixel Graphics", "Actual raster images in terminal (limited support)");
println!(" \x1b[2mSupported: xterm, mlterm, WezTerm, foot, some others\x1b[0m");
println!(" \x1b[2mCould render: actual scatter plots, treemaps, architecture diagrams as images\x1b[0m");
println!();
sub("H6", "Kitty Graphics Protocol", "High-quality image display (Kitty terminal)");
println!(" \x1b[2mSupported: Kitty, WezTerm\x1b[0m");
println!(" \x1b[2mCould render: PNG charts inline in output\x1b[0m");
println!();
sub("H7", "Notification (OSC 9/777)", "Send desktop notification when analysis completes");
println!(" \\x1b]9;Analysis complete\\x07 (Windows Terminal)");
println!(" \\x1b]777;notify;cstat;Done\\x07 (rxvt-unicode)");
println!();
println!();
}
// =====================================================================
// I. DISTRIBUTION VISUALIZATIONS
// =====================================================================
fn section_distribution_viz() {
heading("I", "DISTRIBUTION VISUALIZATIONS");
// I1: Violin plot
sub("I1", "Violin Plot", "Mirrored density curve — shows distribution shape, not just quartiles");
// Simulate a density: peaked in the middle, long right tail
let density = [1,2,3,5,8,12,15,18,15,11,8,6,5,4,3,3,2,2,1,1];
let max_d = 18;
let h = density.len();
println!(" \x1b[2m cyclomatic cognitive\x1b[0m");
let density2 = [1,1,2,4,7,10,14,10,7,5,4,3,2,2,1,1,1,0,0,0];
for row in 0..h {
let d1 = density[row];
let d2 = density2[row];
let w1 = (d1 as f64 / max_d as f64 * 15.0).round() as usize;
let w2 = (d2 as f64 / max_d as f64 * 15.0).round() as usize;
let (r1,g1,b1) = viridis(d1 as f64 / max_d as f64);
let (r2,g2,b2) = magma(d2 as f64 / max_d as f64);
let left_pad = 15 - w1;
print!(" {:>3}\x1b[2m│\x1b[0m", if row == 0 || row == h-1 || row == h/2 { format!("{}", row) } else { String::new() });
print!("{}{}", " ".repeat(left_pad), fg(r1,g1,b1, &"█".repeat(w1)));
print!("\x1b[2m│\x1b[0m");
print!("{}", fg(r1,g1,b1, &"█".repeat(w1)));
print!("{} ", " ".repeat(left_pad));
// second violin
let left_pad2 = 15 - w2;
print!("{}{}", " ".repeat(left_pad2), fg(r2,g2,b2, &"█".repeat(w2)));
print!("\x1b[2m│\x1b[0m");
print!("{}", fg(r2,g2,b2, &"█".repeat(w2)));
println!();
}
println!();
// I2: Ridgeline / joy plot
sub("I2", "Ridgeline / Joy Plot", "Overlapping distributions — compare shapes across groups");
let blocks = ['▁','▂','▃','▄','▅','▆','▇','█'];
let ridges: [(&str, [u8; 20]); 4] = [
("render ", [0,1,2,4,6,7,8,7,5,3,2,1,1,0,0,0,0,0,0,0]),
("deps ", [0,0,1,2,3,5,7,8,7,6,5,4,3,2,1,1,0,0,0,0]),
("complex", [0,0,0,1,1,2,3,4,5,7,8,7,6,4,3,2,1,1,0,0]),
("loc ", [0,0,0,0,0,1,1,2,3,4,5,6,7,8,8,7,5,3,1,0]),
];
for (name, vals) in &ridges {
print!(" {}\x1b[2m│\x1b[0m ", name);
for &v in vals {
if v == 0 {
print!(" ");
} else {
let t = v as f64 / 8.0;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, &blocks[(v as usize - 1).min(7)].to_string()));
}
}
println!();
}
println!(" \x1b[2m └──────────────────────\x1b[0m");
println!();
// I3: Beeswarm plot
sub("I3", "Beeswarm / Jitter Plot", "Individual points jittered to avoid overlap — shows density + outliers");
let swarm_data: [(f64, &[i8]); 1] = [(0.0, &[])]; // placeholder, we'll hardcode the visual
let _ = swarm_data;
// Render a beeswarm: each column is a value bucket, dots stack vertically
println!(" \x1b[2m 5 10 15 20 25 30 35\x1b[0m");
// Row by row, dots placed at various x positions with jitter
let rows: [&str; 5] = [
" ● ● ",
" ● ●● ● ● ",
" ● ●● ●●● ●● ● ● ● ",
" ●● ●●● ●●●● ●●● ●● ●● ● ",
" ●●●● ●●●● ●●●● ●●●● ●●● ●●● ●● ",
];
for (i, row) in rows.iter().enumerate() {
let t = 1.0 - i as f64 / 4.0;
print!(" ");
for ch in row.chars() {
if ch == '●' {
let (r,g,b) = viridis(0.3 + t * 0.5);
print!("{}", fg(r,g,b, "●"));
} else {
print!(" ");
}
}
println!();
}
println!(" \x1b[2m └─────────────────────────────────────\x1b[0m");
println!();
// I4: CDF / Cumulative Distribution
sub("I4", "CDF / Cumulative Distribution Curve", "What % of values fall below threshold X — uses braille for smooth curve");
let cdf_vals = [0.0,0.02,0.05,0.10,0.18,0.28,0.40,0.52,0.63,0.73,0.80,0.86,0.90,0.93,0.95,0.97,0.98,0.99,0.99,1.0];
let cdf_h = 8;
let cdf_w = cdf_vals.len();
for row in (0..cdf_h).rev() {
let threshold = row as f64 / (cdf_h - 1) as f64;
print!(" {:>4.0}%\x1b[2m│\x1b[0m", threshold * 100.0);
for (col, &v) in cdf_vals.iter().enumerate() {
if (v - threshold).abs() < 0.08 {
let (r,g,b) = viridis(v);
print!("{}", fg(r,g,b, "●━"));
} else if v > threshold {
print!(" ");
} else {
print!(" ");
}
}
println!();
}
println!(" \x1b[2m └──────────────────────────────────────\x1b[0m");
println!(" \x1b[2m 0 complexity → max\x1b[0m");
println!();
// I5: Rug plot
sub("I5", "Rug Plot", "Tick marks along axis edge — shows each individual observation");
print!(" \x1b[2m│\x1b[0m");
let rug_points = [2,3,5,5,6,7,7,7,8,10,11,11,12,14,15,18,22,25,28,35];
let rug_max = 40;
let mut rug_line = vec![' '; rug_max + 1];
for &p in &rug_points {
if p <= rug_max { rug_line[p] = '│'; }
}
for (i, &ch) in rug_line.iter().enumerate() {
if ch == '│' {
let t = i as f64 / rug_max as f64;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, "│"));
} else {
print!("\x1b[2m╌\x1b[0m");
}
}
println!("\x1b[2m│\x1b[0m");
println!(" \x1b[2mEach tick = one observation. Dense ticks = concentration.\x1b[0m");
println!();
// I6: Q-Q Plot
sub("I6", "Q-Q Plot", "Quantile-quantile — compare distribution to normal. Points on diagonal = normal.");
let qq_h = 10;
let qq_w = 30;
// Points roughly along diagonal with some deviation
let qq_points: [(usize,usize);12] = [(1,0),(3,2),(6,4),(9,6),(11,8),(13,10),(15,13),(18,16),(21,19),(23,22),(26,25),(29,28)];
for row in (0..qq_h).rev() {
print!(" \x1b[2m│\x1b[0m");
for col in 0..qq_w {
// diagonal reference line
let on_diag = (col as f64 / qq_w as f64 - row as f64 / qq_h as f64).abs() < 0.06;
let is_point = qq_points.iter().any(|&(px,py)| {
px == col && (py as f64 / (qq_h as f64) * qq_h as f64).round() as usize == row
});
if is_point {
print!("{}", fg(80,200,120, "●"));
} else if on_diag {
print!("\x1b[2m╱\x1b[0m");
} else {
print!(" ");
}
}
println!();
}
println!(" \x1b[2m└──────────────────────────────\x1b[0m");
println!(" \x1b[2mtheoretical quantiles → (deviation from line = non-normality)\x1b[0m");
println!();
}
// =====================================================================
// J. COMPARISON & RANKING VISUALIZATIONS
// =====================================================================
fn section_comparison_viz() {
heading("J", "COMPARISON & RANKING VISUALIZATIONS");
// J1: Lollipop chart
sub("J1", "Lollipop Chart", "Dot on a stick — cleaner than bars for sparse/ranked data");
let items = [
("parse_expr", 42),
("resolve_imports",31),
("build_graph", 24),
("validate_ast", 18),
("emit_warning", 7),
];
let max_v = 42;
for (name, val) in &items {
let w = (*val as f64 / max_v as f64 * 35.0) as usize;
let t = *val as f64 / max_v as f64;
let (r,g,b) = heat(t);
print!(" {:<20}", name);
print!("{}", fg(r,g,b, &"╌".repeat(w)));
print!("{}", fg(r,g,b, "●"));
println!(" {}", val);
}
println!();
// J2: Dumbbell chart
sub("J2", "Dumbbell Chart", "Two dots connected — shows range or before/after delta");
let pairs = [
("render.rs", 8, 14),
("complexity.rs", 22, 18),
("dist.rs", 15, 28),
("loc.rs", 12, 12),
];
let scale = 35;
let max_val = 30;
println!(" {:<18} \x1b[2m{:>15} v1 v2\x1b[0m", "", "");
for (name, v1, v2) in &pairs {
let p1 = (*v1 as f64 / max_val as f64 * scale as f64) as usize;
let p2 = (*v2 as f64 / max_val as f64 * scale as f64) as usize;
let (lo, hi) = if p1 < p2 { (p1, p2) } else { (p2, p1) };
let improved = v2 < v1;
print!(" {:<18}", name);
for i in 0..=scale {
if i == p1 {
print!("{}", fg(150,150,200, "●"));
} else if i == p2 {
if improved { print!("{}", fg(80,200,120, "●")); }
else { print!("{}", fg(220,60,60, "●")); }
} else if i > lo && i < hi {
print!("─");
} else {
print!("\x1b[2m·\x1b[0m");
}
}
println!(" {:>2}→{}", v1, v2);
}
println!();
// J3: Slope chart
sub("J3", "Slope Chart", "Two columns connected by slope lines — shows rank change");
let slopes = [
("parse_expr", 1, 2),
("build_graph", 2, 1),
("resolve", 3, 5),
("validate", 4, 3),
("emit_warn", 5, 4),
];
let col_gap = 25;
println!(" \x1b[2m v1.0 v2.0\x1b[0m");
// Position items at their rank
let h = 5;
for rank in 1..=h {
let left = slopes.iter().find(|s| s.1 == rank);
let right = slopes.iter().find(|s| s.2 == rank);
let left_name = left.map(|s| s.0).unwrap_or("");
let right_name = right.map(|s| s.0).unwrap_or("");
let going_up = left.map(|s| s.2 < s.1).unwrap_or(false);
let going_down = left.map(|s| s.2 > s.1).unwrap_or(false);
let slope_char = if going_up { "╱" } else if going_down { "╲" } else { "─" };
let (r,g,b) = if going_up { (80,200,120) } else if going_down { (220,60,60) } else { (150,150,150) };
print!(" {:<14}", left_name);
print!("{}", fg(r,g,b, "●"));
print!("{}", fg(r,g,b, &format!("─{}─",slope_char).repeat(3)));
print!("{}", if right.is_some() { fg(100,180,255,"●") } else { " ".to_string() });
println!(" {}", right_name);
}
println!();
// J4: Bump chart
sub("J4", "Bump Chart", "Rank trajectories over time — who moved up/down");
let bump_data: [(&str, [usize; 5]); 4] = [
("render", [1,1,2,3,3]),
("deps", [2,3,3,2,1]),
("complex", [3,2,1,1,2]),
("loc", [4,4,4,4,4]),
];
let colors = [(220,80,80),(80,200,120),(100,180,255),(240,200,60)];
println!(" \x1b[2m t1 t2 t3 t4 t5\x1b[0m");
for rank in 1..=4 {
print!(" #{:<2}", rank);
for t in 0..5 {
let who = bump_data.iter().position(|d| d.1[t] == rank);
if let Some(idx) = who {
let (r,g,b) = colors[idx];
print!(" {}", fg(r,g,b, &format!("{:─<4}", bump_data[idx].0)));
} else {
print!(" ");
}
}
println!();
}
println!();
// J5: Cleveland dot plot
sub("J5", "Cleveland Dot Plot", "Aligned dots on a grid — precise comparison without bar clutter");
let dot_items = [
("parse_expr", 42.0),
("resolve_imports", 31.0),
("build_graph", 24.5),
("validate_ast", 18.2),
("emit_warning", 7.0),
];
let max_v = 45.0;
println!(" \x1b[2m{:>20} 0 10 20 30 40\x1b[0m", "");
println!(" \x1b[2m{:>20} ┼─────────┼─────────┼─────────┼─────────┼\x1b[0m", "");
for (name, val) in &dot_items {
let pos = (*val / max_v * 45.0) as usize;
print!(" {:>20} ", name);
for i in 0..=45 {
if i == pos {
let t = *val / max_v;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, "◆"));
} else if i % 10 == 0 {
print!("\x1b[2m┊\x1b[0m");
} else {
print!("\x1b[2m·\x1b[0m");
}
}
println!(" {:.1}", val);
}
println!();
// J6: Diverging bar chart
sub("J6", "Diverging Bar Chart", "Bars extend left/right from center — shows positive/negative change");
let changes = [
("render.rs", 6),
("complexity.rs", -4),
("dist.rs", 13),
("loc.rs", 0),
("deps/mod.rs", -8),
];
let max_abs = 15;
let half_w = 15;
for (name, delta) in &changes {
print!(" {:<16}", name);
let abs_d = (*delta as f64).abs();
let bar_w = (abs_d / max_abs as f64 * half_w as f64) as usize;
if *delta < 0 {
let pad = half_w - bar_w;
let (r,g,b) = (100,180,255);
print!("{}{}", " ".repeat(pad), fg(r,g,b, &"◄".repeat(bar_w)));
print!("\x1b[2m│\x1b[0m");
print!("{}", " ".repeat(half_w));
} else if *delta > 0 {
print!("{}", " ".repeat(half_w));
print!("\x1b[2m│\x1b[0m");
let (r,g,b) = (220,120,60);
print!("{}", fg(r,g,b, &"►".repeat(bar_w)));
print!("{}", " ".repeat(half_w - bar_w));
} else {
print!("{}", " ".repeat(half_w));
print!("\x1b[2m│\x1b[0m");
print!("{}", " ".repeat(half_w));
}
println!(" {:>+3}", delta);
}
println!();
// J7: Radar/Spider chart
sub("J7", "Radar / Spider Chart", "Multivariate profile — one polygon per entity, using braille canvas");
// Simplified: show as a small braille rendering
let metrics_labels = ["CC", "LoC", "Nest", "Deps", "Params"];
let profile = [0.8, 0.5, 0.3, 0.7, 0.4]; // normalized 0-1
// Render as a 5-axis star in braille
let cx = 20_f64;
let cy = 16_f64;
let radius = 14.0_f64;
let n_axes = 5;
let mut canvas = vec![vec![0u8; 22]; 9]; // braille cells
let mut density = vec![vec![0u32; 22]; 9];
let pi = std::f64::consts::PI;
// Draw axes and polygon
for i in 0..n_axes {
let angle = pi / 2.0 + i as f64 * 2.0 * pi / n_axes as f64;
// Axis line
for step in 0..30 {
let t = step as f64 / 29.0;
let px = (cx + angle.cos() * radius * t) as usize;
let py = (cy - angle.sin() * radius * t) as usize; // flip Y
set_braille(&mut canvas, &mut density, px, py);
}
// Polygon vertex
let r = profile[i];
let vx = (cx + angle.cos() * radius * r) as usize;
let vy = (cy - angle.sin() * radius * r) as usize;
set_braille(&mut canvas, &mut density, vx, vy);
// Connect to next vertex
let next = (i + 1) % n_axes;
let next_angle = pi / 2.0 + next as f64 * 2.0 * pi / n_axes as f64;
let next_r = profile[next];
let nvx = cx + next_angle.cos() * radius * next_r;
let nvy = cy - next_angle.sin() * radius * next_r;
for step in 0..20 {
let t = step as f64 / 19.0;
let lx = (vx as f64 + (nvx - vx as f64) * t) as usize;
let ly = (vy as f64 + (nvy - vy as f64) * t) as usize;
set_braille(&mut canvas, &mut density, lx, ly);
}
}
for row in 0..9 {
print!(" ");
for col in 0..22 {
let ch = char::from_u32(0x2800 + canvas[row][col] as u32).unwrap();
if canvas[row][col] == 0 {
print!(" ");
} else if density[row][col] > 2 {
print!("{}", fg(253,231,37, &ch.to_string()));
} else {
print!("{}", fg(80,200,120, &ch.to_string()));
}
}
// Labels at approximate positions
match row {
0 => print!(" {}", metrics_labels[0]),
2 => print!(" {}", metrics_labels[1]),
5 => print!(" {}", metrics_labels[4]),
8 => print!(" \x1b[2m(polygon = module profile)\x1b[0m"),
_ => {}
}
println!();
}
println!();
}
fn set_braille(canvas: &mut [Vec<u8>], density: &mut [Vec<u32>], px: usize, py: usize) {
let cx = px / 2;
let cy = py / 4;
if cx >= canvas[0].len() || cy >= canvas.len() { return; }
let lx = px % 2;
let ly = py % 4;
let bit = match (lx, ly) { (0,0)=>0,(0,1)=>1,(0,2)=>2,(0,3)=>6,(1,0)=>3,(1,1)=>4,(1,2)=>5,(1,3)=>7,_=>0 };
canvas[cy][cx] |= 1 << bit;
density[cy][cx] += 1;
}
// =====================================================================
// K. RELATIONAL / FLOW VISUALIZATIONS
// =====================================================================
fn section_relational_viz() {
heading("K", "RELATIONAL & FLOW VISUALIZATIONS");
// K1: Node-edge graph
sub("K1", "Node-Edge Graph Layout", "2D graph with boxes and connecting lines");
println!(" ╭────────╮ ╭──────────╮");
println!(" │ render │─────────→│ summary │");
println!(" ╰────┬───╯ ╰────┬─────╯");
println!(" │ │");
println!(" ↓ ↓");
println!(" ╭─────────╮ ╭──────────╮");
println!(" │ deps │←───────→│ graph │");
println!(" ╰────┬────╯ ╰──────────╯");
println!(" │");
println!(" ↓");
println!(" ╭──────────╮");
println!(" │ analysis │");
println!(" ╰──────────╯");
println!();
// K2: Sankey / flow diagram
sub("K2", "Sankey / Alluvial Flow", "Width-proportional paths between stages — shows flow volume");
let (r1,g1,b1) = (100,180,255);
let (r2,g2,b2) = (80,200,120);
let (r3,g3,b3) = (240,200,60);
let (r4,g4,b4) = (220,100,100);
println!(" \x1b[2mInput Processing Output\x1b[0m");
println!(" {}━━━━━━━━━━━━━━━{}━━━━━━━━━━━{}",
fg(r1,g1,b1,"parse ████"),fg(r1,g1,b1,"████████"),fg(r1,g1,b1,"████ render"));
println!(" {}━━━━━━━━━━{}",
fg(r2,g2,b2," ████"),fg(r2,g2,b2,"━━━━━━━━━━━━━━████ json"));
println!(" {}━━━━━━━━━━━━━━━{}━━━━━━━━━━━{}",
fg(r3,g3,b3,"walk ██"),fg(r3,g3,b3,"██████"),fg(r3,g3,b3,"██ summary"));
println!(" {}━━━━━━━━━━━━━━━{}",
fg(r4,g4,b4," ██"),fg(r4,g4,b4,"━━━━━━━━━━━━━━██ guide"));
println!(" \x1b[2m(bar width ∝ data volume through each path)\x1b[0m");
println!();
// K3: Chord-style connection list
sub("K3", "Chord / Arc Diagram", "Connections between items on a line — uses arcs above/below");
println!(" \x1b[2m(flat layout, arcs show connections; height ∝ strength)\x1b[0m");
// Top arcs
println!(" {} {}",
fg(100,180,255, " ╭───────────────╮"),
"");
println!(" {} {}",
fg(80,200,120, " ╭────╮"),
fg(220,100,100, " ╭────────╮"));
println!(" {} {}",
fg(240,200,60, "╭─╮"),
"");
print!(" ");
let nodes = ["render","deps","graph","loc","summary","complex"];
for n in &nodes {
print!("{} ", fg(253,231,37, &format!("[{}]", &n[..3])));
}
println!();
// Bottom arcs
println!(" {}",
fg(200,100,200, " ╰──────────────────────╯"));
println!();
// K4: Dependency arrows with indentation
sub("K4", "Layered Dependency View", "Modules in tiers with directional arrows between layers");
println!(" \x1b[2m── Tier 0 (entry) ──────────────────────────\x1b[0m");
print!(" ");
print!("{}", fgbg(200,200,200, 40,60,80, " main "));
println!();
println!(" │ │");
println!(" ↓ ↓");
println!(" \x1b[2m── Tier 1 (orchestration) ──────────────────\x1b[0m");
print!(" ");
print!("{} ", fgbg(200,200,200, 40,80,60, " summary "));
print!("{}", fgbg(200,200,200, 40,80,60, " flow "));
println!();
println!(" │ ╲ │");
println!(" ↓ ╲ ↓");
println!(" \x1b[2m── Tier 2 (analysis) ───────────────────────\x1b[0m");
print!(" ");
print!("{} ", fgbg(200,200,200, 60,40,80, " deps "));
print!("{} ", fgbg(200,200,200, 60,40,80, " complexity "));
print!("{}", fgbg(200,200,200, 60,40,80, " loc "));
println!();
println!();
// K5: Dendrogram
sub("K5", "Dendrogram / Cluster Tree", "Hierarchical clustering — which modules are most similar");
println!(" \x1b[2mdistance 0.0 0.5 1.0\x1b[0m");
println!(" {}", fg(100,180,255, "render ─────────────┐"));
println!(" {} {}", fg(100,180,255, "summary ────────────┤"), fg(80,200,120, ""));
println!(" {} {}",
fg(100,180,255, " ├──────────┐"),
"");
println!(" {}", fg(240,200,60, "deps ──────┐ │ │"));
println!(" {}", fg(240,200,60, "graph ─────┤────────┘ │"));
println!(" {}", fg(240,200,60, " │ │"));
println!(" {}", fg(220,100,100, "complexity ────────────────────┘"));
println!();
// K6: Adjacency list view
sub("K6", "Adjacency List (Compact)", "Text-based graph: each node lists its connections");
let adj = [
("render", vec!["deps","summary","loc"]),
("deps", vec!["graph","render"]),
("summary", vec!["complexity","deps","loc","graph"]),
("complexity", vec![]),
("loc", vec![]),
];
for (node, edges) in &adj {
let edge_str: Vec<String> = edges.iter().map(|e| fg(100,180,255, e)).collect();
if edges.is_empty() {
println!(" {} → \x1b[2m(leaf)\x1b[0m", fg(253,231,37, node));
} else {
println!(" {} → {}", fg(253,231,37, node), edge_str.join(", "));
}
}
println!();
}
// =====================================================================
// L. MATRIX & GRID VISUALIZATIONS
// =====================================================================
fn section_matrix_grid_viz() {
heading("L", "MATRIX & GRID VISUALIZATIONS");
// L1: Calendar heatmap
sub("L1", "Calendar Heatmap", "Grid of days colored by value — weeks as columns, days as rows");
let days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
let mut seed: u64 = 99;
println!(" \x1b[2m W1 W2 W3 W4 W5 W6 W7 W8\x1b[0m");
for d in 0..7 {
print!(" \x1b[2m{}\x1b[0m ", days[d]);
for _w in 0..8 {
seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
let v = (seed >> 33) as f64 / u32::MAX as f64;
let (r,g,b) = viridis(v);
print!("{}", bg(r,g,b, " "));
print!(" ");
}
println!();
}
println!(" \x1b[2m(commit activity, complexity changes, etc.)\x1b[0m");
println!();
// L2: Weighted adjacency matrix with blocks
sub("L2", "Weighted Adjacency Matrix", "Color intensity shows connection strength, not just 0/1/2");
let mods = ["rend","deps","summ","comp","loc ","grph"];
let n = mods.len();
print!(" {:>6}", "");
for m in &mods { print!(" {}", m); }
println!();
let mut seed2: u64 = 77;
for i in 0..n {
print!(" {:>5} ", mods[i]);
for j in 0..n {
if i == j {
print!("{}", bg(40,40,40, " ·· "));
print!(" ");
} else {
seed2 = seed2.wrapping_mul(6364136223846793005).wrapping_add(1);
let v = (seed2 >> 33) as f64 / u32::MAX as f64;
let (r,g,b) = magma(v);
let label = format!("{:.1}", v * 10.0);
print!("{}", fgbg(if v > 0.5 {0} else {200}, if v > 0.5 {0} else {200}, if v > 0.5 {0} else {200}, r,g,b, &format!("{:>4}", label)));
print!(" ");
}
}
println!();
}
println!();
// L3: Mosaic / Marimekko chart
sub("L3", "Mosaic / Marimekko Chart", "Variable-width columns — both width and height encode data");
let categories = [("src",50),("tests",25),("bench",15),("docs",10)];
let sub_cats = [(0.6,(80,200,120)),(0.25,(100,180,255)),(0.15,(240,200,60))]; // code/test/doc proportions
let total_w: usize = 60;
println!(" \x1b[2mcolumn width ∝ total LoC, row height ∝ composition\x1b[0m");
for (frac, (r,g,b)) in &sub_cats {
print!(" ");
for (name, pct) in &categories {
let col_w = (*pct as f64 / 100.0 * total_w as f64) as usize;
let fill_h = (*frac * 3.0_f64).round() as usize;
let _ = fill_h;
print!("{}", bg(*r,*g,*b, &" ".repeat(col_w)));
}
println!();
}
print!(" ");
for (name, pct) in &categories {
let col_w = (*pct as f64 / 100.0 * total_w as f64) as usize;
let centered = format!("{:^w$}", name, w=col_w);
print!("\x1b[2m{}\x1b[0m", centered);
}
println!();
println!();
// L4: Heatmap with annotations
sub("L4", "Annotated Heatmap", "Color + text in each cell — value visible on colored background");
let ann_labels = ["CC","Nest","Deps"];
let ann_data = [[8.2,3.1,5.0],[2.4,7.8,1.2],[4.5,2.0,9.1]];
print!(" {:>8}", "");
for l in &ann_labels { print!(" {:>8}", l); }
println!();
for i in 0..3 {
print!(" {:>8}", ann_labels[i]);
for j in 0..3 {
let v = ann_data[i][j];
let t = v / 10.0;
let (r,g,b) = magma(t);
let txt_color = if t > 0.5 { (0,0,0) } else { (220,220,220) };
print!(" {}", fgbg(txt_color.0,txt_color.1,txt_color.2, r,g,b, &format!(" {:>4.1} ", v)));
}
println!();
}
println!();
}
// =====================================================================
// M. PART-TO-WHOLE VISUALIZATIONS
// =====================================================================
fn section_part_to_whole_viz() {
heading("M", "PART-TO-WHOLE VISUALIZATIONS");
// M1: Icicle chart
sub("M1", "Icicle Chart", "Top-down nested rectangles — like a rectangular sunburst");
let (r1,g1,b1) = (80,100,180);
let (r2,g2,b2) = (80,160,120);
let (r3,g3,b3) = (180,160,80);
let (r4,g4,b4) = (180,80,80);
// Level 0: full width
println!(" {}", bg(60,60,80, &format!("{:^60}", "project (12,847 LoC)")));
// Level 1: split
println!(" {}{}{}{}",
bg(r1,g1,b1, &format!("{:^30}", "src/ (8420)")),
bg(r2,g2,b2, &format!("{:^15}", "tests/ (3200)")),
bg(r3,g3,b3, &format!("{:^10}", "bench/")),
bg(r4,g4,b4, &format!("{:^5}", "doc")),
);
// Level 2: src/ split further
let s = lerp((80,100,180),(120,140,220),0.3);
let s2 = lerp((80,100,180),(120,140,220),0.6);
let s3 = lerp((80,100,180),(120,140,220),0.9);
println!(" {}{}{}{}",
bg(s.0,s.1,s.2, &format!("{:^14}", "analysis/")),
bg(s2.0,s2.1,s2.2, &format!("{:^10}", "render/")),
bg(s3.0,s3.1,s3.2, &format!("{:^6}", "cli")),
" ".repeat(30),
);
println!();
// M2: Proportional area (squares)
sub("M2", "Proportional Area Squares", "Square size encodes magnitude — better area perception than bars");
let items = [("parse",42),("resolve",31),("build",24),("validate",18),("emit",7)];
for (name, val) in &items {
let side = ((*val as f64).sqrt() * 1.5) as usize;
let t = *val as f64 / 42.0;
let (r,g,b) = heat(t);
print!(" {:<10}", name);
for _row in 0..1 {
for _ in 0..side { print!("{}", fg(r,g,b, "██")); }
}
println!(" ({})", val);
}
println!(" \x1b[2m(area ∝ value, not just width)\x1b[0m");
println!();
// M3: Nested treemap
sub("M3", "Treemap (Nested)", "Proportional nested rectangles — area ∝ value");
println!(" ┌──────────────────────┬─────────────────┐");
println!(" │ │ │");
println!(" │ {} │ {} │",
fg(100,180,255, "src/analysis"),
fg(80,200,120, "src/render"));
println!(" │ {} │ {} │",
fg(100,180,255, "(4200 LoC)"),
fg(80,200,120, "(2100)"));
println!(" │ │ │");
println!(" ├───────────┬──────────┼────────┬────────┤");
println!(" │ │ │ │ │");
println!(" │ {} │ {} │ {} │ {} │",
fg(240,200,60, "tests"),
fg(220,100,100, "bench"),
fg(200,100,200, "cli"),
fg(150,150,150, "doc"));
println!(" │ {} │ {} │ {} │ {} │",
fg(240,200,60, "(3200)"),
fg(220,100,100, "(890)"),
fg(200,100,200, "(400)"),
fg(150,150,150, "(57)"));
println!(" └───────────┴──────────┴────────┴────────┘");
println!();
// M4: Donut / ring chart (braille)
sub("M4", "Donut / Ring Chart", "Circular proportion display using braille — for 2-4 segments");
let segments: [(f64, (u8,u8,u8)); 3] = [
(0.55, (100,180,255)), // code
(0.30, (80,200,120)), // tests
(0.15, (240,200,60)), // docs
];
let cx = 16.0_f64;
let cy = 16.0_f64;
let outer = 14.0_f64;
let inner = 8.0_f64;
let pi = std::f64::consts::PI;
let mut canvas = vec![vec![0u8; 18]; 9];
let mut colors = vec![vec![(0u8,0u8,0u8); 18]; 9];
let mut angle_start = 0.0_f64;
for (frac, color) in &segments {
let angle_end = angle_start + frac * 2.0 * pi;
// Fill arc
let steps = 100;
for s in 0..steps {
let a = angle_start + (angle_end - angle_start) * s as f64 / steps as f64;
for rd in 0..10 {
let r = inner + (outer - inner) * rd as f64 / 9.0;
let px = (cx + a.cos() * r) as usize;
let py = (cy - a.sin() * r) as usize;
let bcx = px / 2;
let bcy = py / 4;
if bcx < 18 && bcy < 9 {
let lx = px % 2;
let ly = py % 4;
let bit = match (lx, ly) { (0,0)=>0,(0,1)=>1,(0,2)=>2,(0,3)=>6,(1,0)=>3,(1,1)=>4,(1,2)=>5,(1,3)=>7,_=>0 };
canvas[bcy][bcx] |= 1 << bit;
colors[bcy][bcx] = *color;
}
}
}
angle_start = angle_end;
}
for row in 0..9 {
print!(" ");
for col in 0..18 {
let ch = char::from_u32(0x2800 + canvas[row][col] as u32).unwrap();
if canvas[row][col] == 0 {
print!(" ");
} else {
let (r,g,b) = colors[row][col];
print!("{}", fg(r,g,b, &ch.to_string()));
}
}
match row {
2 => print!(" {} 55% code", fg(100,180,255, "██")),
4 => print!(" {} 30% tests", fg(80,200,120, "██")),
6 => print!(" {} 15% docs", fg(240,200,60, "██")),
_ => {}
}
println!();
}
println!();
// M5: Stacked percentage bar
sub("M5", "Stacked 100% Bar", "Horizontal bar always fills to 100% — shows proportions");
let total_w = 50;
let segments_pct = [("code",55,(80,200,120)),("test",30,(100,180,255)),("docs",10,(240,200,60)),("cfg",5,(180,100,200))];
print!(" ");
for (name, pct, (r,g,b)) in &segments_pct {
let w = (*pct as f64 / 100.0 * total_w as f64).round() as usize;
let label = if w > name.len() + 2 { format!("{:^w$}", format!("{} {}%", name, pct), w=w) } else { format!("{:^w$}", "", w=w) };
print!("{}", fgbg(if *pct > 20 {255} else {200},if *pct > 20 {255} else {200},if *pct > 20 {255} else {200}, *r,*g,*b, &label));
}
println!();
println!();
// M6: Parliament / hemicycle (just described, complex to render)
sub("M6", "Waffle Grid (Categorized)", "Grid squares colored by category — each square = 1%");
let grid_cats = [('■',(80,200,120),55),('■',(100,180,255),30),('■',(240,200,60),10),('■',(180,100,200),5)];
print!(" ");
let mut count = 0;
for (ch, (r,g,b), n) in &grid_cats {
for _ in 0..*n {
if count > 0 && count % 25 == 0 { print!("\n "); }
print!("{}", fg(*r,*g,*b, &ch.to_string()));
count += 1;
}
}
println!();
print!(" ");
for (_, (r,g,b), _) in &grid_cats {
print!("{} ", fg(*r,*g,*b, "■■"));
}
println!();
println!(" \x1b[2mcode tests docs cfg\x1b[0m");
println!();
}
// =====================================================================
// N. TEMPORAL & SEQUENTIAL VISUALIZATIONS
// =====================================================================
fn section_temporal_viz() {
heading("N", "TEMPORAL & SEQUENTIAL VISUALIZATIONS");
// N1: Sparkline band (multiple aligned)
sub("N1", "Sparkline Band", "Multiple aligned sparklines for cross-metric comparison");
let blocks = ['▁','▂','▃','▄','▅','▆','▇','█'];
let bands: [(&str, [u8;20], fn(f64)->(u8,u8,u8)); 4] = [
("CC ", [2,3,4,3,5,6,5,4,6,7,8,7,6,5,6,7,6,5,4,3], viridis),
("LoC ", [3,3,4,4,5,5,6,6,7,7,7,7,8,8,8,7,7,6,6,5], magma),
("Deps ", [1,2,2,3,3,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8], inferno),
("Nest ", [5,5,4,4,3,3,3,2,2,2,3,3,4,4,3,3,2,2,1,1], plasma),
];
for (name, vals, pal) in &bands {
print!(" {}", name);
for &v in vals {
let t = v as f64 / 8.0;
let (r,g,b) = pal(t);
print!("{}", fg(r,g,b, &blocks[(v as usize - 1).min(7)].to_string()));
}
println!();
}
println!(" \x1b[2m ← older newer →\x1b[0m");
println!();
// N2: Horizon chart
sub("N2", "Horizon Chart", "Folded bands — encodes magnitude via color layers, saves vertical space");
// Values 0-8, but we fold at 4: values 0-4 use light shade, 4-8 overlay dark
let hz_vals = [1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,1,2,4,6,8,6,4,2,0,1,3,5,7,5];
let fold_at = 4;
print!(" layer1: ");
for &v in &hz_vals {
let base = v.min(fold_at);
let t = base as f64 / fold_at as f64;
let (r,g,b) = lerp((30,30,50),(80,140,200), t);
print!("{}", bg(r,g,b, &blocks[(base as usize).min(7).max(1) - 1].to_string()));
}
println!();
print!(" layer2: ");
for &v in &hz_vals {
let over = if v > fold_at { v - fold_at } else { 0 };
let base = v.min(fold_at);
let base_t = base as f64 / fold_at as f64;
let (br,bg_c,bb) = lerp((30,30,50),(80,140,200), base_t);
if over > 0 {
let over_t = over as f64 / fold_at as f64;
let (fr,fgc,fb) = lerp((100,160,220),(220,240,255), over_t);
print!("{}", fgbg(fr,fgc,fb, br,bg_c,bb, &blocks[(over as usize).min(7).max(1) - 1].to_string()));
} else {
print!("{}", bg(br,bg_c,bb, " "));
}
}
println!();
println!(" \x1b[2m(same data: layer1 = base, layer2 = base + overflow folded on top)\x1b[0m");
println!();
// N3: Gantt / timeline chart
sub("N3", "Gantt / Timeline Chart", "Horizontal bars on a time axis — phases, durations, overlaps");
let gantt = [
("parse", 0, 8, (100,180,255)),
("analyze", 5, 15, (80,200,120)),
("deps", 8, 12, (240,200,60)),
("complexity",10, 18, (220,100,100)),
("render", 16, 22, (200,100,200)),
];
let max_t = 24;
let scale = 48;
println!(" \x1b[2m{:>14} 0 5 10 15 20\x1b[0m", "");
println!(" \x1b[2m{:>14} ┼────────┼────────┼────────┼────────┼\x1b[0m", "");
for (name, start, end, (r,g,b)) in &gantt {
print!(" {:>14} ", name);
let s = (*start as f64 / max_t as f64 * scale as f64) as usize;
let e = (*end as f64 / max_t as f64 * scale as f64) as usize;
for i in 0..scale {
if i >= s && i < e {
print!("{}", fg(*r,*g,*b, "█"));
} else {
print!("\x1b[2m·\x1b[0m");
}
}
println!();
}
println!();
// N4: Step chart
sub("N4", "Step Chart", "Discrete level changes — like sparkline but shows exact transitions");
let step_vals: [usize; 15] = [2,2,4,4,4,7,7,3,3,5,5,5,8,8,6];
let max_s = 8;
for row in (1..=max_s).rev() {
print!(" {:>2}\x1b[2m│\x1b[0m", row);
for (i, &v) in step_vals.iter().enumerate() {
if v == row {
let t = v as f64 / max_s as f64;
let (r,g,b) = viridis(t);
// horizontal segment
print!("{}", fg(r,g,b, "──"));
// vertical connector to next if different
} else if i > 0 && step_vals[i-1] == row && v != row {
// vertical going down or up
let going = if v > row { "│ " } else { "│ " };
let t = row as f64 / max_s as f64;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, going));
} else if i > 0 && step_vals[i] != row && step_vals[i-1] != row {
// Check if vertical line passes through this row
let prev = step_vals[i-1];
let cur = step_vals[i];
let (lo, hi) = if prev < cur { (prev, cur) } else { (cur, prev) };
if row > lo && row < hi && i > 0 {
let t = row as f64 / max_s as f64;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, "│ "));
} else {
print!(" ");
}
} else {
print!(" ");
}
}
println!();
}
println!(" \x1b[2m └──────────────────────────────\x1b[0m");
println!();
// N5: Event timeline / marker chart
sub("N5", "Event Timeline / Markers", "Discrete events on a continuous axis");
print!(" \x1b[2m│\x1b[0m");
let events: [(usize, &str, (u8,u8,u8)); 6] = [
(3, "▼", (220,60,60)),
(8, "▼", (240,200,60)),
(12,"▼", (80,200,120)),
(18,"▼", (100,180,255)),
(25,"▼", (220,60,60)),
(33,"▼", (200,100,200)),
];
let tl_w = 40;
let mut tl_line = vec![("─", (80,80,80)); tl_w];
for (pos, marker, color) in &events {
if *pos < tl_w { tl_line[*pos] = (*marker, *color); }
}
for (ch, (r,g,b)) in &tl_line {
print!("{}", fg(*r,*g,*b, ch));
}
println!("\x1b[2m│\x1b[0m");
print!(" ");
for (pos, _, _) in &events {
let label_pos = if *pos > 1 { *pos } else { 1 };
print!("{:>w$}", "│", w=if label_pos > 0 {3} else {1});
}
println!();
println!(" \x1b[2m release bug feature refactor bug deploy\x1b[0m");
println!();
}
// =====================================================================
// O. TEXT-INTEGRATED VISUALIZATIONS
// =====================================================================
fn section_text_integrated_viz() {
heading("O", "TEXT-INTEGRATED VISUALIZATIONS");
// O1: Data bars in table cells
sub("O1", "In-Cell Data Bars", "Bars embedded within table cells — like Excel conditional formatting");
println!(" ╭──────────────────┬────────┬──────────────────────╮");
println!(" │ Function │ Score │ Distribution │");
println!(" ├──────────────────┼────────┼──────────────────────┤");
let table_data = [
("parse_expr", 42, 42),
("resolve_imports", 31, 42),
("build_graph", 24, 42),
("validate_ast", 18, 42),
];
for (name, val, max_v) in &table_data {
let t = *val as f64 / *max_v as f64;
let (r,g,b) = heat(t);
let bar_w = (t * 20.0) as usize;
let bar = fg(r,g,b, &"█".repeat(bar_w));
let pad = " ".repeat(20 - bar_w);
println!(" │ {:<16} │ {:>6} │ {}{} │",
name, fg(r,g,b,&val.to_string()), bar, pad);
}
println!(" ╰──────────────────┴────────┴──────────────────────╯");
println!();
// O2: Heatmap-colored text
sub("O2", "Heatmap-Colored Text", "The text IS the visualization — value encoded in text color");
let funcs = [
("parse_expr", 42), ("resolve_imports",31), ("build_graph",24),
("validate_ast", 18), ("emit_warning", 7), ("new_scope", 12),
("check_types", 28), ("fold_const", 15), ("inline_fn", 9),
];
println!(" \x1b[2mFunction names colored by complexity score:\x1b[0m");
print!(" ");
for (i, (name, val)) in funcs.iter().enumerate() {
let t = *val as f64 / 42.0;
let (r,g,b) = heat(t);
print!("{}", fg(r,g,b, name));
if i < funcs.len() - 1 { print!(" "); }
if (i + 1) % 3 == 0 { print!("\n "); }
}
println!();
println!();
// O3: Inline sparklines in table
sub("O3", "Inline Sparklines in Table Cells", "Trend mini-charts within each row");
let blocks = ['▁','▂','▃','▄','▅','▆','▇','█'];
println!(" ╭──────────────┬───────┬────────────────────┬───────╮");
println!(" │ Module │ CC │ Trend (10 commits) │ Δ │");
println!(" ├──────────────┼───────┼────────────────────┼───────┤");
let sparkdata: [(&str, f64, [u8;10], &str); 4] = [
("render", 8.3, [3,4,4,5,5,6,6,7,7,8], "+2.1↑"),
("deps", 12.1, [8,7,7,6,6,5,5,4,4,3], "-3.2↓"),
("complexity", 6.7, [5,5,5,6,5,5,6,5,5,5], " 0.0→"),
("loc", 4.2, [2,3,4,3,4,5,4,3,4,4], "+0.3↑"),
];
for (name, cc, trend, delta) in &sparkdata {
let cc_t = *cc / 15.0;
let (cr,cg,cb) = heat(cc_t);
print!(" │ {:<12} │ {} │ ", name, fg(cr,cg,cb, &format!("{:>5.1}", cc)));
for &v in trend {
let t = v as f64 / 8.0;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, &blocks[(v as usize - 1).min(7)].to_string()));
}
let delta_color = if delta.contains('↑') { fg(220,60,60,delta) }
else if delta.contains('↓') { fg(80,200,120,delta) }
else { fg(150,150,150,delta) };
println!(" │ {} │", delta_color);
}
println!(" ╰──────────────┴───────┴────────────────────┴───────╯");
println!();
// O4: Conditional row highlighting
sub("O4", "Conditional Row Highlighting", "Entire row background changes based on value/status");
println!(" \x1b[2m Function CC Status\x1b[0m");
let rows = [
("parse_expr", 42, "critical"),
("resolve_imports",31, "warning"),
("build_graph", 24, "warning"),
("validate_ast", 18, "ok"),
("emit_warning", 7, "ok"),
];
for (name, cc, status) in &rows {
let (br,bgg,bb) = match *status {
"critical" => (60,20,20),
"warning" => (50,40,15),
_ => (20,20,20),
};
let (fr,fgg,fb) = match *status {
"critical" => (255,100,100),
"warning" => (240,200,80),
_ => (180,220,180),
};
let line = format!(" {:<22} {:>3} {:<10}", name, cc, status);
println!(" {}", fgbg(fr,fgg,fb, br,bgg,bb, &line));
}
println!();
// O5: Annotation callouts
sub("O5", "Annotation / Callout Lines", "Point at specific data with explanatory text");
let bar_vals = [3,7,5,12,4,6,2,9];
let max_b = 12;
print!(" ");
for &v in &bar_vals {
let t = v as f64 / max_b as f64;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, &format!("{:>3} ", v)));
}
println!();
print!(" ");
for &v in &bar_vals {
let t = v as f64 / max_b as f64;
let h = (t * 6.0) as usize;
let (r,g,b) = viridis(t);
let bks = ['▁','▂','▃','▄','▅','▆','▇','█'];
print!("{}", fg(r,g,b, &format!(" {} ", bks[h.min(7)])));
print!(" ");
}
println!();
// Callout arrow pointing to the outlier (12)
println!(" \x1b[2m ↑\x1b[0m");
println!(" \x1b[2m ╰── {} (z=2.4, outlier)\x1b[0m", fg(253,231,37, "12"));
println!();
// O6: Multi-metric compact row
sub("O6", "Multi-Metric Compact Row", "All metrics for one item in a single dense line");
println!(" \x1b[2mformat: name CC▕gauge▏ nest▕gauge▏ deps▕gauge▏ trend grade\x1b[0m");
let compact = [
("parse_expr", 8.5, 4, 6, [3,4,5,6,7,8], "C"),
("resolve_imports",3.2, 2, 3, [3,3,3,3,3,3], "A"),
("build_graph", 5.1, 3, 8, [2,3,4,5,6,5], "B"),
];
let blocks = ['▁','▂','▃','▄','▅','▆','▇','█'];
for (name, cc, nest, deps, trend, grade) in &compact {
let cc_t = *cc / 10.0;
let nest_t = *nest as f64 / 6.0;
let deps_t = *deps as f64 / 10.0;
let (cr,cg,cb) = heat(cc_t);
let (nr,ng,nb) = heat(nest_t);
let (dr,dg,db) = heat(deps_t);
print!(" {:<16}", name);
// CC gauge
let cc_bar = (cc_t * 5.0) as usize;
print!(" {} {}{}\x1b[2m{}\x1b[0m",
fg(cr,cg,cb, &format!("{:.1}", cc)),
fg(cr,cg,cb, &"█".repeat(cc_bar)),
"\x1b[2m░\x1b[0m".repeat(5-cc_bar),
""
);
// Nest gauge
let n_bar = (nest_t * 4.0) as usize;
print!(" {} {}{}",
fg(nr,ng,nb, &format!("n{}", nest)),
fg(nr,ng,nb, &"█".repeat(n_bar)),
"\x1b[2m░\x1b[0m".repeat(4-n_bar),
);
// Deps
print!(" {} ", fg(dr,dg,db, &format!("d{}", deps)));
// Trend sparkline
for &v in trend {
let t = v as f64 / 8.0;
let (r,g,b) = viridis(t);
print!("{}", fg(r,g,b, &blocks[(v as usize -1).min(7)].to_string()));
}
// Grade badge
let grade_color = match *grade {
"A" => (80,200,120),
"B" => (240,200,60),
_ => (220,60,60),
};
print!(" {}", fgbg(0,0,0, grade_color.0,grade_color.1,grade_color.2, &format!(" {} ", grade)));
println!();
}
println!();
println!("\n{}", "═".repeat(70));
println!(" END OF GLOSSARY");
println!(" A: 8 pixel primitives B: 8 line styles C: 7 color modes");
println!(" D: 9 palettes E: 12 chart elements F: 9 symbol sets");
println!(" G: 7 layout patterns H: 7 terminal features");
println!(" I: 6 distribution viz J: 7 comparison viz K: 6 relational viz");
println!(" L: 4 matrix/grid viz M: 6 part-to-whole N: 5 temporal viz");
println!(" O: 6 text-integrated = {} total entries", 8+8+7+9+12+9+7+7+6+7+6+4+6+5+6);
println!(" Run: rustc demo_glossary.rs -o demo_glossary && ./demo_glossary");
println!("{}\n", "═".repeat(70));
}