1use std::io::Write;
2
3fn main() -> Result<(), lexopt::Error> {
4 let args = Args::parse()?;
5 let stdout = std::io::stdout();
6 let mut stdout = stdout.lock();
7
8 for fixed in 0..16 {
9 let style = style(fixed, args.layer, args.effects);
10 let _ = print_number(&mut stdout, fixed, style);
11 if fixed == 7 || fixed == 15 {
12 let _ = writeln!(&mut stdout);
13 }
14 }
15
16 for r in 0..6 {
17 let _ = writeln!(stdout);
18 for g in 0..6 {
19 for b in 0..6 {
20 let fixed = r * 36 + g * 6 + b + 16;
21 let style = style(fixed, args.layer, args.effects);
22 let _ = print_number(&mut stdout, fixed, style);
23 }
24 let _ = writeln!(stdout);
25 }
26 }
27
28 for c in 0..24 {
29 if 0 == c % 8 {
30 let _ = writeln!(stdout);
31 }
32 let fixed = 232 + c;
33 let style = style(fixed, args.layer, args.effects);
34 let _ = print_number(&mut stdout, fixed, style);
35 }
36
37 Ok(())
38}
39
40fn style(fixed: u8, layer: Layer, effects: anstyle::Effects) -> anstyle::Style {
41 let color = anstyle::Ansi256Color(fixed).into();
42 (match layer {
43 Layer::Fg => anstyle::Style::new().fg_color(Some(color)),
44 Layer::Bg => anstyle::Style::new().bg_color(Some(color)),
45 Layer::Underline => anstyle::Style::new().underline_color(Some(color)),
46 }) | effects
47}
48
49fn print_number(
50 stdout: &mut std::io::StdoutLock<'_>,
51 fixed: u8,
52 style: anstyle::Style,
53) -> std::io::Result<()> {
54 write!(
55 stdout,
56 "{}{:>4}{}",
57 style.render(),
58 fixed,
59 anstyle::Reset.render()
60 )
61}
62
63#[derive(Default)]
64struct Args {
65 effects: anstyle::Effects,
66 layer: Layer,
67}
68
69#[derive(Copy, Clone, Default)]
70enum Layer {
71 #[default]
72 Fg,
73 Bg,
74 Underline,
75}
76
77impl Args {
78 fn parse() -> Result<Self, lexopt::Error> {
79 use lexopt::prelude::*;
80
81 let mut res = Args::default();
82
83 let mut args = lexopt::Parser::from_env();
84 while let Some(arg) = args.next()? {
85 match arg {
86 Long("layer") => {
87 res.layer = args.value()?.parse_with(|s| match s {
88 "fg" => Ok(Layer::Fg),
89 "bg" => Ok(Layer::Bg),
90 "underline" => Ok(Layer::Underline),
91 _ => Err("expected values fg, bg, underline"),
92 })?;
93 }
94 Long("effect") => {
95 const EFFECTS: [(&str, anstyle::Effects); 12] = [
96 ("bold", anstyle::Effects::BOLD),
97 ("dimmed", anstyle::Effects::DIMMED),
98 ("italic", anstyle::Effects::ITALIC),
99 ("underline", anstyle::Effects::UNDERLINE),
100 ("double_underline", anstyle::Effects::DOUBLE_UNDERLINE),
101 ("curly_underline", anstyle::Effects::CURLY_UNDERLINE),
102 ("dotted_underline", anstyle::Effects::DOTTED_UNDERLINE),
103 ("dashed_underline", anstyle::Effects::DASHED_UNDERLINE),
104 ("blink", anstyle::Effects::BLINK),
105 ("invert", anstyle::Effects::INVERT),
106 ("hidden", anstyle::Effects::HIDDEN),
107 ("strikethrough", anstyle::Effects::STRIKETHROUGH),
108 ];
109 let effect = args.value()?.parse_with(|s| {
110 EFFECTS
111 .into_iter()
112 .find(|(name, _)| *name == s)
113 .map(|(_, effect)| effect)
114 .ok_or_else(|| {
115 format!(
116 "expected one of {}",
117 EFFECTS
118 .into_iter()
119 .map(|(n, _)| n)
120 .collect::<Vec<_>>()
121 .join(", ")
122 )
123 })
124 })?;
125 res.effects = res.effects.insert(effect);
126 }
127 _ => return Err(arg.unexpected()),
128 }
129 }
130 Ok(res)
131 }
132}
133