use anstyle_wincon::WinconStream as _; fn main() -> Result<(), lexopt::Error> { let args = Args::parse()?; let stdout = std::io::stdout(); let mut stdout = stdout.lock(); for fixed in 0..16 { let style = style(fixed, args.layer, args.effects); let _ = print_number(&mut stdout, fixed, style); if fixed == 7 || fixed == 15 { let _ = stdout.write_colored(None, None, &b"\n"[..]); } } for r in 0..6 { let _ = stdout.write_colored(None, None, &b"\n"[..]); for g in 0..6 { for b in 0..6 { let fixed = r * 36 + g * 6 + b + 16; let style = style(fixed, args.layer, args.effects); let _ = print_number(&mut stdout, fixed, style); } let _ = stdout.write_colored(None, None, &b"\n"[..]); } } for c in 0..24 { if 0 == c % 8 { let _ = stdout.write_colored(None, None, &b"\n"[..]); } let fixed = 232 + c; let style = style(fixed, args.layer, args.effects); let _ = print_number(&mut stdout, fixed, style); } Ok(()) } fn style(fixed: u8, layer: Layer, effects: anstyle::Effects) -> anstyle::Style { let color = anstyle::Ansi256Color(fixed).into(); (match layer { Layer::Fg => anstyle::Style::new().fg_color(Some(color)), Layer::Bg => anstyle::Style::new().bg_color(Some(color)), Layer::Underline => anstyle::Style::new().underline_color(Some(color)), }) | effects } fn print_number( stdout: &mut std::io::StdoutLock<'static>, fixed: u8, style: anstyle::Style, ) -> std::io::Result<()> { let fg = style.get_fg_color().and_then(|c| match c { anstyle::Color::Ansi(c) => Some(c), anstyle::Color::Ansi256(c) => c.into_ansi(), anstyle::Color::Rgb(_) => None, }); let bg = style.get_bg_color().and_then(|c| match c { anstyle::Color::Ansi(c) => Some(c), anstyle::Color::Ansi256(c) => c.into_ansi(), anstyle::Color::Rgb(_) => None, }); stdout .write_colored(fg, bg, format!("{:>4}", fixed).as_bytes()) .map(|_| ()) } #[derive(Default)] struct Args { effects: anstyle::Effects, layer: Layer, } #[derive(Copy, Clone, Default)] enum Layer { #[default] Fg, Bg, Underline, } impl Args { fn parse() -> Result { use lexopt::prelude::*; let mut res = Args::default(); let mut args = lexopt::Parser::from_env(); while let Some(arg) = args.next()? { match arg { Long("layer") => { res.layer = args.value()?.parse_with(|s| match s { "fg" => Ok(Layer::Fg), "bg" => Ok(Layer::Bg), "underline" => Ok(Layer::Underline), _ => Err("expected values fg, bg, underline"), })?; } Long("effect") => { const EFFECTS: [(&str, anstyle::Effects); 12] = [ ("bold", anstyle::Effects::BOLD), ("dimmed", anstyle::Effects::DIMMED), ("italic", anstyle::Effects::ITALIC), ("underline", anstyle::Effects::UNDERLINE), ("double_underline", anstyle::Effects::UNDERLINE), ("curly_underline", anstyle::Effects::CURLY_UNDERLINE), ("dotted_underline", anstyle::Effects::DOTTED_UNDERLINE), ("dashed_underline", anstyle::Effects::DASHED_UNDERLINE), ("blink", anstyle::Effects::BLINK), ("invert", anstyle::Effects::INVERT), ("hidden", anstyle::Effects::HIDDEN), ("strikethrough", anstyle::Effects::STRIKETHROUGH), ]; let effect = args.value()?.parse_with(|s| { EFFECTS .into_iter() .find(|(name, _)| *name == s) .map(|(_, effect)| effect) .ok_or_else(|| { format!( "expected one of {}", EFFECTS .into_iter() .map(|(n, _)| n) .collect::>() .join(", ") ) }) })?; res.effects = res.effects.insert(effect); } _ => return Err(arg.unexpected()), } } Ok(res) } }