From 04501c6aa973893b4edb619744a72e53cdfc54d2 Mon Sep 17 00:00:00 2001 From: Jed Date: Mon, 15 Jun 2026 22:06:28 +0200 Subject: [PATCH] feat: pass highlight position from code.lua to highlight.rs module --- yazi-core/src/highlighter.rs | 45 ++++++++++++++++++++--------- yazi-core/src/tab/preview.rs | 2 -- yazi-plugin/preset/plugins/code.lua | 19 ++++++------ yazi-plugin/src/utils/preview.rs | 10 ++----- 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/yazi-core/src/highlighter.rs b/yazi-core/src/highlighter.rs index 99f2bd83..0082e4d9 100644 --- a/yazi-core/src/highlighter.rs +++ b/yazi-core/src/highlighter.rs @@ -1,20 +1,20 @@ -use std::{ - io::{BufRead, BufReader, Cursor, Seek}, - path::PathBuf, - sync::OnceLock, -}; - use anyhow::{Result, anyhow, bail}; use ratatui::{ layout::Size, text::{Line, Span, Text}, }; +use std::{ + io::{BufRead, BufReader, Cursor, Seek}, + path::PathBuf, + sync::OnceLock, +}; use syntect::{ LoadingError, dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}, }; +use yazi_binding::elements::HighlightPosition; use yazi_config::{THEME, YAZI}; use yazi_runner::previewer::PeekError; use yazi_shared::{Id, Ids, replace_to_printable}; @@ -37,12 +37,17 @@ pub struct Highlighter { } impl Highlighter { - pub async fn oneshot

(path: P, skip: usize, size: Size) -> Result, PeekError> + pub async fn oneshot

( + path: P, + skip: usize, + size: Size, + position: Option, + ) -> Result, PeekError> where P: Into, { let path = path.into(); - tokio::task::spawn_blocking(move || Self::make(path, skip, size)?.highlight()).await? + tokio::task::spawn_blocking(move || Self::make(path, skip, size)?.highlight(position)).await? } fn make

(path: P, skip: usize, size: Size) -> Result @@ -75,7 +80,7 @@ impl Highlighter { INCR.next(); } - fn highlight(mut self) -> Result, PeekError> { + fn highlight(mut self, position: Option) -> Result, PeekError> { self.load_syntax()?; let mut plain = self.syntax.is_none(); @@ -84,7 +89,6 @@ impl Highlighter { let mut lines = Vec::with_capacity(self.size.height as usize); let mut inspected = 0u16; while self.reader.read_until(b'\n', &mut buf).is_ok_and(|n| n > 0) { - // tracing::debug!("{:?}", buf); if Self::is_binary(&buf, &mut inspected) { Err(anyhow!("Binary file"))?; } @@ -95,9 +99,9 @@ impl Highlighter { } self.ensure_not_cancelled()?; - if plain && !self.process_plain(&buf, &mut i, &mut lines)? { + if plain && !self.process_plain(&buf, &mut i, &position, &mut lines)? { break; - } else if !plain && !self.process_hyper(&buf, &mut i, &mut lines)? { + } else if !plain && !self.process_hyper(&buf, &mut i, &position, &mut lines)? { break; } buf.clear(); @@ -110,7 +114,13 @@ impl Highlighter { Ok(Text::from(lines)) } - fn process_plain(&mut self, buf: &[u8], i: &mut usize, lines: &mut Vec) -> Result { + fn process_plain( + &mut self, + buf: &[u8], + i: &mut usize, + position: &Option, + lines: &mut Vec, + ) -> Result { let b = replace_to_printable(buf, true, YAZI.preview.tab_size, false); let s = String::from_utf8_lossy(&b); @@ -131,11 +141,18 @@ impl Highlighter { Ok(true) } - fn process_hyper(&mut self, buf: &[u8], i: &mut usize, lines: &mut Vec) -> Result { + fn process_hyper( + &mut self, + buf: &[u8], + i: &mut usize, + position: &Option, + lines: &mut Vec, + ) -> Result { let Some(syntax) = self.syntax else { bail!("No syntax") }; let h = self.inner.get_or_insert_with(|| HighlightLines::new(syntax, self.theme)); let s = String::from_utf8_lossy(buf); + tracing::debug!("s {:?}", s); let line = [Self::to_line_widget(h.highlight_line(&s, self.syntaxes)?)]; let mut it = LineIter::parsed(&line, YAZI.preview.tab_size); diff --git a/yazi-core/src/tab/preview.rs b/yazi-core/src/tab/preview.rs index d1f9f4fe..ce182153 100644 --- a/yazi-core/src/tab/preview.rs +++ b/yazi-core/src/tab/preview.rs @@ -45,8 +45,6 @@ impl Preview { let job = PeekJob { previewer, file, mime, skip: self.skip, search_idx: self.search_idx }; - tracing::debug!("preview before to peek {:?}", self.search_idx); - self.handle = Some(tokio::spawn(async move { let mut rx = RUNNER.peek(&job).await; match rx.recv().await.unwrap_or(Err(PeekError::Cancelled)) { diff --git a/yazi-plugin/preset/plugins/code.lua b/yazi-plugin/preset/plugins/code.lua index 6ad206ee..d366718e 100644 --- a/yazi-plugin/preset/plugins/code.lua +++ b/yazi-plugin/preset/plugins/code.lua @@ -4,7 +4,8 @@ local function get_search_occurrences(url) if not url.is_search then return end - local occurrences = tostring(url):match("^search://(.-)//") + -- Shoud we encode ~ too? + local subject_len, occurrences = tostring(url):match("^search://([^~]+)~(.-)//") local lines = {} for occurrence in occurrences:gmatch("[^,]+") do local line, col = occurrence:match("(%d+)-(%d+)") @@ -15,7 +16,7 @@ local function get_search_occurrences(url) return end - return lines + return tonumber(subject_len), lines end local function get_next_occurrence_idx(search_idx, direction, occurrences_len) @@ -37,18 +38,19 @@ local function get_next_occurrence_idx(search_idx, direction, occurrences_len) end function M:peek(job) - local search_occurrences = get_search_occurrences(job.file.url) + local subject_len, search_occurrences = get_search_occurrences(job.file.url) local search_idx = job.search_idx - ya.dbg("code.lua: search_occurrences:", search_occurrences) - local occurrence if search_occurrences and search_idx then occurrence = search_occurrences[search_idx] + job.position = { + line = occurrence[1], + col = occurrence[2], + length = subject_len, + } end - ya.dbg("code.lua: Occurrence:", occurrence) - -- Todo: Pass the occurrence for highlighting local err, bound = ya.preview_code(job) if bound then ya.emit("peek", { bound, only_if = job.file.url, upper_bound = true }) @@ -61,14 +63,13 @@ function M:seek(job) local direction = job.units > 0 and "down" or "up" local search_idx = cx.active.preview.search_idx - ya.dbg("search index before to set it in seek", search_idx) local h = cx.active.current.hovered if not h or h.url ~= job.file.url then return end - local search_occurrences = get_search_occurrences(job.file.url) + local _, search_occurrences = get_search_occurrences(job.file.url) if search_occurrences then local next_occurrence_idx = get_next_occurrence_idx(search_idx, direction, #search_occurrences) local occurrence = search_occurrences[next_occurrence_idx] diff --git a/yazi-plugin/src/utils/preview.rs b/yazi-plugin/src/utils/preview.rs index 4cf50b2c..70a9ae19 100644 --- a/yazi-plugin/src/utils/preview.rs +++ b/yazi-plugin/src/utils/preview.rs @@ -7,7 +7,7 @@ use yazi_binding::{ use yazi_core::{Highlighter, MgrProxy, tab::PreviewLock}; use yazi_fs::FsUrl; use yazi_runner::previewer::PeekError; -use yazi_shared::url::AsUrl; +use yazi_shared::url::{AsUrl, UrlLike}; use super::Utils; @@ -20,16 +20,10 @@ impl Utils { let area: Area = t.raw_get("area")?; let position: Option = t.raw_get("position").ok(); - tracing::debug!("{:?}", position); - let mut lock = PreviewLock::try_from(t)?; let path = lock.url.as_url().unified_path(); - let search_subject = lock.url.as_url().scheme().domain(); - - tracing::debug!("search subject{:?}", search_subject); - - let inner = match Highlighter::oneshot(path, lock.skip, area.size()).await { + let inner = match Highlighter::oneshot(path, lock.skip, area.size(), position).await { Ok(text) => { // tracing::debug!("{:?}", text); text