@@ -2,6 +2,7 @@ use std::cmp::Ordering;
2
2
use std:: os:: unix:: fs:: MetadataExt ;
3
3
4
4
use getopts;
5
+ use glob;
5
6
use natord;
6
7
7
8
use fs:: File ;
@@ -60,29 +61,47 @@ pub struct FileFilter {
60
61
/// evaluation that goes through my home directory is slowed down by
61
62
/// this accumulated sludge.
62
63
show_invisibles : bool ,
64
+
65
+ /// Glob patterns to ignore. Any file name that matches *any* of these
66
+ /// patterns won't be displayed in the list.
67
+ ignore_patterns : IgnorePatterns ,
63
68
}
64
69
65
70
impl FileFilter {
66
71
67
72
/// Determines the set of file filter options to use, based on the user’s
68
73
/// command-line arguments.
69
74
pub fn deduce ( matches : & getopts:: Matches ) -> Result < FileFilter , Misfire > {
70
- let sort_field = try!( SortField :: deduce ( & matches) ) ;
71
-
72
75
Ok ( FileFilter {
73
76
list_dirs_first : matches. opt_present ( "group-directories-first" ) ,
74
77
reverse : matches. opt_present ( "reverse" ) ,
78
+ sort_field : try!( SortField :: deduce ( matches) ) ,
75
79
show_invisibles : matches. opt_present ( "all" ) ,
76
- sort_field : sort_field ,
80
+ ignore_patterns : try! ( IgnorePatterns :: deduce ( matches ) ) ,
77
81
} )
78
82
}
79
83
80
84
/// Remove every file in the given vector that does *not* pass the
81
- /// filter predicate.
82
- pub fn filter_files ( & self , files : & mut Vec < File > ) {
85
+ /// filter predicate for files found inside a directory .
86
+ pub fn filter_child_files ( & self , files : & mut Vec < File > ) {
83
87
if !self . show_invisibles {
84
88
files. retain ( |f| !f. is_dotfile ( ) ) ;
85
89
}
90
+
91
+ files. retain ( |f| !self . ignore_patterns . is_ignored ( f) ) ;
92
+ }
93
+
94
+ /// Remove every file in the given vector that does *not* pass the
95
+ /// filter predicate for file names specified on the command-line.
96
+ ///
97
+ /// The rules are different for these types of files than the other
98
+ /// type because the ignore rules can be used with globbing. For
99
+ /// example, running "exa -I='*.tmp' .vimrc" shouldn't filter out the
100
+ /// dotfile, because it's been directly specified. But running
101
+ /// "exa -I='*.ogg' music/*" should filter out the ogg files obtained
102
+ /// from the glob, even though the globbing is done by the shell!
103
+ pub fn filter_argument_files ( & self , files : & mut Vec < File > ) {
104
+ files. retain ( |f| !self . ignore_patterns . is_ignored ( f) ) ;
86
105
}
87
106
88
107
/// Sort the files in the given vector based on the sort field option.
@@ -229,3 +248,28 @@ impl SortField {
229
248
}
230
249
}
231
250
}
251
+
252
+
253
+ #[ derive( PartialEq , Default , Debug , Clone ) ]
254
+ struct IgnorePatterns {
255
+ patterns : Vec < glob:: Pattern > ,
256
+ }
257
+
258
+ impl IgnorePatterns {
259
+ /// Determines the set of file filter options to use, based on the user’s
260
+ /// command-line arguments.
261
+ pub fn deduce ( matches : & getopts:: Matches ) -> Result < IgnorePatterns , Misfire > {
262
+ let patterns = match matches. opt_str ( "ignore-glob" ) {
263
+ None => Ok ( Vec :: new ( ) ) ,
264
+ Some ( is) => is. split ( '|' ) . map ( |a| glob:: Pattern :: new ( a) ) . collect ( ) ,
265
+ } ;
266
+
267
+ Ok ( IgnorePatterns {
268
+ patterns : try!( patterns) ,
269
+ } )
270
+ }
271
+
272
+ fn is_ignored ( & self , file : & File ) -> bool {
273
+ self . patterns . iter ( ) . any ( |p| p. matches ( & file. name ) )
274
+ }
275
+ }
0 commit comments