From 0a27d6e180b4623287114fd5e7c0f037d56730ff Mon Sep 17 00:00:00 2001 From: Sam Mohr Date: Thu, 28 Dec 2023 00:34:19 -0800 Subject: [PATCH] feat: support ANSI themes --- yazi-plugin/src/external/highlighter.rs | 27 ++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/yazi-plugin/src/external/highlighter.rs b/yazi-plugin/src/external/highlighter.rs index a04b89ff..65ef2218 100644 --- a/yazi-plugin/src/external/highlighter.rs +++ b/yazi-plugin/src/external/highlighter.rs @@ -1,7 +1,8 @@ use std::{mem, path::{Path, PathBuf}, sync::{atomic::{AtomicUsize, Ordering}, OnceLock}}; use anyhow::{anyhow, Result}; -use syntect::{dumps::from_uncompressed_data, easy::HighlightLines, highlighting::{Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}, util::as_24_bit_terminal_escaped}; +use crossterm::{style::{Color, Print, SetForegroundColor}, Command}; +use syntect::{dumps::from_uncompressed_data, easy::HighlightLines, highlighting::{Style, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}}; use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}}; use yazi_config::THEME; use yazi_shared::PeekError; @@ -117,15 +118,35 @@ impl Highlighter { } let regions = h.highlight_line(&line, syntaxes).map_err(|e| anyhow!(e))?; - result.push_str(&as_24_bit_terminal_escaped(®ions, false)); + Self::write_highlighted_line_as_ansi(®ions, &mut result) + .map_err(|e| anyhow!("Failed to write highlighted text to preview window: {}", e))?; } - result.push_str("\x1b[0m"); + SetForegroundColor(Color::Reset) + .write_ansi(&mut result) + .map_err(|e| anyhow!("Failed to reset color at end of preview window line: {}", e))?; + Ok(result) }) .await? } + fn write_highlighted_line_as_ansi(regions: &[(Style, &str)], s: &mut String) -> std::fmt::Result { + for &(ref style, text) in regions { + let fg = style.foreground; + // As is done in the file previewer `bat`, we assume the convention that themes + // with a 0x00 alpha value are actually 8-bit themes, with their colors in the + // red color component. + let foreground_color = + if fg.a == 0 { Color::AnsiValue(fg.r) } else { Color::Rgb { r: fg.r, g: fg.g, b: fg.b } }; + + SetForegroundColor(foreground_color).write_ansi(s)?; + Print(text).write_ansi(s)?; + } + + Ok(()) + } + #[inline] pub fn abort() { INCR.fetch_add(1, Ordering::Relaxed); } }