pub mod colorize; pub mod gradient; pub mod stateful; #[macro_export] macro_rules! cuteprint { ($($arg:tt)*) => {{ print!("{}", $crate::cute(&format!($($arg)*))); }}; } #[macro_export] macro_rules! cuteprintln { () => {{ println!(); }}; ($($arg:tt)*) => {{ println!("{}", $crate::cute(&format!($($arg)*))); }}; } #[macro_export] macro_rules! cute { ($($arg:tt)*) => {{ $crate::cute(&format!($($arg)*)) }}; } use crossterm::{ execute, style::{Color, Print, SetForegroundColor}, }; use std::io::{self, Write}; pub use colorize::{CutifiedString, Cutify}; pub use gradient::{ColorPalette, GradientConfig, GradientDirection, HueRange}; pub use stateful::{ cute, cuteprint, cuteprintln, reset_gradient, set_gradient_config, set_palette, }; #[macro_export] macro_rules! config_delegate { ($($method:ident($($arg:ident: $type:ty),*)),* $(,)?) => { $( pub fn $method(mut self, $($arg: $type),*) -> Self { self.config = self.config.$method($($arg),*); self } )* }; } pub fn cutify(text: &str) { cutify_with(text, &GradientConfig::default()); } pub fn cutify_with(text: &str, config: &GradientConfig) { let _ = cutify_to(text, config, &mut io::stdout()); } pub fn cutify_to(text: &str, config: &GradientConfig, writer: &mut W) -> io::Result<()> { execute!(writer, Print('\n'))?; let lines: Vec<&str> = text.lines().collect(); let max_height = lines.len(); let max_width = lines .iter() .map(|line| line.chars().count()) .max() .unwrap_or(0); for (row, line) in lines.iter().enumerate() { for (col, ch) in line.chars().enumerate() { let color = config.color_at_position(col, row, max_width, max_height); execute!(writer, SetForegroundColor(color), Print(ch))?; } execute!(writer, Print('\n'))?; } execute!(writer, SetForegroundColor(Color::Reset), Print('\n'))?; Ok(()) } pub fn cutify_string(text: &str, config: &GradientConfig) -> String { let mut buffer = Vec::new(); let _ = cutify_to(text, config, &mut buffer); String::from_utf8_lossy(&buffer).to_string() } pub struct Cutifier { text: String, config: GradientConfig, } impl Cutifier { pub fn new(text: impl Into) -> Self { Self { text: text.into(), config: GradientConfig::default(), } } config_delegate! { direction(direction: GradientDirection), hue_range(range: HueRange), saturation(saturation: f32), lightness(lightness: f32), hue_shift(shift: f32), base_hue(hue: f32), random_hue(), palette(palette: ColorPalette), reverse(), scale(scale: f32), step(step: f32), } pub fn print(&self) { cutify_with(&self.text, &self.config); } pub fn write_to(&self, writer: &mut W) -> io::Result<()> { cutify_to(&self.text, &self.config, writer) } } impl std::fmt::Display for Cutifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", cutify_string(&self.text, &self.config)) } }