1 | use std::io::Write; |
2 | |
3 | fn 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 | |
40 | fn 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 | |
49 | fn 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)] |
64 | struct Args { |
65 | effects: anstyle::Effects, |
66 | layer: Layer, |
67 | } |
68 | |
69 | #[derive(Copy, Clone, Default)] |
70 | enum Layer { |
71 | #[default] |
72 | Fg, |
73 | Bg, |
74 | Underline, |
75 | } |
76 | |
77 | impl 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 | |