From fa1e2d39a2f8a1f5bc1fab97d9e4c665b73e91e8 Mon Sep 17 00:00:00 2001 From: yggverse Date: Mon, 2 Dec 2024 22:29:50 +0200 Subject: [PATCH] draft syntax highlight features by syntect --- Cargo.toml | 6 ++- .../item/page/content/text/gemini/reader.rs | 45 +++++++++++++------ .../page/content/text/gemini/reader/syntax.rs | 35 +++++++++++++++ 3 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs diff --git a/Cargo.toml b/Cargo.toml index 4b3d8947..7a5ebf6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,11 @@ version = "0.32.1" [dependencies.openssl] version = "0.10.68" +[dependencies] +syntect = "5.2.0" + # development [patch.crates-io] #ggemini = { path = "ggemini" } -ggemtext = { git = "https://github.com/YGGverse/ggemtext.git" } +#ggemtext = { git = "https://github.com/YGGverse/ggemtext.git" } +ggemtext = { path = "ggemtext" } diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs index 68474c52..97ecc564 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader.rs @@ -1,8 +1,10 @@ pub mod error; +mod syntax; mod tag; mod widget; pub use error::Error; +use syntax::Syntax; use tag::Tag; use widget::Widget; @@ -53,6 +55,9 @@ impl Reader { // Init multiline code builder features let mut multiline = None; + // Init syntect highlight features + let syntax = Syntax::new(); + // Init tags let tag = Tag::new(); @@ -66,7 +71,10 @@ impl Reader { // Append value to buffer buffer.insert_with_tags( &mut buffer.end_iter(), - code.value.as_str(), + &match syntax.highlight(&code.value, None) { + Some(result) => result, + None => code.value.to_string(), + }, &[&tag.code.text_tag], ); buffer.insert(&mut buffer.end_iter(), NEW_LINE); @@ -93,22 +101,31 @@ impl Reader { // Close tag found: if this.completed { // Is alt provided - if let Some(alt) = &this.alt { - // Insert alt value to the main buffer - buffer.insert_with_tags( - &mut buffer.end_iter(), - alt.as_str(), - &[&tag.title.text_tag], - ); + let alt = match this.alt { + Some(ref alt) => { + // Insert alt value to the main buffer + buffer.insert_with_tags( + &mut buffer.end_iter(), + alt.as_str(), + &[&tag.title.text_tag], + ); - // Append new line after alt text - buffer.insert(&mut buffer.end_iter(), NEW_LINE); - } + // Append new line after alt text + buffer.insert(&mut buffer.end_iter(), NEW_LINE); + + // Return value as wanted also for syntax highlight detection + Some(alt) + } + None => None, + }; // Insert multiline code buffer into main buffer buffer.insert_with_tags( &mut buffer.end_iter(), - &this.value, + &match syntax.highlight(&this.value, alt) { + Some(result) => result, + None => this.value.to_string(), + }, &[&tag.code.text_tag], ); @@ -316,8 +333,8 @@ impl Reader { None::<&Window>, None::<&Cancellable>, |result| { - if let Err(error) = result { - println!("{error}") + if let Err(e) = result { + println!("{e}") } }, ), diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs new file mode 100644 index 00000000..f3026f47 --- /dev/null +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/syntax.rs @@ -0,0 +1,35 @@ +use syntect::{ + easy::HighlightLines, highlighting::ThemeSet, parsing::SyntaxSet, + util::as_24_bit_terminal_escaped, +}; + +pub const DEFAULT_THEME: &str = "base16-ocean.dark"; + +pub struct Syntax { + syntax_set: SyntaxSet, + theme_set: ThemeSet, +} + +impl Syntax { + pub fn new() -> Self { + Self { + syntax_set: SyntaxSet::load_defaults_newlines(), + theme_set: ThemeSet::load_defaults(), + } + } + + pub fn highlight(&self, source: &str, extension: Option<&String>) -> Option { + match extension { + Some(extension) => match self.syntax_set.find_syntax_by_extension(extension) { + Some(syntax) => { + let ranges = HighlightLines::new(syntax, &self.theme_set.themes[DEFAULT_THEME]) + .highlight_line(&source, &self.syntax_set) + .unwrap(); // @TODO + Some(as_24_bit_terminal_escaped(&ranges[..], true)) + } + None => None, + }, + None => None, // @TODO detect by source + } + } +}