use smol_str::SmolStr;
#[derive(Debug, Clone)]
pub struct HighlightConfig {
pub highlighted_lines: Vec<usize>,
pub rainbow: bool,
}
impl Default for HighlightConfig {
fn default() -> Self {
Self {
highlighted_lines: Vec::new(),
rainbow: true,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Highlighted<'a> {
pub lines: Vec<Line<'a>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Line<'a> {
pub number: usize,
pub highlighted: bool,
pub tokens: Vec<Token<'a>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Token<'a> {
pub text: &'a str,
pub highlight: Option<&'a str>,
pub rainbow: Option<usize>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HighlightResult {
pub lines: Vec<OwnedLine>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OwnedLine {
pub number: usize,
pub highlighted: bool,
pub tokens: Vec<OwnedToken>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OwnedToken {
pub text: String,
pub highlight: Option<SmolStr>,
pub rainbow: Option<usize>,
}
impl Highlighted<'_> {
pub fn to_owned(&self) -> HighlightResult {
HighlightResult {
lines: self
.lines
.iter()
.map(|line| OwnedLine {
number: line.number,
highlighted: line.highlighted,
tokens: line
.tokens
.iter()
.map(|token| OwnedToken {
text: token.text.to_owned(),
highlight: token.highlight.map(SmolStr::new),
rainbow: token.rainbow,
})
.collect(),
})
.collect(),
}
}
}
impl HighlightResult {
pub fn as_highlighted(&self) -> Highlighted<'_> {
Highlighted {
lines: self
.lines
.iter()
.map(|line| Line {
number: line.number,
highlighted: line.highlighted,
tokens: line
.tokens
.iter()
.map(|token| Token {
text: &token.text,
highlight: token.highlight.as_deref(),
rainbow: token.rainbow,
})
.collect(),
})
.collect(),
}
}
pub fn with_highlighted_lines(&self, lines: &[usize]) -> Highlighted<'_> {
let mut highlighted = self.as_highlighted();
let mut selected = lines.to_vec();
selected.sort_unstable();
let mut selected = selected.into_iter().peekable();
for line in &mut highlighted.lines {
while selected.peek().is_some_and(|number| *number < line.number) {
selected.next();
}
line.highlighted = selected.peek() == Some(&line.number);
}
highlighted
}
#[cfg(feature = "render-html")]
pub fn render_html(&self, theme: &crate::Theme, config: &crate::RenderHtmlConfig) -> String {
crate::render::html::render(self.lines.iter(), Some(theme), &[], config, false)
}
#[cfg(feature = "render-html")]
pub fn render_html_classes(&self, config: &crate::RenderHtmlConfig) -> String {
crate::render::html::render(self.lines.iter(), None, &[], config, false)
}
#[cfg(feature = "render-html")]
pub fn render_html_themes(
&self,
themes: &[(&str, &crate::Theme)],
default_theme: &str,
config: &crate::RenderHtmlConfig,
) -> Result<String, crate::Error> {
crate::render::html::render_themes(self.lines.iter(), themes, default_theme, config)
}
#[cfg(feature = "render-ansi")]
pub fn render_ansi(&self, theme: &crate::Theme) -> String {
crate::render::ansi::render(self.lines.iter(), theme)
}
}