feat: wip improve rg generated url to get all files occurences

This commit is contained in:
Jed 2026-06-04 19:49:37 +02:00
parent d9cd1907d9
commit c1f4fb5c3b

View file

@ -1,21 +1,26 @@
use std::{path::Path, process::Stdio};
use std::process::Stdio;
use anyhow::Result;
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}};
use tokio::{
io::{AsyncBufReadExt, BufReader},
process::Command,
sync::mpsc::{self, UnboundedReceiver},
};
use yazi_fs::{File, FsUrl};
use yazi_shared::url::{AsUrl, UrlBuf, UrlLike};
use yazi_vfs::VfsFile;
pub struct RgOpt {
pub cwd: UrlBuf,
pub hidden: bool,
pub cwd: UrlBuf,
pub hidden: bool,
pub subject: String,
pub args: Vec<String>,
pub args: Vec<String>,
}
pub fn rg(opt: RgOpt) -> Result<UnboundedReceiver<File>> {
let mut child = Command::new("rg")
.args(["--color=never", "--files-with-matches", "--smart-case"])
.args(["--color=never", "--no-heading", "--column", "--smart-case"])
// .args(["--color=never", "--files-with-matches", "--smart-case"])
.arg(if opt.hidden { "--hidden" } else { "--no-hidden" })
.args(opt.args)
.arg(opt.subject)
@ -29,18 +34,61 @@ pub fn rg(opt: RgOpt) -> Result<UnboundedReceiver<File>> {
let (tx, rx) = mpsc::unbounded_channel();
tokio::spawn(async move {
while let Ok(Some(line)) = it.next_line().await {
if Path::new(&line).is_absolute() {
continue;
// let mut occurrences_per_file: HashMap<String, Vec<(u32, u32)>> = HashMap::new();
// let mut current_file_path: String = String::new();
let mut current_file: String = String::new();
let mut current_occurrences: Vec<(u32, u32)> = vec![];
while let Ok(Some(search_line)) = it.next_line().await {
let Some((file_path, line, col)) = parse_rg_line(&search_line) else { continue };
if current_file != file_path {
let Some(url) = build_file_url(opt.cwd.clone(), &current_file, &current_occurrences) else {
continue;
};
if let Ok(file) = File::new(url).await {
tx.send(file).ok();
}
current_file = file_path.clone();
current_occurrences = vec![];
}
let Ok(url) = opt.cwd.try_join(line) else {
continue;
};
if let Ok(file) = File::new(url).await {
tx.send(file).ok();
current_occurrences.push((line as u32, col as u32));
}
if current_occurrences.len() > 0 {
match build_file_url(opt.cwd, &current_file, &current_occurrences) {
Some(url) => {
if let Ok(file) = File::new(url).await {
tx.send(file).ok();
}
}
None => {}
}
}
child.wait().await.ok();
});
Ok(rx)
}
fn build_file_url(cwd: UrlBuf, file_path: &str, occurences: &Vec<(u32, u32)>) -> Option<UrlBuf> {
let occurrences_str =
occurences.iter().map(|(line, col)| format!("{line}-{col}")).collect::<Vec<_>>().join(",");
let url = cwd.try_join(file_path).ok().and_then(|u| u.into_search(occurrences_str).ok());
url
}
fn parse_rg_line(line: &str) -> Option<(String, usize, usize)> {
let mut parts = line.split(':');
let (file, line, col) = (parts.next()?, parts.next()?, parts.next()?);
if file.is_empty() {
return None;
}
Some((file.to_owned(), line.parse().ok()?, col.parse().ok()?))
}