diff --git a/Cargo.lock b/Cargo.lock index c926facf..919e36ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,9 @@ dependencies = [ [[package]] name = "anstyle" version = "0.2.5" +dependencies = [ + "lexopt", +] [[package]] name = "anstyle-ansi-term" @@ -193,6 +196,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lexopt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" + [[package]] name = "libc" version = "0.2.133" diff --git a/crates/anstyle/Cargo.toml b/crates/anstyle/Cargo.toml index dece8bc7..4e775911 100644 --- a/crates/anstyle/Cargo.toml +++ b/crates/anstyle/Cargo.toml @@ -26,3 +26,6 @@ default = ["std"] std = [] [dependencies] + +[dev-dependencies] +lexopt = "0.3.0" diff --git a/crates/anstyle/examples/dump.rs b/crates/anstyle/examples/dump.rs new file mode 100644 index 00000000..664dbdb7 --- /dev/null +++ b/crates/anstyle/examples/dump.rs @@ -0,0 +1,113 @@ +fn main() -> Result<(), lexopt::Error> { + let args = Args::parse()?; + + for fixed in 0..16 { + print_number(fixed, args.layer, args.effects); + if fixed == 7 || fixed == 15 { + println!(); + } + } + + for r in 0..6 { + println!(); + for g in 0..6 { + for b in 0..6 { + let fixed = r * 36 + g * 6 + b + 16; + print_number(fixed, args.layer, args.effects); + } + println!(); + } + } + + for c in 0..24 { + if 0 == c % 8 { + println!(); + } + let fixed = 232 + c; + print_number(fixed, args.layer, args.effects); + } + + Ok(()) +} + +#[derive(Default)] +struct Args { + effects: anstyle::Effects, + layer: Layer, +} + +#[derive(Copy, Clone)] +enum Layer { + Fg, + Bg, + Underline, +} + +impl Default for Layer { + fn default() -> Self { + Layer::Fg + } +} + +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); 8] = [ + ("bold", anstyle::Effects::BOLD), + ("dimmed", anstyle::Effects::DIMMED), + ("italic", anstyle::Effects::ITALIC), + ("underline", anstyle::Effects::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) + } +} + +fn print_number(fixed: u8, layer: Layer, effects: anstyle::Effects) { + let color = anstyle::XTermColor(fixed).into(); + let style = 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; + print!("{}{:>4}{}", style.render(), fixed, anstyle::Reset.render()); +}