mirror of
https://github.com/sxyazi/yazi.git
synced 2024-12-25 17:54:57 +03:00
feat: add fd, rg external tools
This commit is contained in:
parent
fd0966de3f
commit
a72acf6fd3
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)
|
||||
- ffmpegthumbnailer (optional, for video thumbnails)
|
||||
- fzf (optional, for fuzzy search)
|
||||
- rg (optional, for fuzzy search)
|
||||
- fd (optional, for file searching)
|
||||
- rg (optional, for content searching)
|
||||
- zoxide (optional, for directory jumping)
|
||||
|
||||
Execute the following commands to clone the project and build Yazi:
|
||||
@ -30,11 +30,11 @@ cargo build --release
|
||||
|
||||
## TODO
|
||||
|
||||
- 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 fzf, rg for fuzzy file searching
|
||||
- Support for Überzug++ for image previews with X11/wayland environment
|
||||
- Batch renaming support
|
||||
- [ ] 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 fd, rg for fuzzy file searching
|
||||
- [ ] Support for Überzug++ for image previews with X11/wayland environment
|
||||
- [ ] Batch renaming support
|
||||
|
||||
## 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 event;
|
||||
pub mod external;
|
||||
mod input;
|
||||
mod manager;
|
||||
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 defer;
|
||||
mod fns;
|
||||
|
||||
pub use buffer::*;
|
||||
pub use chars::*;
|
||||
pub use defer::*;
|
||||
pub use fns::*;
|
||||
|
Loading…
Reference in New Issue
Block a user