2018-08-03 23:26:22 +02:00
|
|
|
extern crate grep;
|
|
|
|
extern crate termcolor;
|
|
|
|
extern crate walkdir;
|
|
|
|
|
|
|
|
use std::env;
|
2018-09-05 17:51:53 +02:00
|
|
|
use std::error::Error;
|
2018-08-03 23:26:22 +02:00
|
|
|
use std::ffi::OsString;
|
|
|
|
use std::process;
|
|
|
|
|
2018-08-30 02:53:52 +02:00
|
|
|
use grep::cli;
|
2018-08-03 23:26:22 +02:00
|
|
|
use grep::printer::{ColorSpecs, StandardBuilder};
|
|
|
|
use grep::regex::RegexMatcher;
|
|
|
|
use grep::searcher::{BinaryDetection, SearcherBuilder};
|
2018-08-30 02:53:52 +02:00
|
|
|
use termcolor::ColorChoice;
|
2018-08-03 23:26:22 +02:00
|
|
|
use walkdir::WalkDir;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
if let Err(err) = try_main() {
|
|
|
|
eprintln!("{}", err);
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-05 17:51:53 +02:00
|
|
|
fn try_main() -> Result<(), Box<Error>> {
|
2018-08-03 23:26:22 +02:00
|
|
|
let mut args: Vec<OsString> = env::args_os().collect();
|
|
|
|
if args.len() < 2 {
|
2018-09-05 17:51:53 +02:00
|
|
|
return Err("Usage: simplegrep <pattern> [<path> ...]".into());
|
2018-08-03 23:26:22 +02:00
|
|
|
}
|
|
|
|
if args.len() == 2 {
|
|
|
|
args.push(OsString::from("./"));
|
|
|
|
}
|
2018-08-30 02:53:52 +02:00
|
|
|
search(cli::pattern_from_os(&args[1])?, &args[2..])
|
2018-08-03 23:26:22 +02:00
|
|
|
}
|
|
|
|
|
2018-09-05 17:51:53 +02:00
|
|
|
fn search(pattern: &str, paths: &[OsString]) -> Result<(), Box<Error>> {
|
2018-08-03 23:26:22 +02:00
|
|
|
let matcher = RegexMatcher::new_line_matcher(&pattern)?;
|
|
|
|
let mut searcher = SearcherBuilder::new()
|
|
|
|
.binary_detection(BinaryDetection::quit(b'\x00'))
|
2018-08-30 02:53:52 +02:00
|
|
|
.line_number(false)
|
2018-08-03 23:26:22 +02:00
|
|
|
.build();
|
|
|
|
let mut printer = StandardBuilder::new()
|
2018-08-30 02:53:52 +02:00
|
|
|
.color_specs(ColorSpecs::default_with_color())
|
2018-09-05 17:51:53 +02:00
|
|
|
.build(cli::stdout(
|
|
|
|
if cli::is_tty_stdout() {
|
|
|
|
ColorChoice::Auto
|
|
|
|
} else {
|
|
|
|
ColorChoice::Never
|
|
|
|
}
|
|
|
|
));
|
2018-08-03 23:26:22 +02:00
|
|
|
|
|
|
|
for path in paths {
|
|
|
|
for result in WalkDir::new(path) {
|
|
|
|
let dent = match result {
|
|
|
|
Ok(dent) => dent,
|
|
|
|
Err(err) => {
|
2018-09-05 17:51:53 +02:00
|
|
|
eprintln!("{}", err);
|
2018-08-03 23:26:22 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if !dent.file_type().is_file() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let result = searcher.search_path(
|
|
|
|
&matcher,
|
|
|
|
dent.path(),
|
|
|
|
printer.sink_with_path(&matcher, dent.path()),
|
|
|
|
);
|
|
|
|
if let Err(err) = result {
|
|
|
|
eprintln!("{}: {}", dent.path().display(), err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|