mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: add fd, rg external tools
This commit is contained in:
parent
fd0966de3f
commit
a72acf6fd3
7 changed files with 124 additions and 7 deletions
14
README.md
14
README.md
|
|
@ -10,8 +10,8 @@ Before getting started, ensure that the following dependencies are installed on
|
||||||
|
|
||||||
- jq (optional, for JSON preview)
|
- jq (optional, for JSON preview)
|
||||||
- ffmpegthumbnailer (optional, for video thumbnails)
|
- ffmpegthumbnailer (optional, for video thumbnails)
|
||||||
- fzf (optional, for fuzzy search)
|
- fd (optional, for file searching)
|
||||||
- rg (optional, for fuzzy search)
|
- rg (optional, for content searching)
|
||||||
- zoxide (optional, for directory jumping)
|
- zoxide (optional, for directory jumping)
|
||||||
|
|
||||||
Execute the following commands to clone the project and build Yazi:
|
Execute the following commands to clone the project and build Yazi:
|
||||||
|
|
@ -30,11 +30,11 @@ cargo build --release
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- Add example config for general usage, currently please see my [another repo](https://github.com/sxyazi/dotfiles/tree/main/yazi) instead
|
- [ ] Add example config for general usage, currently please see my [another repo](https://github.com/sxyazi/dotfiles/tree/main/yazi) instead
|
||||||
- Integration with zoxide for fast directory navigation
|
- [ ] Integration with zoxide for fast directory navigation
|
||||||
- Integration with fzf, rg for fuzzy file searching
|
- [ ] Integration with fd, rg for fuzzy file searching
|
||||||
- Support for Überzug++ for image previews with X11/wayland environment
|
- [ ] Support for Überzug++ for image previews with X11/wayland environment
|
||||||
- Batch renaming support
|
- [ ] Batch renaming support
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
38
src/core/external/fd.rs
vendored
Normal file
38
src/core/external/fd.rs
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
use std::{path::PathBuf, process::Stdio, time::Duration};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::UnboundedReceiver, task::JoinHandle};
|
||||||
|
|
||||||
|
use crate::misc::DelayedBuffer;
|
||||||
|
|
||||||
|
pub struct FdOpt {
|
||||||
|
pub cwd: PathBuf,
|
||||||
|
pub hidden: bool,
|
||||||
|
pub regex: bool,
|
||||||
|
pub subject: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fd(opt: FdOpt) -> Result<(JoinHandle<()>, UnboundedReceiver<Vec<String>>)> {
|
||||||
|
let mut child = Command::new("fd")
|
||||||
|
.arg("--base-directory")
|
||||||
|
.arg(&opt.cwd)
|
||||||
|
.arg(if opt.hidden { "--hidden" } else { "--no-hidden" })
|
||||||
|
.arg(if opt.regex { "--regex" } else { "--glob" })
|
||||||
|
.arg(&opt.subject)
|
||||||
|
.kill_on_drop(true)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()?;
|
||||||
|
|
||||||
|
drop(child.stderr.take());
|
||||||
|
|
||||||
|
let mut it = BufReader::new(child.stdout.take().unwrap()).lines();
|
||||||
|
let (mut buf, rx) = DelayedBuffer::new(Duration::from_millis(100));
|
||||||
|
|
||||||
|
let handle = tokio::spawn(async move {
|
||||||
|
while let Ok(Some(line)) = it.next_line().await {
|
||||||
|
buf.push(line);
|
||||||
|
}
|
||||||
|
child.wait().await.ok();
|
||||||
|
});
|
||||||
|
Ok((handle, rx))
|
||||||
|
}
|
||||||
5
src/core/external/mod.rs
vendored
Normal file
5
src/core/external/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
mod fd;
|
||||||
|
mod rg;
|
||||||
|
|
||||||
|
pub use fd::*;
|
||||||
|
pub use rg::*;
|
||||||
36
src/core/external/rg.rs
vendored
Normal file
36
src/core/external/rg.rs
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
use std::{path::PathBuf, process::Stdio, time::Duration};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::UnboundedReceiver, task::JoinHandle};
|
||||||
|
|
||||||
|
use crate::misc::DelayedBuffer;
|
||||||
|
|
||||||
|
pub struct RgOpt {
|
||||||
|
pub cwd: PathBuf,
|
||||||
|
pub hidden: bool,
|
||||||
|
pub subject: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn rg(opt: RgOpt) -> Result<(JoinHandle<()>, UnboundedReceiver<Vec<String>>)> {
|
||||||
|
let mut child = Command::new("rg")
|
||||||
|
.current_dir(&opt.cwd)
|
||||||
|
.args(&["--color=never", "--files-with-matches", "--smart-case"])
|
||||||
|
.arg(if opt.hidden { "--hidden" } else { "--no-hidden" })
|
||||||
|
.arg(&opt.subject)
|
||||||
|
.kill_on_drop(true)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()?;
|
||||||
|
|
||||||
|
drop(child.stderr.take());
|
||||||
|
|
||||||
|
let mut it = BufReader::new(child.stdout.take().unwrap()).lines();
|
||||||
|
let (mut buf, rx) = DelayedBuffer::new(Duration::from_millis(100));
|
||||||
|
|
||||||
|
let handle = tokio::spawn(async move {
|
||||||
|
while let Ok(Some(line)) = it.next_line().await {
|
||||||
|
buf.push(line);
|
||||||
|
}
|
||||||
|
child.wait().await.ok();
|
||||||
|
});
|
||||||
|
Ok((handle, rx))
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
mod adapter;
|
mod adapter;
|
||||||
mod event;
|
mod event;
|
||||||
|
pub mod external;
|
||||||
mod input;
|
mod input;
|
||||||
mod manager;
|
mod manager;
|
||||||
mod tasks;
|
mod tasks;
|
||||||
|
|
|
||||||
35
src/misc/buffer.rs
Normal file
35
src/misc/buffer.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use tokio::{sync::mpsc::{self, UnboundedReceiver, UnboundedSender}, time::Instant};
|
||||||
|
|
||||||
|
pub struct DelayedBuffer<T> {
|
||||||
|
buf: Vec<T>,
|
||||||
|
tx: UnboundedSender<Vec<T>>,
|
||||||
|
last: Instant,
|
||||||
|
interval: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> DelayedBuffer<T> {
|
||||||
|
pub fn new(interval: Duration) -> (Self, UnboundedReceiver<Vec<T>>) {
|
||||||
|
let (tx, rx) = mpsc::unbounded_channel();
|
||||||
|
(Self { buf: Vec::new(), tx, last: Instant::now() - interval, interval }, rx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, item: T) {
|
||||||
|
self.buf.push(item);
|
||||||
|
if self.last.elapsed() >= self.interval {
|
||||||
|
self.last = Instant::now();
|
||||||
|
self.tx.send(self.buf.drain(..).collect()).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush(&mut self) {
|
||||||
|
if !self.buf.is_empty() {
|
||||||
|
self.tx.send(self.buf.drain(..).collect()).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Drop for DelayedBuffer<T> {
|
||||||
|
fn drop(&mut self) { self.flush(); }
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
|
mod buffer;
|
||||||
mod chars;
|
mod chars;
|
||||||
mod defer;
|
mod defer;
|
||||||
mod fns;
|
mod fns;
|
||||||
|
|
||||||
|
pub use buffer::*;
|
||||||
pub use chars::*;
|
pub use chars::*;
|
||||||
pub use defer::*;
|
pub use defer::*;
|
||||||
pub use fns::*;
|
pub use fns::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue