summaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs105
1 files changed, 66 insertions, 39 deletions
diff --git a/src/main.rs b/src/main.rs
index 999b6d98..4d90cae7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,15 +4,21 @@ extern crate docopt;
extern crate grep;
extern crate memchr;
extern crate memmap;
+extern crate num_cpus;
extern crate regex;
extern crate regex_syntax as syntax;
extern crate rustc_serialize;
+extern crate walkdir;
const USAGE: &'static str = "
-Usage: rep [options] <pattern> [<file> ...]
+Usage: xrep [options] <pattern> <path> ...
+
+xrep is like the silver searcher, but faster than it and grep.
+
+At least one path is required. Searching stdin isn't yet supported.
Options:
- -c, --count Suppress normal output and show count of matches.
+ -c, --count Suppress normal output and show count of line matches.
";
use std::error::Error;
@@ -21,22 +27,37 @@ use std::process;
use std::result;
use docopt::Docopt;
+use grep::Grep;
+use walkdir::{WalkDir, WalkDirIterator};
+
+macro_rules! errored {
+ ($($tt:tt)*) => {
+ return Err(From::from(format!($($tt)*)));
+ }
+}
-use grep::{Grep, GrepBuilder};
+macro_rules! eprintln {
+ ($($tt:tt)*) => {{
+ use std::io::Write;
+ let _ = writeln!(&mut ::std::io::stderr(), $($tt)*);
+ }}
+}
+
+mod glob;
pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;
#[derive(RustcDecodable)]
struct Args {
arg_pattern: String,
- arg_file: Vec<String>,
+ arg_path: Vec<String>,
flag_count: bool,
}
fn main() {
- let args = Docopt::new(USAGE).and_then(|d| d.decode())
- .unwrap_or_else(|e| e.exit());
- match run(&args) {
+ let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
+ .unwrap_or_else(|e| e.exit());
+ match args.run() {
Ok(count) if count == 0 => process::exit(1),
Ok(_) => process::exit(0),
Err(err) => {
@@ -46,42 +67,48 @@ fn main() {
}
}
-fn run(args: &Args) -> Result<u64> {
- if args.arg_file.is_empty() {
- unimplemented!()
- } else {
- let searcher = try!(GrepBuilder::new(&args.arg_pattern).create());
- if args.flag_count {
- run_mmap_count_only(args, &searcher)
- } else {
- run_mmap(args, &searcher)
+impl Args {
+ fn run(&self) -> Result<u64> {
+ if self.arg_path.is_empty() {
+ return errored!("Searching stdin is not currently supported.");
+ }
+ for p in &self.arg_path {
+ let mut it = WalkDir::new(p).into_iter();
+ loop {
+ let ent = match it.next() {
+ None => break,
+ Some(Err(err)) => {
+ eprintln!("{}", err);
+ continue;
+ }
+ Some(Ok(ent)) => ent,
+ };
+ if is_hidden(&ent) {
+ if ent.file_type().is_dir() {
+ it.skip_current_dir();
+ }
+ continue;
+ }
+ println!("{}", ent.path().display());
+ }
}
+ Ok(0)
}
-}
-fn run_mmap(args: &Args, searcher: &Grep) -> Result<u64> {
- unimplemented!()
- /*
- for m in searcher.iter(text) {
- if !args.flag_count {
- try!(wtr.write(&text[m.start()..m.end()]));
- try!(wtr.write(b"\n"));
- }
- count += 1;
+ fn run_mmap_count_only(&self, searcher: &Grep) -> Result<u64> {
+ use memmap::{Mmap, Protection};
+
+ assert!(self.arg_path.len() == 1);
+ let mut wtr = io::BufWriter::new(io::stdout());
+ let mmap = try!(Mmap::open_path(&self.arg_path[0], Protection::Read));
+ let text = unsafe { mmap.as_slice() };
+ let count = searcher.iter(text).count() as u64;
+ try!(writeln!(wtr, "{}", count));
+ Ok(count)
}
- Ok(count)
- */
}
-#[inline(never)]
-fn run_mmap_count_only(args: &Args, searcher: &Grep) -> Result<u64> {
- use memmap::{Mmap, Protection};
-
- assert!(args.arg_file.len() == 1);
- let mut wtr = io::BufWriter::new(io::stdout());
- let mmap = try!(Mmap::open_path(&args.arg_file[0], Protection::Read));
- let text = unsafe { mmap.as_slice() };
- let count = searcher.iter(text).count() as u64;
- try!(writeln!(wtr, "{}", count));
- Ok(count)
+fn is_hidden(ent: &walkdir::DirEntry) -> bool {
+ ent.depth() > 0 &&
+ ent.file_name().to_str().map(|s| s.starts_with(".")).unwrap_or(false)
}