draft highlight tag implementation

This commit is contained in:
yggverse 2024-12-03 01:23:23 +02:00
parent ac1b896fc0
commit 70dfac115f
2 changed files with 115 additions and 28 deletions

View File

@ -69,14 +69,22 @@ impl Reader {
// Is inline code // Is inline code
if let Some(code) = Code::inline_from(line) { if let Some(code) = Code::inline_from(line) {
// Append value to buffer // Append value to buffer
buffer.insert_with_tags( match syntax.highlight(&code.value, &tag.code.text_tag, None) {
&mut buffer.end_iter(), Ok(highlight) => {
&match syntax.auto_highlight(&code.value, None) { for (text_tag, entity) in highlight {
Ok(highlight) => highlight, buffer.insert_with_tags(&mut buffer.end_iter(), &entity, &[&text_tag]);
Err(_) => code.value.to_string(), // @TODO handle }
}, }
&[&tag.code.text_tag], Err(_) => {
); buffer.insert_with_tags(
&mut buffer.end_iter(),
&code.value,
&[&tag.code.text_tag],
);
} // @TODO handle
}
// Append new line
buffer.insert(&mut buffer.end_iter(), NEW_LINE); buffer.insert(&mut buffer.end_iter(), NEW_LINE);
// Skip other actions for this line // Skip other actions for this line
@ -119,15 +127,25 @@ impl Reader {
None => None, None => None,
}; };
// Insert multiline code buffer into main buffer // Insert multiline code into main buffer
buffer.insert_with_tags( match syntax.highlight(&this.value, &tag.code.text_tag, alt) {
&mut buffer.end_iter(), Ok(highlight) => {
&match syntax.auto_highlight(&this.value, alt) { for (text_tag, entity) in highlight {
Ok(highlight) => highlight, buffer.insert_with_tags(
Err(_) => this.value.to_string(), // @TODO handle &mut buffer.end_iter(),
}, &entity,
&[&tag.code.text_tag], &[&text_tag],
); );
}
}
Err(_) => {
buffer.insert_with_tags(
&mut buffer.end_iter(),
&this.value,
&[&tag.code.text_tag],
);
} // @TODO handle
}
// Reset // Reset
multiline = None; multiline = None;

View File

@ -1,8 +1,13 @@
use gtk::{
gdk::RGBA,
pango::{Style, Underline},
prelude::TextTagExt,
TextTag,
};
use syntect::{ use syntect::{
easy::HighlightLines, easy::HighlightLines,
highlighting::ThemeSet, highlighting::{Color, FontStyle, ThemeSet},
parsing::{SyntaxReference, SyntaxSet}, parsing::{SyntaxReference, SyntaxSet},
util::as_24_bit_terminal_escaped,
Error, Error,
}; };
@ -21,28 +26,92 @@ impl Syntax {
} }
} }
pub fn auto_highlight(&self, source: &str, alt: Option<&String>) -> Result<String, Error> { pub fn highlight(
&self,
source_code: &str,
source_tag: &TextTag,
alt: Option<&String>,
) -> Result<Vec<(TextTag, String)>, Error> {
if let Some(name) = alt { if let Some(name) = alt {
if let Some(syntax_reference) = self.syntax_set.find_syntax_by_name(name) { if let Some(reference) = self.syntax_set.find_syntax_by_extension(name) {
return self.highlight(source, syntax_reference); return self.syntect_buffer(source_code, source_tag, reference);
} }
} }
if let Some(syntax_reference) = self.syntax_set.find_syntax_by_first_line(source) { if let Some(reference) = self.syntax_set.find_syntax_by_first_line(source_code) {
return self.highlight(source, syntax_reference); return self.syntect_buffer(source_code, source_tag, reference);
} }
Ok(source.to_string()) Ok(self.default_buffer(source_code, source_tag))
} }
pub fn highlight( fn default_buffer(&self, source: &str, source_tag: &TextTag) -> Vec<(TextTag, String)> {
// Init new line buffer
let mut buffer = Vec::new();
// Create new tag from source preset
let mut tag = TextTag::new(None);
tag.clone_from(source_tag);
// Append
buffer.push((tag, source.to_string()));
buffer
}
fn syntect_buffer(
&self, &self,
source: &str, source: &str,
source_tag: &TextTag,
syntax_reference: &SyntaxReference, syntax_reference: &SyntaxReference,
) -> Result<String, Error> { ) -> Result<Vec<(TextTag, String)>, Error> {
// Init new line buffer
let mut buffer = Vec::new();
// Apply syntect decorator
let ranges = HighlightLines::new(syntax_reference, &self.theme_set.themes[DEFAULT_THEME]) let ranges = HighlightLines::new(syntax_reference, &self.theme_set.themes[DEFAULT_THEME])
.highlight_line(&source, &self.syntax_set)?; .highlight_line(&source, &self.syntax_set)?;
Ok(as_24_bit_terminal_escaped(&ranges[..], true)) // Build tags
for (style, entity) in ranges {
// Create new tag from source preset
let mut tag = TextTag::new(None);
tag.clone_from(source_tag);
// Tuneup using syntect conversion
tag.set_background_rgba(Some(&color_to_rgba(style.background)));
tag.set_foreground_rgba(Some(&color_to_rgba(style.foreground)));
tag.set_style(font_style_to_style(style.font_style));
tag.set_underline(font_style_to_underline(style.font_style));
// Append
buffer.push((tag, entity.to_string()));
}
Ok(buffer)
}
}
// Tools
fn color_to_rgba(color: Color) -> RGBA {
RGBA::new(
color.r.into(),
color.g.into(),
color.b.into(),
color.a.into(),
)
}
fn font_style_to_style(font_style: FontStyle) -> Style {
match font_style {
FontStyle::ITALIC => Style::Italic,
_ => Style::Normal,
}
}
fn font_style_to_underline(font_style: FontStyle) -> Underline {
match font_style {
FontStyle::UNDERLINE => Underline::Single,
_ => Underline::None,
} }
} }