diff options
author | Andrew Gallant <jamslam@gmail.com> | 2018-08-03 17:26:22 -0400 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2018-08-20 07:10:19 -0400 |
commit | bb110c1ebeeda452046830b3991f705f5759da92 (patch) | |
tree | cc2b0112a3ca9b8d05cf1e953553907d71564082 /grep/examples/simplegrep.rs | |
parent | d9ca5293569efb255608d3c601107bcfe7060f15 (diff) |
ripgrep: migrate to libripgrep
This commit does the work to delete the old `grep` crate and effectively
rewrite most of ripgrep core to use the new libripgrep crates. The new
`grep` crate is now a facade that collects the various crates that make
up libripgrep.
The most complex part of ripgrep core is now arguably the translation
between command line parameters and the library options, which is
ultimately where we want to be.
Diffstat (limited to 'grep/examples/simplegrep.rs')
-rw-r--r-- | grep/examples/simplegrep.rs | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/grep/examples/simplegrep.rs b/grep/examples/simplegrep.rs new file mode 100644 index 00000000..fb2d4001 --- /dev/null +++ b/grep/examples/simplegrep.rs @@ -0,0 +1,107 @@ +extern crate atty; +extern crate grep; +extern crate termcolor; +extern crate walkdir; + +use std::env; +use std::error; +use std::ffi::OsString; +use std::path::Path; +use std::process; +use std::result; + +use grep::printer::{ColorSpecs, StandardBuilder}; +use grep::regex::RegexMatcher; +use grep::searcher::{BinaryDetection, SearcherBuilder}; +use termcolor::{ColorChoice, StandardStream}; +use walkdir::WalkDir; + +macro_rules! fail { + ($($tt:tt)*) => { + return Err(From::from(format!($($tt)*))); + } +} + +type Result<T> = result::Result<T, Box<error::Error>>; + +fn main() { + if let Err(err) = try_main() { + eprintln!("{}", err); + process::exit(1); + } +} + +fn try_main() -> Result<()> { + let mut args: Vec<OsString> = env::args_os().collect(); + if args.len() < 2 { + fail!("Usage: simplegrep <pattern> [<path> ...]"); + } + if args.len() == 2 { + args.push(OsString::from("./")); + } + let pattern = match args[1].clone().into_string() { + Ok(pattern) => pattern, + Err(_) => { + fail!( + "pattern is not valid UTF-8: '{:?}'", + args[1].to_string_lossy() + ); + } + }; + search(&pattern, &args[2..]) +} + +fn search(pattern: &str, paths: &[OsString]) -> Result<()> { + let matcher = RegexMatcher::new_line_matcher(&pattern)?; + let mut searcher = SearcherBuilder::new() + .binary_detection(BinaryDetection::quit(b'\x00')) + .build(); + let mut printer = StandardBuilder::new() + .color_specs(colors()) + .build(StandardStream::stdout(color_choice())); + + for path in paths { + for result in WalkDir::new(path) { + let dent = match result { + Ok(dent) => dent, + Err(err) => { + eprintln!( + "{}: {}", + err.path().unwrap_or(Path::new("error")).display(), + err, + ); + 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(()) +} + +fn color_choice() -> ColorChoice { + if atty::is(atty::Stream::Stdout) { + ColorChoice::Auto + } else { + ColorChoice::Never + } +} + +fn colors() -> ColorSpecs { + ColorSpecs::new(&[ + "path:fg:magenta".parse().unwrap(), + "line:fg:green".parse().unwrap(), + "match:fg:red".parse().unwrap(), + "match:style:bold".parse().unwrap(), + ]) +} |