a better coloring crate
Diffstat (limited to 'src/cfstr.rs')
-rw-r--r--src/cfstr.rs125
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));
+ }
+}