Răsfoiți Sursa

fix: selectively filter files when recursing #1101

PThorpe92 1 an în urmă
părinte
comite
c34458d1a3
3 a modificat fișierele cu 34 adăugiri și 34 ștergeri
  1. 18 28
      src/fs/filter.rs
  2. 14 5
      src/main.rs
  3. 2 1
      src/output/details.rs

+ 18 - 28
src/fs/filter.rs

@@ -85,38 +85,28 @@ pub struct FileFilter {
 impl FileFilter {
     /// Remove every file in the given vector that does *not* pass the
     /// filter predicate for files found inside a directory.
-    pub fn filter_child_files(&self, files: &mut Vec<File<'_>>) {
+#[rustfmt::skip]
+    pub fn filter_child_files(&self, is_recurse: bool, files: &mut Vec<File<'_>>) {
         use FileFilterFlags::{NoSymlinks, OnlyDirs, OnlyFiles, ShowSymlinks};
 
         files.retain(|f| !self.ignore_patterns.is_ignored(&f.name));
-
-        match (
-            self.flags.contains(&OnlyDirs),
-            self.flags.contains(&OnlyFiles),
-            self.flags.contains(&NoSymlinks),
-            self.flags.contains(&ShowSymlinks),
-        ) {
-            (true, false, false, false) => {
-                // On pass '--only-dirs' flag only
-                files.retain(File::is_directory);
-            }
-            (true, false, true, false) => {
-                files.retain(File::is_directory);
-            }
-            (true, false, false, true) => {
-                files.retain(|f| f.is_directory() || f.points_to_directory());
-            }
-            (false, true, false, false) => {
-                files.retain(File::is_file);
+        files.retain(|f| {
+            match (
+                self.flags.contains(&OnlyDirs),
+                self.flags.contains(&OnlyFiles),
+                self.flags.contains(&NoSymlinks),
+                self.flags.contains(&ShowSymlinks),
+            ) {
+                (true, false, false, false) => f.is_directory(),
+                (true, false, true, false) => f.is_directory(),
+                (true, false, false, true) => f.is_directory() || f.points_to_directory(),
+                (false, true, false, false) => if is_recurse { true } else {f.is_file() },
+                (false, true, false, true) => if is_recurse { true } else { f.is_file() || f.is_link() && !f.points_to_directory()
+                },
+                (false, false, true, false) => !f.is_link(),
+                _ => true,
             }
-            (false, true, false, true) => {
-                files.retain(|f| f.is_file() || f.is_link() && !f.points_to_directory());
-            }
-            (false, false, true, false) => {
-                files.retain(|f| !f.is_link());
-            }
-            _ => {}
-        }
+        });
     }
 
     /// Remove every file in the given vector that does *not* pass the

+ 14 - 5
src/main.rs

@@ -30,7 +30,7 @@ use std::process::exit;
 use nu_ansi_term::{AnsiStrings as ANSIStrings, Style};
 
 use crate::fs::feature::git::GitCache;
-use crate::fs::filter::GitIgnore;
+use crate::fs::filter::{FileFilterFlags::OnlyFiles, GitIgnore};
 use crate::fs::{Dir, File};
 use crate::options::stdin::FilesInput;
 use crate::options::{vars, Options, OptionsResult, Vars};
@@ -343,8 +343,10 @@ impl<'args> Exa<'args> {
                     Err((path, e)) => writeln!(io::stderr(), "[{}: {}]", path.display(), e)?,
                 }
             }
-
-            self.options.filter.filter_child_files(&mut children);
+            let recursing = self.options.dir_action.recurse_options().is_some();
+            self.options
+                .filter
+                .filter_child_files(recursing, &mut children);
             self.options.filter.sort_files(&mut children);
 
             if let Some(recurse_opts) = self.options.dir_action.recurse_options() {
@@ -384,11 +386,18 @@ impl<'args> Exa<'args> {
     }
 
     /// Prints the list of files using whichever view is selected.
-    fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File<'_>>) -> io::Result<()> {
+    fn print_files(&mut self, dir: Option<&Dir>, mut files: Vec<File<'_>>) -> io::Result<()> {
         if files.is_empty() {
             return Ok(());
         }
-
+        let recursing = self.options.dir_action.recurse_options().is_some();
+        let only_files = self.options.filter.flags.contains(&OnlyFiles);
+        if recursing && only_files {
+            files = files
+                .into_iter()
+                .filter(|f| !f.is_directory())
+                .collect::<Vec<_>>();
+        }
         let theme = &self.theme;
         let View {
             ref mode,

+ 2 - 1
src/output/details.rs

@@ -356,7 +356,8 @@ impl<'a> Render<'a> {
                     }
                 }
 
-                self.filter.filter_child_files(&mut files);
+                self.filter
+                    .filter_child_files(self.recurse.is_some(), &mut files);
 
                 if !files.is_empty() {
                     for xattr in egg.xattrs {