pulldown_cmark_mdcat/render/
highlighting.rs1use anstyle::{AnsiColor, Effects};
10use std::{
11 io::{Result, Write},
12 sync::OnceLock,
13};
14use syntect::highlighting::{FontStyle, Highlighter, Style, Theme};
15
16static SOLARIZED_DARK_DUMP: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/theme.dump"));
17static THEME: OnceLock<Theme> = OnceLock::new();
18static HIGHLIGHTER: OnceLock<Highlighter> = OnceLock::new();
19
20fn theme() -> &'static Theme {
21 THEME.get_or_init(|| syntect::dumps::from_binary(SOLARIZED_DARK_DUMP))
22}
23
24pub fn highlighter() -> &'static Highlighter<'static> {
25 HIGHLIGHTER.get_or_init(|| Highlighter::new(theme()))
26}
27
28pub fn write_as_ansi<'a, W: Write, I: Iterator<Item = (Style, &'a str)>>(
44 writer: &mut W,
45 regions: I,
46) -> Result<()> {
47 for (style, text) in regions {
48 let rgb = {
49 let fg = style.foreground;
50 (fg.r, fg.g, fg.b)
51 };
52 let color = match rgb {
53 (0x00, 0x2b, 0x36)
55 | (0x07, 0x36, 0x42)
56 | (0x58, 0x6e, 0x75)
57 | (0x65, 0x7b, 0x83)
58 | (0x83, 0x94, 0x96)
59 | (0x93, 0xa1, 0xa1)
60 | (0xee, 0xe8, 0xd5)
61 | (0xfd, 0xf6, 0xe3) => None,
62 (0xb5, 0x89, 0x00) => Some(AnsiColor::Yellow.into()),
63 (0xcb, 0x4b, 0x16) => Some(AnsiColor::BrightRed.into()),
64 (0xdc, 0x32, 0x2f) => Some(AnsiColor::Red.into()),
65 (0xd3, 0x36, 0x82) => Some(AnsiColor::Magenta.into()),
66 (0x6c, 0x71, 0xc4) => Some(AnsiColor::BrightMagenta.into()),
67 (0x26, 0x8b, 0xd2) => Some(AnsiColor::Blue.into()),
68 (0x2a, 0xa1, 0x98) => Some(AnsiColor::Cyan.into()),
69 (0x85, 0x99, 0x00) => Some(AnsiColor::Green.into()),
70 (r, g, b) => panic!("Unexpected RGB colour: #{r:2>0x}{g:2>0x}{b:2>0x}"),
71 };
72 let font = style.font_style;
73 let effects = Effects::new()
74 .set(Effects::BOLD, font.contains(FontStyle::BOLD))
75 .set(Effects::ITALIC, font.contains(FontStyle::ITALIC))
76 .set(Effects::UNDERLINE, font.contains(FontStyle::UNDERLINE));
77 let style = anstyle::Style::new().fg_color(color).effects(effects);
78 write!(writer, "{}{}{}", style.render(), text, style.render_reset())?;
79 }
80 Ok(())
81}