You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.1 KiB
Rust
162 lines
5.1 KiB
Rust
use anyhow::Result;
|
|
use rga::adapters::custom::map_exe_error;
|
|
use rga::adapters::*;
|
|
use rga::config::{split_args, RgaConfig};
|
|
use rga::matching::*;
|
|
use rga::print_dur;
|
|
use ripgrep_all as rga;
|
|
use structopt::StructOpt;
|
|
|
|
use schemars::schema_for;
|
|
use std::process::Command;
|
|
use std::time::Instant;
|
|
|
|
fn list_adapters(args: RgaConfig) -> Result<()> {
|
|
let (enabled_adapters, disabled_adapters) = get_all_adapters(args.custom_adapters);
|
|
|
|
println!("Adapters:\n");
|
|
let print = |adapter: std::sync::Arc<dyn FileAdapter>| {
|
|
let meta = adapter.metadata();
|
|
let matchers = meta
|
|
.fast_matchers
|
|
.iter()
|
|
.map(|m| match m {
|
|
FastFileMatcher::FileExtension(ext) => format!(".{ext}"),
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.join(", ");
|
|
let slow_matchers = meta
|
|
.slow_matchers
|
|
.as_ref()
|
|
.unwrap_or(&vec![])
|
|
.iter()
|
|
.filter_map(|m| match m {
|
|
FileMatcher::MimeType(x) => Some(x.to_string()),
|
|
FileMatcher::Fast(_) => None,
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.join(", ");
|
|
let mime_text = if slow_matchers.is_empty() {
|
|
"".to_owned()
|
|
} else {
|
|
format!("Mime Types: {slow_matchers}")
|
|
};
|
|
print!(
|
|
" - **{name}**\n {desc} \n Extensions: {matchers} \n {mime} \n",
|
|
name = meta.name,
|
|
desc = meta.description.replace('\n', "\n "),
|
|
matchers = matchers,
|
|
mime = mime_text
|
|
);
|
|
println!();
|
|
};
|
|
for adapter in enabled_adapters {
|
|
print(adapter)
|
|
}
|
|
println!("The following adapters are disabled by default, and can be enabled using '--rga-adapters=+foo,bar':\n");
|
|
for adapter in disabled_adapters {
|
|
print(adapter)
|
|
}
|
|
Ok(())
|
|
}
|
|
fn main() -> anyhow::Result<()> {
|
|
// set debugging as early as possible
|
|
if std::env::args().any(|e| e == "--debug") {
|
|
std::env::set_var("RUST_LOG", "debug");
|
|
}
|
|
|
|
env_logger::init();
|
|
|
|
let (config, mut passthrough_args) = split_args(false)?;
|
|
|
|
if config.print_config_schema {
|
|
println!("{}", serde_json::to_string_pretty(&schema_for!(RgaConfig))?);
|
|
return Ok(());
|
|
}
|
|
if config.list_adapters {
|
|
return list_adapters(config);
|
|
}
|
|
if let Some(path) = config.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.is_empty() {
|
|
// rg would show help. Show own help instead.
|
|
RgaConfig::clap().print_help()?;
|
|
println!();
|
|
return Ok(());
|
|
}
|
|
|
|
let adapters = get_adapters_filtered(config.custom_adapters.clone(), &config.adapters)?;
|
|
|
|
let pre_glob = if !config.accurate {
|
|
let extensions = adapters
|
|
.iter()
|
|
.flat_map(|a| &a.metadata().fast_matchers)
|
|
.flat_map(|m| match m {
|
|
FastFileMatcher::FileExtension(ext) => vec![ext.clone(), ext.to_ascii_uppercase()],
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.join(",");
|
|
format!("*.{{{extensions}}}")
|
|
} else {
|
|
"*".to_owned()
|
|
};
|
|
|
|
add_exe_to_path()?;
|
|
|
|
let rg_args = vec![
|
|
"--no-line-number",
|
|
// smart case by default because within weird files
|
|
// we probably can't really trust casing anyways
|
|
"--smart-case",
|
|
];
|
|
|
|
let exe = std::env::current_exe().expect("Could not get executable location");
|
|
let preproc_exe = exe.with_file_name("rga-preproc");
|
|
|
|
let before = Instant::now();
|
|
let mut cmd = Command::new("rg");
|
|
cmd.args(rg_args)
|
|
.arg("--pre")
|
|
.arg(preproc_exe)
|
|
.arg("--pre-glob")
|
|
.arg(pre_glob)
|
|
.args(passthrough_args);
|
|
log::debug!("rg command to run: {:?}", cmd);
|
|
let mut child = cmd
|
|
.spawn()
|
|
.map_err(|e| map_exe_error(e, "rg", "Please make sure you have ripgrep installed."))?;
|
|
|
|
let result = child.wait()?;
|
|
|
|
log::debug!("running rg took {}", print_dur(before));
|
|
if !result.success() {
|
|
std::process::exit(result.code().unwrap_or(1));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// add the directory that contains `rga` to PATH, so rga-preproc can find pandoc etc (if we are on Windows where we include dependent binaries)
|
|
fn add_exe_to_path() -> Result<()> {
|
|
use std::env;
|
|
let mut exe = env::current_exe().expect("Could not get executable location");
|
|
// let preproc_exe = exe.with_file_name("rga-preproc");
|
|
exe.pop(); // dirname
|
|
|
|
let path = env::var_os("PATH").unwrap_or_default();
|
|
let paths = env::split_paths(&path).collect::<Vec<_>>();
|
|
// prepend: prefer bundled versions to system-installed versions of binaries
|
|
// solves https://github.com/phiresky/ripgrep-all/issues/32
|
|
// may be somewhat of a security issue if rga binary is in installed in unprivileged locations
|
|
let paths = [&[exe.to_owned(), exe.join("lib")], &paths[..]].concat();
|
|
let new_path = env::join_paths(paths)?;
|
|
env::set_var("PATH", new_path);
|
|
Ok(())
|
|
}
|