1 use failure::Fallible;
2 use log::*;
3 use rga::adapters::spawning::map_exe_error;
4 use rga::adapters::*;
5 use rga::args::*;
6 use rga::matching::*;
7 use ripgrep_all as rga;
8 use structopt::StructOpt;
9
10 use std::process::Command;
11
main() -> Result<(), exitfailure::ExitFailure>12 fn main() -> Result<(), exitfailure::ExitFailure> {
13 env_logger::init();
14
15 let (args, passthrough_args) = split_args()?;
16
17 if args.list_adapters {
18 let (enabled_adapters, disabled_adapters) = get_all_adapters();
19
20 println!("Adapters:\n");
21 let print = |adapter: std::rc::Rc<dyn FileAdapter>| {
22 let meta = adapter.metadata();
23 let matchers = meta
24 .fast_matchers
25 .iter()
26 .map(|m| match m {
27 FastMatcher::FileExtension(ext) => format!(".{}", ext),
28 })
29 .collect::<Vec<_>>()
30 .join(", ");
31 let slow_matchers = meta
32 .slow_matchers
33 .as_ref()
34 .unwrap_or(&vec![])
35 .iter()
36 .filter_map(|m| match m {
37 SlowMatcher::MimeType(x) => Some(format!("{}", x)),
38 SlowMatcher::Fast(_) => None,
39 })
40 .collect::<Vec<_>>()
41 .join(", ");
42 let mime_text = if slow_matchers.is_empty() {
43 "".to_owned()
44 } else {
45 format!("Mime Types: {}", slow_matchers)
46 };
47 print!(
48 " - {name}\n {desc}\n Extensions: {matchers}\n {mime}\n",
49 name = meta.name,
50 desc = meta.description,
51 matchers = matchers,
52 mime = mime_text
53 );
54 println!("");
55 };
56 for adapter in enabled_adapters {
57 print(adapter)
58 }
59 println!("The following adapters are disabled by default, and can be enabled using '--rga-adapters=+pdfpages,tesseract':\n");
60 for adapter in disabled_adapters {
61 print(adapter)
62 }
63 return Ok(());
64 }
65
66 if passthrough_args.len() == 0 {
67 // rg would show help. Show own help instead.
68 RgaArgs::clap().print_help()?;
69 println!("");
70 return Ok(());
71 }
72
73 let adapters = get_adapters_filtered(&args.adapters)?;
74
75 let pre_glob = if !args.accurate {
76 let extensions = adapters
77 .iter()
78 .flat_map(|a| &a.metadata().fast_matchers)
79 .flat_map(|m| match m {
80 FastMatcher::FileExtension(ext) => vec![ext.clone(), ext.to_ascii_uppercase()],
81 })
82 .collect::<Vec<_>>()
83 .join(",");
84 format!("*.{{{}}}", extensions)
85 } else {
86 "*".to_owned()
87 };
88
89 add_exe_to_path()?;
90
91 let rg_args = vec![
92 "--no-line-number",
93 // smart case by default because within weird files
94 // we probably can't really trust casing anyways
95 "--smart-case",
96 ];
97
98 let exe = std::env::current_exe().expect("Could not get executable location");
99 let preproc_exe = exe.with_file_name("rga-preproc");
100
101 let mut child = Command::new("rg")
102 .args(rg_args)
103 .arg("--pre")
104 .arg(preproc_exe)
105 .arg("--pre-glob")
106 .arg(pre_glob)
107 .args(passthrough_args)
108 .spawn()
109 .map_err(|e| map_exe_error(e, "rg", "Please make sure you have ripgrep installed."))?;
110
111 child.wait()?;
112 Ok(())
113 }
114
115 /// 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)
add_exe_to_path() -> Fallible<()>116 fn add_exe_to_path() -> Fallible<()> {
117 use std::env;
118 let mut exe = env::current_exe().expect("Could not get executable location");
119 // let preproc_exe = exe.with_file_name("rga-preproc");
120 exe.pop(); // dirname
121
122 let path = env::var_os("PATH").unwrap_or("".into());
123 let paths = env::split_paths(&path).collect::<Vec<_>>();
124 // prepend: prefer bundled versions to system-installed versions of binaries
125 // solves https://github.com/phiresky/ripgrep-all/issues/32
126 // may be somewhat of a security issue if rga binary is in installed in unprivileged locations
127 let paths = [&[exe.to_owned(), exe.join("lib")], &paths[..]].concat();
128 let new_path = env::join_paths(paths)?;
129 env::set_var("PATH", &new_path);
130 Ok(())
131 }
132