This commit is contained in:
sxyazi 2024-08-05 13:06:34 +08:00
parent 0c24307555
commit ed806bdced
No known key found for this signature in database
3 changed files with 26 additions and 41 deletions

View file

@ -199,10 +199,10 @@ impl Emulator {
bail!("unexpected EOF");
}
buf.push(c[0]);
if c[0] != b'c' || !buf.contains(&b'\x1b') {
if c[0] != b'c' || !buf.contains(&0x1b) {
continue;
}
if buf.rsplitn(2, |&b| b == b'\x1b').next().is_some_and(|s| s.starts_with(b"[?")) {
if buf.rsplitn(2, |&b| b == 0x1b).next().is_some_and(|s| s.starts_with(b"[?")) {
break;
}
}

View file

@ -21,7 +21,7 @@ impl<'a> Input<'a> {
bail!("Highlighting is disabled");
}
let (theme, syntaxes) = Highlighter::init();
let (theme, syntaxes) = futures::executor::block_on(Highlighter::init());
if let Some(syntax) = syntaxes.find_syntax_by_name("Bourne Again Shell (bash)") {
let mut h = HighlightLines::new(syntax, theme);
let regions = h.highlight_line(self.cx.input.value(), syntaxes)?;

View file

@ -1,15 +1,14 @@
use std::{io::Cursor, mem, path::{Path, PathBuf}, sync::{atomic::{AtomicUsize, Ordering}, OnceLock}};
use std::{io::Cursor, mem, path::{Path, PathBuf}, sync::atomic::{AtomicUsize, Ordering}};
use anyhow::{anyhow, Result};
use ratatui::text::{Line, Span, Text};
use syntect::{dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}};
use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}};
use syntect::{dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}, LoadingError};
use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, sync::OnceCell};
use yazi_config::{PREVIEW, THEME};
use yazi_shared::PeekError;
static INCR: AtomicUsize = AtomicUsize::new(0);
static SYNTECT_SYNTAX: OnceLock<SyntaxSet> = OnceLock::new();
static SYNTECT_THEME: OnceLock<Theme> = OnceLock::new();
static SYNTECT: OnceCell<(Theme, SyntaxSet)> = OnceCell::const_new();
pub struct Highlighter {
path: PathBuf,
@ -19,27 +18,28 @@ impl Highlighter {
#[inline]
pub fn new(path: &Path) -> Self { Self { path: path.to_owned() } }
pub fn init() -> (&'static Theme, &'static SyntaxSet) {
#[inline]
fn from_file() -> Result<Theme> {
let file = std::fs::File::open(&THEME.manager.syntect_theme)?;
Ok(ThemeSet::load_from_reader(&mut std::io::BufReader::new(file))?)
}
pub async fn init() -> (&'static Theme, &'static SyntaxSet) {
let fut = async {
tokio::task::spawn_blocking(|| {
let theme = std::fs::File::open(&THEME.manager.syntect_theme)
.map_err(LoadingError::Io)
.and_then(|f| ThemeSet::load_from_reader(&mut std::io::BufReader::new(f)))
.or_else(|_| ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuild::ansi_theme())));
let theme = SYNTECT_THEME.get_or_init(|| {
from_file().unwrap_or_else(|_| {
ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuild::ansi_theme())).unwrap()
let syntaxes = dumps::from_uncompressed_data(yazi_prebuild::syntaxes());
(theme.unwrap(), syntaxes.unwrap())
})
});
.await
.unwrap()
};
let syntaxes = SYNTECT_SYNTAX
.get_or_init(|| dumps::from_uncompressed_data(yazi_prebuild::syntaxes()).unwrap());
(theme, syntaxes)
let r = SYNTECT.get_or_init(|| fut).await;
(&r.0, &r.1)
}
async fn find_syntax(path: &Path) -> Result<&'static SyntaxReference> {
let (_, syntaxes) = Self::init();
let (_, syntaxes) = Self::init().await;
let name = path.file_name().map(|n| n.to_string_lossy()).unwrap_or_default();
if let Some(s) = syntaxes.find_syntax_by_extension(&name) {
return Ok(s);
@ -73,7 +73,7 @@ impl Highlighter {
break;
}
if !plain && buf.len() > 6000 {
if !plain && (buf.len() > 5000 || buf.contains(&0x1b)) {
plain = true;
drop(mem::take(&mut before));
}
@ -84,20 +84,6 @@ impl Highlighter {
buf.push(b'\n');
}
let esc_count = buf.iter().filter(|&&b| b == 27).count();
if esc_count > 0 {
plain = true;
drop(mem::take(&mut before));
buf = buf.iter().fold(Vec::with_capacity(buf.len() + esc_count), |mut acc, &b| {
if b == 27 {
acc.extend_from_slice(b"^[");
} else {
acc.push(b);
}
acc
})
}
if i > skip {
after.push(String::from_utf8_lossy(&buf).into_owned());
} else if !plain {
@ -112,7 +98,7 @@ impl Highlighter {
if plain {
let indent = " ".repeat(PREVIEW.tab_size as usize);
Ok(Text::from(after.join("").replace('\t', &indent)))
Ok(Text::from(after.join("").replace('\x1b', "^[").replace('\t', &indent)))
} else {
Self::highlight_with(before, after, syntax.unwrap()).await
}
@ -124,11 +110,10 @@ impl Highlighter {
syntax: &'static SyntaxReference,
) -> Result<Text<'static>, PeekError> {
let ticket = INCR.load(Ordering::Relaxed);
let (theme, syntaxes) = Self::init().await;
tokio::task::spawn_blocking(move || {
let (theme, syntaxes) = Self::init();
let mut h = HighlightLines::new(syntax, theme);
for line in before {
if ticket != INCR.load(Ordering::Relaxed) {
return Err("Highlighting cancelled".into());