chromasync-renderers 0.3.0

Built-in renderers and target registry for Chromasync
Documentation
use chromasync_types::{GeneratedArtifact, HexColor, RenderTarget, SemanticTokens};

use crate::{Renderer, RendererError, terminal_ansi_colors};

#[derive(Debug, Clone, Copy, Default)]
pub(crate) struct KittyRenderer;

#[derive(Debug, Clone, PartialEq, Eq)]
struct KittyTheme {
    foreground: HexColor,
    background: HexColor,
    selection_foreground: HexColor,
    selection_background: HexColor,
    cursor: HexColor,
    cursor_text: HexColor,
    url_color: HexColor,
    active_border_color: HexColor,
    inactive_border_color: HexColor,
    active_tab_background: HexColor,
    active_tab_foreground: HexColor,
    inactive_tab_background: HexColor,
    inactive_tab_foreground: HexColor,
    ansi: [HexColor; 16],
}

impl KittyRenderer {
    fn map(&self, tokens: &SemanticTokens) -> KittyTheme {
        KittyTheme {
            foreground: tokens.text.clone(),
            background: tokens.bg.clone(),
            selection_foreground: tokens.text.clone(),
            selection_background: tokens.selection.clone(),
            cursor: tokens.accent.clone(),
            cursor_text: tokens.accent_fg.clone(),
            url_color: tokens.link.clone(),
            active_border_color: tokens.accent.clone(),
            inactive_border_color: tokens.border.clone(),
            active_tab_background: tokens.accent.clone(),
            active_tab_foreground: tokens.accent_fg.clone(),
            inactive_tab_background: tokens.surface.clone(),
            inactive_tab_foreground: tokens.text_muted.clone(),
            ansi: terminal_ansi_colors(tokens),
        }
    }

    fn render(&self, theme: &KittyTheme) -> String {
        format!(
            concat!(
                "background {background}\n",
                "foreground {foreground}\n",
                "selection_background {selection_background}\n",
                "selection_foreground {selection_foreground}\n",
                "cursor {cursor}\n",
                "cursor_text_color {cursor_text}\n",
                "url_color {url_color}\n",
                "active_border_color {active_border_color}\n",
                "inactive_border_color {inactive_border_color}\n",
                "active_tab_background {active_tab_background}\n",
                "active_tab_foreground {active_tab_foreground}\n",
                "inactive_tab_background {inactive_tab_background}\n",
                "inactive_tab_foreground {inactive_tab_foreground}\n",
                "color0 {color0}\n",
                "color1 {color1}\n",
                "color2 {color2}\n",
                "color3 {color3}\n",
                "color4 {color4}\n",
                "color5 {color5}\n",
                "color6 {color6}\n",
                "color7 {color7}\n",
                "color8 {color8}\n",
                "color9 {color9}\n",
                "color10 {color10}\n",
                "color11 {color11}\n",
                "color12 {color12}\n",
                "color13 {color13}\n",
                "color14 {color14}\n",
                "color15 {color15}\n"
            ),
            background = theme.background,
            foreground = theme.foreground,
            selection_background = theme.selection_background,
            selection_foreground = theme.selection_foreground,
            cursor = theme.cursor,
            cursor_text = theme.cursor_text,
            url_color = theme.url_color,
            active_border_color = theme.active_border_color,
            inactive_border_color = theme.inactive_border_color,
            active_tab_background = theme.active_tab_background,
            active_tab_foreground = theme.active_tab_foreground,
            inactive_tab_background = theme.inactive_tab_background,
            inactive_tab_foreground = theme.inactive_tab_foreground,
            color0 = theme.ansi[0],
            color1 = theme.ansi[1],
            color2 = theme.ansi[2],
            color3 = theme.ansi[3],
            color4 = theme.ansi[4],
            color5 = theme.ansi[5],
            color6 = theme.ansi[6],
            color7 = theme.ansi[7],
            color8 = theme.ansi[8],
            color9 = theme.ansi[9],
            color10 = theme.ansi[10],
            color11 = theme.ansi[11],
            color12 = theme.ansi[12],
            color13 = theme.ansi[13],
            color14 = theme.ansi[14],
            color15 = theme.ansi[15],
        )
    }
}

impl Renderer for KittyRenderer {
    fn target(&self) -> RenderTarget {
        RenderTarget::Kitty
    }

    fn name(&self) -> &'static str {
        "kitty"
    }

    fn render_artifact(&self, tokens: &SemanticTokens) -> Result<GeneratedArtifact, RendererError> {
        let theme = self.map(tokens);

        Ok(GeneratedArtifact {
            target: self.name().to_owned(),
            file_name: self.file_name().to_owned(),
            content: self.render(&theme),
        })
    }
}