diff --git a/Cargo.toml b/Cargo.toml index 9fc5fb0..384860d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,13 @@ description = "Formats whitespace in a SQL string to make it easier to read" keywords = ["sql"] categories = ["development-tools"] +[features] +debug = ["dep:anstream", "dep:anstyle", "dep:okhsl"] + [dependencies] +anstream = { version = "0.6.21", optional = true } +anstyle = { version = "1.0.13", optional = true } +okhsl = { version = "1.0.1", optional = true } unicode_categories = "0.1.1" winnow = { version = "0.7.0", features = ["simd"] } diff --git a/src/debug.rs b/src/debug.rs new file mode 100644 index 0000000..aaadea7 --- /dev/null +++ b/src/debug.rs @@ -0,0 +1,25 @@ +use std::hash::{DefaultHasher, Hash, Hasher}; + +use anstyle::RgbColor; + +pub(crate) trait ToColor { + fn to_color(&self) -> RgbColor; +} + +impl ToColor for T { + fn to_color(&self) -> RgbColor { + let mut s = DefaultHasher::new(); + self.hash(&mut s); + + let v = s.finish(); + + let v = ((v >> 32) as u32) ^ (v as u32); + + let h = v as f64 / u32::MAX as f64; + + let c = okhsl::Okhsv { h, s: 0.7, v: 0.9 }; + let r = c.to_srgb(); + + RgbColor(r.r, r.g, r.b) + } +} diff --git a/src/formatter.rs b/src/formatter.rs index 58d37c8..12f00a0 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -139,6 +139,43 @@ pub(crate) fn format( } }, } + + #[cfg(feature = "debug")] + { + use crate::debug::*; + let b = anstyle::Style::new().bold(); + let k = b.fg_color(Some(token.kind.to_color().into())); + let rk = k.render_reset(); + let k = k.render(); + let d = anstyle::Style::new().dimmed(); + let rd = d.render_reset(); + let d = d.render(); + + let kind = format!("{:?}", token.kind); + + let mut lines = formatted_query + .lines() + .rev() + .filter(|l| !l.trim().is_empty()); + let line = lines.next().unwrap_or(formatted_query.as_str()); + let value = match token.kind { + TokenKind::Whitespace => { + let s = token + .value + .chars() + .map(|c| match c { + '\n' => Cow::Borrowed(r"\n"), + '\t' => Cow::Borrowed(r"\t"), + '\r' => Cow::Borrowed(r"\r"), + _ => c.to_string().into(), + }) + .collect::(); + s.into() + } + _ => Cow::Borrowed(token.value), + }; + anstream::eprintln!("{k}{:21}{rk}: {d}{:50}{rd} {line}", kind, value); + } } formatted_query.trim().to_string() } diff --git a/src/lib.rs b/src/lib.rs index 2f7b28f..9734e70 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,9 @@ mod inline_block; mod params; mod tokenizer; +#[cfg(feature = "debug")] +mod debug; + /// Formats whitespace in a SQL string to make it easier to read. /// Optionally replaces parameter placeholders with `params`. pub fn format(query: &str, params: &QueryParams, options: &FormatOptions) -> String { diff --git a/src/tokenizer.rs b/src/tokenizer.rs index ab813f6..de125dc 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -73,7 +73,7 @@ pub(crate) struct Token<'a> { pub alias: &'a str, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(crate) enum TokenKind { TypeSpecifier, Whitespace,