add experimental rga-fzf binary

This commit is contained in:
phiresky 2020-06-08 14:00:18 +02:00
parent 38185dda21
commit 0001feb24b
3 changed files with 90 additions and 1 deletions

View File

@ -147,6 +147,12 @@ pub struct RgaArgs {
)]
pub max_archive_recursion: i32,
#[serde(skip)]
#[structopt(long = "--rga-fzf-path", require_equals = true, hidden = true)]
/// same as passing path directly, except if argument is empty
/// kinda hacky, but if no file is found, fzf calls rga with empty string as path, which causes No such file or directory from rg. So filter those cases and return specially
pub fzf_path: Option<String>,
// these arguments stop the process, so don't serialize them
#[serde(skip)]
#[structopt(long = "--rga-list-adapters", help = "List all known adapters")]

75
src/bin/rga-fzf.rs Normal file
View File

@ -0,0 +1,75 @@
use anyhow::Context;
use rga::adapters::spawning::map_exe_error;
use ripgrep_all as rga;
use std::process::{Command, Stdio};
fn main() -> anyhow::Result<()> {
env_logger::init();
let mut passthrough_args: Vec<String> = std::env::args().skip(1).collect();
let inx = passthrough_args.iter().position(|e| !e.starts_with("-"));
let initial_query = if let Some(inx) = inx {
passthrough_args.remove(inx)
} else {
"".to_string()
};
let exe = std::env::current_exe().context("Could not get executable location")?;
let preproc_exe = exe.with_file_name("rga");
let preproc_exe = preproc_exe
.to_str()
.context("rga executable is in non-unicode path")?;
let rg_prefix = format!(
"{} --files-with-matches --rga-cache-max-blob-len=10M",
preproc_exe
);
let child = Command::new("fzf")
.arg(format!(
"--preview={} --pretty --context 5 {{q}} --rga-fzf-path=_{{}}",
preproc_exe
))
.arg("--phony")
.arg("--query")
.arg(&initial_query)
.arg("--print-query")
.arg(format!("--bind=change:reload: {} {{q}}", rg_prefix))
.env(
"FZF_DEFAULT_COMMAND",
format!("{} '{}'", rg_prefix, &initial_query),
)
.stdout(Stdio::piped())
.spawn()
.map_err(|e| map_exe_error(e, "fzf", "Please make sure you have fzf installed."))?;
let output = child.wait_with_output()?;
let mut x = output.stdout.split(|e| e == &b'\n');
let final_query =
std::str::from_utf8(x.next().context("fzf output empty")?).context("fzf query not utf8")?;
let selected_file = std::str::from_utf8(x.next().context("fzf output not two line")?)
.context("fzf ofilename not utf8")?;
println!("query='{}', file='{}'", final_query, selected_file);
if selected_file.ends_with(".pdf") {
use std::io::ErrorKind::*;
let worked = Command::new("evince")
.arg("--find")
.arg(final_query)
.arg(selected_file)
.spawn()
.map_or_else(
|err| match err.kind() {
NotFound => Ok(false),
_ => Err(err),
},
|_| Ok(true),
)?;
if worked {
return Ok(());
}
}
Command::new("xdg-open").arg(selected_file).spawn()?;
Ok(())
}

View File

@ -12,7 +12,7 @@ use std::process::Command;
fn main() -> anyhow::Result<()> {
env_logger::init();
let (args, passthrough_args) = split_args()?;
let (args, mut passthrough_args) = split_args()?;
if args.list_adapters {
let (enabled_adapters, disabled_adapters) = get_all_adapters();
@ -62,6 +62,14 @@ fn main() -> anyhow::Result<()> {
}
return Ok(());
}
if let Some(path) = args.fzf_path {
if path == "_" {
// fzf found no result, ignore everything and return
println!("[no file found]");
return Ok(());
}
passthrough_args.push(std::ffi::OsString::from(&path[1..]));
}
if passthrough_args.len() == 0 {
// rg would show help. Show own help instead.