diff --git a/harper-core/src/linting/mod.rs b/harper-core/src/linting/mod.rs index 2398ca2bb..a65a63199 100644 --- a/harper-core/src/linting/mod.rs +++ b/harper-core/src/linting/mod.rs @@ -264,6 +264,49 @@ where } } +pub mod debug { + use crate::Token; + + /// Formats a lint match with surrounding context for debug output. + /// + /// The function takes the same `matched_tokens` and `source`, and `context` parameters + /// passed to `[match_to_lint_with_context]`. + /// + /// # Arguments + /// * `log` - `matched_tokens` + /// * `ctx` - `context`, or `None` if calling from `[match_to_lint]` + /// * `src` - `source` from `[match_to_lint]` / `[match_to_lint_with_context]` + /// + /// # Returns + /// A string with ANSI escape codes where: + /// - Context tokens are dimmed before and after the matched tokens in normal weight. + /// - Markup and formatting text hidden in whitespace tokens is filtered out. + pub fn format_lint_match( + log: &[Token], + ctx: Option<(&[Token], &[Token])>, + src: &[char], + ) -> String { + let fmt = |tokens: &[Token]| { + tokens + .iter() + .filter(|t| !t.kind.is_unlintable()) + .map(|t| t.span.get_content_string(src)) + .collect::() + }; + + if let Some((pro, epi)) = ctx { + format!( + "\x1b[2m{}\x1b[0m{}\x1b[2m{}\x1b[0m", + fmt(pro), + fmt(log), + fmt(epi) + ) + } else { + fmt(log) + } + } +} + #[cfg(test)] pub mod tests { use crate::parsers::Markdown;