summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Larralde <martin.larralde@ens-cachan.fr>2018-02-07 16:13:28 +0100
committerDavid Peter <sharkdp@users.noreply.github.com>2018-02-10 14:18:37 +0100
commit370d9f081fd4d22eb4c8c1ac04d647fd718688b1 (patch)
treee1e1d36067801361cb02d21f6ec514bcf97416ad
parent86fe9977e8953ba3da826f233e6a51c561a78724 (diff)
Use RegexSet instead of hand-written parser
-rw-r--r--src/internal.rs3
-rw-r--r--src/main.rs14
-rw-r--r--src/utils.rs45
-rw-r--r--src/walk.rs9
4 files changed, 17 insertions, 54 deletions
diff --git a/src/internal.rs b/src/internal.rs
index c903204..fe9a43d 100644
--- a/src/internal.rs
+++ b/src/internal.rs
@@ -16,6 +16,7 @@ use exec::CommandTemplate;
use lscolors::LsColors;
use walk::FileType;
use regex_syntax::{Expr, ExprBuilder};
+use regex::RegexSet;
/// Configuration options for *fd*.
pub struct FdOptions {
@@ -65,7 +66,7 @@ pub struct FdOptions {
/// The extension to search for. Only entries matching the extension will be included.
///
/// The value (if present) will be a lowercase string without leading dots.
- pub extensions: Option<HashSet<String>>,
+ pub extensions: Option<RegexSet>,
/// If a value is supplied, each item found will be used to generate and execute commands.
pub command: Option<CommandTemplate>,
diff --git a/src/main.rs b/src/main.rs
index 62f5d41..bd714f1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -25,7 +25,6 @@ mod app;
mod exec;
mod internal;
mod output;
-mod utils;
mod walk;
#[cfg(windows)]
@@ -38,7 +37,7 @@ use std::sync::Arc;
use std::time;
use atty::Stream;
-use regex::RegexBuilder;
+use regex::{RegexBuilder, RegexSetBuilder};
use exec::CommandTemplate;
use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions};
@@ -153,8 +152,15 @@ fn main() {
.collect(),
},
extensions: matches.values_of("extension").map(|exts| {
- exts.map(|e| String::from(".") + &e.trim_left_matches('.'))
- .collect()
+ let patterns = exts.map(|e| e.trim_left_matches('.'))
+ .map(|e| format!(r".\.{}$", regex::escape(e)));
+ match RegexSetBuilder::new(patterns)
+ .case_insensitive(true)
+ .build()
+ {
+ Ok(re) => re,
+ Err(err) => error(err.description()),
+ }
}),
command,
exclude_patterns: matches
diff --git a/src/utils.rs b/src/utils.rs
deleted file mode 100644
index f2c3926..0000000
--- a/src/utils.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2017 fd developers
-// Licensed under the Apache License, Version 2.0
-// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
-// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
-// at your option. All files in the project carrying such
-// notice may not be copied, modified, or distributed except
-// according to those terms.
-
-use std::path::Path;
-use std::iter::Iterator;
-
-/// Determine if an os string ends with any of the given extensions (case insensitive).
-pub fn path_has_any_extension<'a, I>(path: &Path, exts: I) -> bool
-where
- I: 'a + Iterator<Item = &'a String> + Clone,
-{
- // TODO: remove these two lines when we drop support for Rust version < 1.23.
- #[allow(unused_imports)]
- use std::ascii::AsciiExt;
-
- if let Some(ref name) = path.file_name() {
- if let Some(ref name_str) = name.to_str() {
- exts.clone().any(|x| {
- let mut it = name_str.chars().rev();
-
- if x.chars()
- .rev()
- .zip(&mut it)
- .all(|(a, b)| a.eq_ignore_ascii_case(&b))
- {
- match it.next() {
- Some('/') | None => false,
- _ => true,
- }
- } else {
- false
- }
- })
- } else {
- false
- }
- } else {
- false
- }
-}
diff --git a/src/walk.rs b/src/walk.rs
index 121d3a8..ac71fa9 100644
--- a/src/walk.rs
+++ b/src/walk.rs
@@ -11,7 +11,6 @@ extern crate ctrlc;
use exec;
use fshelper;
use internal::{error, FdOptions, EXITCODE_SIGINT, MAX_BUFFER_LENGTH};
-use utils::path_has_any_extension;
use output;
use std::process;
@@ -214,9 +213,11 @@ pub fn scan(path_vec: &[PathBuf], pattern: Arc<Regex>, config: Arc<FdOptions>) {
}
// Filter out unwanted extensions.
- if let Some(ref filter_exts) = config.extensions {
- if !path_has_any_extension(entry_path, filter_exts.iter()) {
- return ignore::WalkState::Continue;
+ if let Some(ref exts_regex) = config.extensions {
+ if let Some(path_str) = entry_path.file_name().map_or(None, |s| s.to_str()) {
+ if !exts_regex.is_match(path_str) {
+ return ignore::WalkState::Continue;
+ }
}
}