summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsharkdp <davidpeter@web.de>2018-02-25 11:11:14 +0100
committerDavid Peter <sharkdp@users.noreply.github.com>2018-02-25 18:17:11 +0100
commit40d811c7be96914ed15c0e91df4ab4457a61a01d (patch)
tree07a54f3d4486fe408272af9047a02b58f038aa9c
parente5ee5eb7b360d3e15efd582d0ab5e11b880046e1 (diff)
Rewrite of file-type filtering leading to 5% speed-up
-rw-r--r--src/internal.rs24
-rw-r--r--src/main.rs31
-rw-r--r--src/walk.rs27
3 files changed, 44 insertions, 38 deletions
diff --git a/src/internal.rs b/src/internal.rs
index 172e32b..5d694b5 100644
--- a/src/internal.rs
+++ b/src/internal.rs
@@ -6,7 +6,6 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
-use std::collections::HashSet;
use std::ffi::OsString;
use std::process;
use std::time;
@@ -14,10 +13,26 @@ use std::io::Write;
use exec::CommandTemplate;
use lscolors::LsColors;
-use walk::FileType;
use regex_syntax::{Expr, ExprBuilder};
use regex::RegexSet;
+/// Whether or not to show
+pub struct FileTypes {
+ pub files: bool,
+ pub directories: bool,
+ pub symlinks: bool,
+}
+
+impl Default for FileTypes {
+ fn default() -> FileTypes {
+ FileTypes {
+ files: false,
+ directories: false,
+ symlinks: false,
+ }
+ }
+}
+
/// Configuration options for *fd*.
pub struct FdOptions {
/// Whether the search is case-sensitive or case-insensitive.
@@ -60,8 +75,9 @@ pub struct FdOptions {
/// how to style different filetypes.
pub ls_colors: Option<LsColors>,
- /// The type of file to search for. All files other than the specified type will be ignored.
- pub file_types: HashSet<FileType>,
+ /// The type of file to search for. If set to `None`, all file types are displayed. If
+ /// set to `Some(..)`, only the types that are specified are shown.
+ pub file_types: Option<FileTypes>,
/// The extension to search for. Only entries matching the extension will be included.
///
diff --git a/src/main.rs b/src/main.rs
index e40e730..df749db 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -40,9 +40,8 @@ use atty::Stream;
use regex::{RegexBuilder, RegexSetBuilder};
use exec::CommandTemplate;
-use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions};
+use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions, FileTypes};
use lscolors::LsColors;
-use walk::FileType;
fn main() {
let checked_args = transform_args_with_exec(env::args_os());
@@ -142,22 +141,18 @@ fn main() {
.and_then(|n| u64::from_str_radix(n, 10).ok())
.map(time::Duration::from_millis),
ls_colors,
- file_types: match matches.values_of("file-type") {
- None => vec![
- FileType::RegularFile,
- FileType::Directory,
- FileType::SymLink,
- ].into_iter()
- .collect(),
- Some(values) => values
- .map(|value| match value {
- "f" | "file" => FileType::RegularFile,
- "d" | "directory" => FileType::Directory,
- "l" | "symlink" => FileType::SymLink,
- _ => FileType::RegularFile,
- })
- .collect(),
- },
+ file_types: matches.values_of("file-type").map(|values| {
+ let mut file_types = FileTypes::default();
+ for value in values {
+ match value {
+ "f" | "file" => file_types.files = true,
+ "d" | "directory" => file_types.directories = true,
+ "l" | "symlink" => file_types.symlinks = true,
+ _ => unreachable!(),
+ }
+ }
+ file_types
+ }),
extensions: matches.values_of("extension").map(|exts| {
let patterns = exts.map(|e| e.trim_left_matches('.'))
.map(|e| format!(r".\.{}$", regex::escape(e)));
diff --git a/src/walk.rs b/src/walk.rs
index a1d32e2..346ab63 100644
--- a/src/walk.rs
+++ b/src/walk.rs
@@ -35,14 +35,6 @@ enum ReceiverMode {
Streaming,
}
-/// The types of file to search for.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum FileType {
- RegularFile,
- Directory,
- SymLink,
-}
-
/// Recursively scan the given search path for files / pathnames matching the pattern.
///
/// If the `--exec` argument was supplied, this will create a thread pool for executing
@@ -206,14 +198,17 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) {
}
// Filter out unwanted file types.
- if (entry.file_type().map_or(false, |ft| ft.is_file())
- && !config.file_types.contains(&FileType::RegularFile))
- || (entry.file_type().map_or(false, |ft| ft.is_dir())
- && !config.file_types.contains(&FileType::Directory))
- || (entry.file_type().map_or(false, |ft| ft.is_symlink())
- && !config.file_types.contains(&FileType::SymLink))
- {
- return ignore::WalkState::Continue;
+ if let Some(ref file_types) = config.file_types {
+ if let Some(ref entry_type) = entry.file_type() {
+ if (entry_type.is_file() && !file_types.files)
+ || (entry_type.is_dir() && !file_types.directories)
+ || (entry_type.is_symlink() && !file_types.symlinks)
+ {
+ return ignore::WalkState::Continue;
+ }
+ } else {
+ return ignore::WalkState::Continue;
+ }
}
// Filter out unwanted extensions.