Skip to main content

farben_core/
debug.rs

1use crate::{
2    ansi::{Color, Ground, NamedColor},
3    lexer::{EmphasisType, TagType, Token},
4};
5
6/// Converts a `TagType` into its farben markup representation.
7///
8/// Example: `TagType::Emphasis(EmphasisType::Bold)` → `"bold"`.
9pub fn tag_to_markup_part(tag: &TagType) -> String {
10    match tag {
11        TagType::Emphasis(e) => match e {
12            EmphasisType::Bold => "bold".to_string(),
13            EmphasisType::Blink => "blink".to_string(),
14            EmphasisType::Dim => "dim".to_string(),
15            EmphasisType::Italic => "italic".to_string(),
16            EmphasisType::Strikethrough => "strikethrough".to_string(),
17            EmphasisType::Underline => "underline".to_string(),
18            EmphasisType::DoubleUnderline => "double-underline".to_string(),
19            EmphasisType::Overline => "overline".to_string(),
20            EmphasisType::Invisible => "invisible".to_string(),
21            EmphasisType::Reverse => "reverse".to_string(),
22            EmphasisType::RapidBlink => "rapid-blink".to_string(),
23        },
24        TagType::Color { color, ground } => {
25            let prepend = match ground {
26                Ground::Background => "bg:",
27                _ => "",
28            };
29            match color {
30                Color::Ansi256(a) => format!("{prepend}ansi({a})"),
31                Color::Named(n) => {
32                    let name = match n {
33                        NamedColor::Black => "black",
34                        NamedColor::Red => "red",
35                        NamedColor::Green => "green",
36                        NamedColor::Yellow => "yellow",
37                        NamedColor::Blue => "blue",
38                        NamedColor::Magenta => "magenta",
39                        NamedColor::Cyan => "cyan",
40                        NamedColor::White => "white",
41                        NamedColor::BrightBlack => "bright-black",
42                        NamedColor::BrightRed => "bright-red",
43                        NamedColor::BrightGreen => "bright-green",
44                        NamedColor::BrightYellow => "bright-yellow",
45                        NamedColor::BrightBlue => "bright-blue",
46                        NamedColor::BrightMagenta => "bright-magenta",
47                        NamedColor::BrightCyan => "bright-cyan",
48                        NamedColor::BrightWhite => "bright-white",
49                    };
50                    format!("{prepend}{name}")
51                }
52                Color::Rgb(r, g, b) => format!("{prepend}rgb({r},{g},{b})"),
53            }
54        }
55        TagType::ResetAll => "/".to_string(),
56        TagType::ResetOne(inner) => format!("/{}", tag_to_markup_part(inner)),
57        TagType::Prefix(_) => String::new(),
58    }
59}
60
61/// Converts a sequence of `Token`s back into a farben markup string.
62///
63/// The inverse of [`tokenize`](crate::lexer::tokenize).
64pub fn tokens_to_markup(tokens: &[Token]) -> String {
65    let mut result = String::new();
66    let mut i = 0;
67
68    while i < tokens.len() {
69        match &tokens[i] {
70            Token::Text(s) => {
71                result.push_str(s);
72                i += 1;
73            }
74            Token::Tag(_) => {
75                let mut parts = Vec::new();
76                while i < tokens.len() {
77                    if let Token::Tag(tag) = &tokens[i] {
78                        parts.push(tag_to_markup_part(tag));
79                        i += 1;
80                    } else {
81                        break;
82                    }
83                }
84                result.push('[');
85                result.push_str(&parts.join(" "));
86                result.push(']');
87            }
88        }
89    }
90
91    result
92}