a better coloring crate
Diffstat (limited to 'src/cfstr.rs')
| -rw-r--r-- | src/cfstr.rs | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/cfstr.rs b/src/cfstr.rs new file mode 100644 index 0000000..96699ca --- /dev/null +++ b/src/cfstr.rs @@ -0,0 +1,125 @@ +use proc_macro2::Literal; +use quote::{ToTokens, TokenStreamExt}; +use syn::{parse::Parse, LitStr, Result}; + +fn name2ansi(name: &str) -> Option<&'static str> { + Some(match name { + "black" => "\x1b[0;34;30m", + "red" => "\x1b[0;34;31m", + "green" => "\x1b[0;34;32m", + "yellow" => "\x1b[0;34;33m", + "blue" => "\x1b[0;34;34m", + "magenta" => "\x1b[0;34;35m", + "cyan" => "\x1b[0;34;36m", + "white" => "\x1b[0;34;37m", + "default" => "\x1b[0;34;39m", + + "bold_black" => "\x1b[1;34;30m", + "bold_red" => "\x1b[1;34;31m", + "bold_green" => "\x1b[1;34;32m", + "bold_yellow" => "\x1b[1;34;33m", + "bold_blue" => "\x1b[1;34;34m", + "bold_magenta" => "\x1b[1;34;35m", + "bold_cyan" => "\x1b[1;34;36m", + "bold_white" => "\x1b[1;34;37m", + "bold_default" => "\x1b[1;34;39m", + + "on_black_bold" => "\x1b[1;34;40m", + "on_red_bold" => "\x1b[1;34;41m", + "on_green_bold" => "\x1b[1;34;42m", + "on_yellow_bold" => "\x1b[1;34;43m", + "on_blue_bold" => "\x1b[1;34;44m", + "on_magenta_bold" => "\x1b[1;44;35m", + "on_cyan_bold" => "\x1b[1;34;46m", + "on_white_bold" => "\x1b[1;34;47m", + "on_default_bold" => "\x1b[1;34;49m", + + "on_black" => "\x1b[0;34;40m", + "on_red" => "\x1b[0;34;41m", + "on_green" => "\x1b[0;34;42m", + "on_yellow" => "\x1b[0;34;43m", + "on_blue" => "\x1b[0;34;44m", + "on_magenta" => "\x1b[0;44;35m", + "on_cyan" => "\x1b[0;34;46m", + "on_white" => "\x1b[0;34;47m", + "on_default" => "\x1b[0;34;49m", + + "reset" => "\x1b[0m", + "dim" => "\x1b[2m", + "italic" => "\x1b[3m", + "underline" => "\x1b[24m", + "blinking" => "\x1b[5m", + "hide" => "\x1b[8m", + "strike" => "\x1b[9m", + "bold" => "\x1b[1m", + _ => return None, + }) +} + +pub struct CFStr(String); + +impl Parse for CFStr { + fn parse(stream: syn::parse::ParseStream) -> Result<Self> { + let input = stream.parse::<LitStr>()?.value(); + let mut chars = input.chars().peekable(); + let mut temp = String::new(); + let mut out = String::new(); + while let Some(ch) = chars.next() { + match ch { + '{' => { + match chars.next() { + Some('{') => { + out.push('{'); + continue; + } + Some(ch) => temp.push(ch), + None => return Err(stream.error("unexpected eof")), + } + for ch in chars.by_ref() { + match ch { + '}' => { + if let Some(a) = name2ansi(&temp) { + out.push_str(a); + temp.clear(); + break; + } else if let Some((b, a)) = temp.split_once(':') { + if let Some(a) = name2ansi(a) { + out.push_str(name2ansi("reset").unwrap()); + out.push_str(a); + out.push('{'); + out.push_str(b); + out.push('}'); + out.push_str(name2ansi("reset").unwrap()); + temp.clear(); + break; + } + } + out.push('{'); + out.push_str(&temp); + out.push('}'); + temp.clear(); + break; + } + t => temp.push(t), + } + } + } + '}' => match chars.next() { + Some('}') => { + out.push('}'); + continue; + } + _ => return Err(stream.error("unexpected text")), + }, + c => out.push(c), + } + } + Ok(Self(out)) + } +} + +impl ToTokens for CFStr { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + tokens.append(Literal::string(&self.0)); + } +} |