diff --git a/Cargo.lock b/Cargo.lock index fcb2662..7e4e9ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = "0.3.0" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -22,11 +22,48 @@ name = "ansi_term" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fnv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "getopts" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "globset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ignore" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "isatty" version = "0.1.3" @@ -46,11 +83,21 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lazy_static" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "log" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" version = "1.0.1" @@ -144,10 +191,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" +"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" +"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" +"checksum globset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "feeb1b6840809ef5efcf7a4a990bc4e1b7ee3df8cf9e2379a75aeb2ba42ac9c3" +"checksum ignore 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9bda0eaa44a060e21581315efb449e7fabceb93cf38c8376dd1b7e0623e07844" "checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" +"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" diff --git a/Cargo.toml b/Cargo.toml index 66ff949..a2d7289 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,4 @@ ansi_term = "0.9" getopts = "0.2" isatty = "0.1" regex = "0.2" -walkdir = "1" +ignore = "0.2" diff --git a/src/main.rs b/src/main.rs index 4222eec..28bc685 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ extern crate ansi_term; extern crate getopts; extern crate isatty; extern crate regex; -extern crate walkdir; +extern crate ignore; use std::collections::HashMap; use std::env; @@ -17,7 +17,7 @@ use ansi_term::{Style, Colour}; use getopts::Options; use isatty::stdout_isatty; use regex::{Regex, RegexBuilder}; -use walkdir::{WalkDir, DirEntry, WalkDirIterator}; +use ignore::WalkBuilder; /// Maps file extensions to ANSI colors / styles. type ExtensionStyles = HashMap; @@ -26,16 +26,14 @@ type ExtensionStyles = HashMap; struct FdOptions { case_sensitive: bool, search_full_path: bool, - search_hidden: bool, + ignore_hidden: bool, + read_ignore: bool, follow_links: bool, + max_depth: Option, colored: bool, - max_depth: usize, extension_styles: Option } -/// The default maximum recursion depth. -const MAX_DEPTH_DEFAULT : usize = 25; - /// Print a search result to the console. fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) { let path_full = path_root.join(path_entry); @@ -91,24 +89,20 @@ fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) { } } -/// Check if filename of entry starts with a dot. -fn is_hidden(entry: &DirEntry) -> bool { - entry.file_name() - .to_str() - .map(|s| s.starts_with(".")) - .unwrap_or(false) -} - /// Recursively scan the given root path and search for files / pathnames /// matching the pattern. fn scan(root: &Path, pattern: &Regex, config: &FdOptions) { - let walker = WalkDir::new(root) + let walker = WalkBuilder::new(root) + .hidden(config.ignore_hidden) + .ignore(config.read_ignore) + .git_ignore(config.read_ignore) + .parents(config.read_ignore) + .git_global(config.read_ignore) + .git_exclude(config.read_ignore) .follow_links(config.follow_links) .max_depth(config.max_depth) + .build() .into_iter() - .filter_entry(|e| config.search_hidden - || !is_hidden(e) - || e.path() == root) .filter_map(|e| e.ok()) .filter(|e| e.path() != root); @@ -206,15 +200,15 @@ fn main() { opts.optflag("p", "full-path", "search full path (default: filename only)"); opts.optflag("H", "hidden", - "search hidden files/directories (default: off)"); + "search hidden files/directories"); + opts.optflag("I", "no-ignore", + "do not respect .(git)ignore files"); opts.optflag("f", "follow", - "follow symlinks (default: off)"); + "follow symlinks"); opts.optflag("n", "no-color", - "do not colorize output (default: on)"); + "do not colorize output"); opts.optopt( "d", "max-depth", - format!("maximum search depth (default: {})", - MAX_DEPTH_DEFAULT).as_str(), - "D"); + "maximum search depth (default: none)", "D"); let matches = match opts.parse(&args[1..]) { Ok(m) => m, @@ -254,13 +248,13 @@ fn main() { case_sensitive: matches.opt_present("sensitive") || pattern.chars().any(char::is_uppercase), search_full_path: matches.opt_present("full-path"), - search_hidden: matches.opt_present("hidden"), - colored: colored_output, + ignore_hidden: !matches.opt_present("hidden"), + read_ignore: !matches.opt_present("no-ignore"), follow_links: matches.opt_present("follow"), max_depth: matches.opt_str("max-depth") - .and_then(|ds| usize::from_str_radix(&ds, 10).ok()) - .unwrap_or(MAX_DEPTH_DEFAULT), + .and_then(|ds| usize::from_str_radix(&ds, 10).ok()), + colored: colored_output, extension_styles: ext_styles };