@@ -5,6 +5,7 @@ mod text_effects;
5
5
mod utils;
6
6
use std:: os:: unix:: fs:: { FileTypeExt , MetadataExt } ;
7
7
use structopt:: StructOpt ;
8
+ use std:: cmp:: Ordering ;
8
9
9
10
struct Directory {
10
11
paths : Vec < File > ,
@@ -44,59 +45,69 @@ enum PathType {
44
45
impl PathType {
45
46
fn new ( file : & std:: path:: PathBuf ) -> Result < Vec < Self > , Box < dyn std:: error:: Error > > {
46
47
let mut return_val = Vec :: new ( ) ;
47
- if file. symlink_metadata ( ) ?. is_dir ( ) { return_val. push ( Self :: Dir ) }
48
- if file. symlink_metadata ( ) ?. file_type ( ) . is_symlink ( ) { return_val. push ( Self :: Symlink ) }
49
- if file. symlink_metadata ( ) ?. file_type ( ) . is_fifo ( ) { return_val. push ( Self :: Pipe ) }
50
- if file. symlink_metadata ( ) ?. file_type ( ) . is_char_device ( ) { return_val. push ( Self :: CharD ) }
51
- if file. symlink_metadata ( ) ?. file_type ( ) . is_block_device ( ) { return_val. push ( Self :: BlockD ) }
52
- if file. symlink_metadata ( ) ?. file_type ( ) . is_socket ( ) { return_val. push ( Self :: Socket ) }
53
- if return_val. is_empty ( ) { return_val. push ( Self :: Path ) }
48
+ if file. symlink_metadata ( ) ?. is_dir ( ) { return_val. push ( Self :: Dir ) }
49
+ if file. symlink_metadata ( ) ?. file_type ( ) . is_symlink ( ) { return_val. push ( Self :: Symlink ) }
50
+ if file. symlink_metadata ( ) ?. file_type ( ) . is_fifo ( ) { return_val. push ( Self :: Pipe ) }
51
+ if file. symlink_metadata ( ) ?. file_type ( ) . is_char_device ( ) { return_val. push ( Self :: CharD ) }
52
+ if file. symlink_metadata ( ) ?. file_type ( ) . is_block_device ( ) { return_val. push ( Self :: BlockD ) }
53
+ if file. symlink_metadata ( ) ?. file_type ( ) . is_socket ( ) { return_val. push ( Self :: Socket ) }
54
+ if return_val. is_empty ( ) { return_val. push ( Self :: Path ) }
54
55
55
56
Ok ( return_val)
56
57
}
57
58
59
+ fn create_letter ( & self , letter : & str ) -> String {
60
+ format ! (
61
+ "{}{}{}{}" ,
62
+ self . get_color_for_type( ) ,
63
+ letter,
64
+ termion:: color:: Fg ( termion:: color:: Reset ) ,
65
+ termion:: color:: Bg ( termion:: color:: Reset )
66
+ )
67
+ }
68
+
58
69
fn get_letter_for_type ( & self ) -> String {
59
70
match self {
60
- Self :: Dir => format ! ( "{}d{}{}" , self . get_color_for_type ( ) , termion :: color :: Fg ( termion :: color :: Reset ) , termion :: color :: Bg ( termion :: color :: Reset ) ) ,
61
- Self :: Symlink => format ! ( "{}l{}{}" , self . get_color_for_type ( ) , termion :: color :: Fg ( termion :: color :: Reset ) , termion :: color :: Bg ( termion :: color :: Reset ) ) ,
62
- Self :: Pipe => format ! ( "{}|{}{}" , self . get_color_for_type ( ) , termion :: color :: Fg ( termion :: color :: Reset ) , termion :: color :: Bg ( termion :: color :: Reset ) ) ,
63
- Self :: CharD => format ! ( "{}c{}{}" , self . get_color_for_type ( ) , termion :: color :: Fg ( termion :: color :: Reset ) , termion :: color :: Bg ( termion :: color :: Reset ) ) ,
64
- Self :: BlockD => format ! ( "{}b{}{}" , self . get_color_for_type ( ) , termion :: color :: Fg ( termion :: color :: Reset ) , termion :: color :: Bg ( termion :: color :: Reset ) ) ,
65
- Self :: Socket => format ! ( "{}s{}{}" , self . get_color_for_type ( ) , termion :: color :: Fg ( termion :: color :: Reset ) , termion :: color :: Bg ( termion :: color :: Reset ) ) ,
66
- _ => format ! ( "{}.{}{}" , self . get_color_for_type ( ) , termion :: color :: Fg ( termion :: color :: Reset ) , termion :: color :: Bg ( termion :: color :: Reset ) ) ,
71
+ Self :: Dir => self . create_letter ( "d" ) ,
72
+ Self :: Symlink => self . create_letter ( "l" ) ,
73
+ Self :: Pipe => self . create_letter ( "|" ) ,
74
+ Self :: CharD => self . create_letter ( "c" ) ,
75
+ Self :: BlockD => self . create_letter ( "b" ) ,
76
+ Self :: Socket => self . create_letter ( "s" ) ,
77
+ _ => self . create_letter ( "." ) ,
67
78
}
68
79
}
69
80
70
81
fn get_color_for_type ( & self ) -> String {
71
82
match self {
72
- Self :: Dir => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightBlue ) ) ,
73
- Self :: Symlink => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightMagenta ) ) ,
74
- Self :: Path => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: White ) ) ,
75
- Self :: Pipe => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: Yellow ) ) ,
76
- Self :: CharD => format ! ( "{}{}" , termion:: color:: Bg ( termion:: color:: Yellow ) , termion:: color:: Fg ( termion:: color:: LightBlue ) ) ,
77
- Self :: BlockD => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightGreen ) ) ,
78
- Self :: Socket => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightRed ) ) ,
83
+ Self :: Dir => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightBlue ) ) ,
84
+ Self :: Symlink => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightMagenta ) ) ,
85
+ Self :: Path => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: White ) ) ,
86
+ Self :: Pipe => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: Yellow ) ) ,
87
+ Self :: CharD => format ! ( "{}{}" , termion:: color:: Bg ( termion:: color:: Yellow ) , termion:: color:: Fg ( termion:: color:: LightBlue ) ) ,
88
+ Self :: BlockD => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightGreen ) ) ,
89
+ Self :: Socket => format ! ( "{}" , termion:: color:: Fg ( termion:: color:: LightRed ) ) ,
79
90
}
80
91
}
81
92
82
93
fn get_text_traits_for_type ( & self , name : & str , file : & std:: path:: PathBuf ) -> String {
83
94
match self {
84
- Self :: Dir => text_effects:: bold ( & format ! ( "{}{}/" , name, termion:: color:: Fg ( termion:: color:: White ) ) ) ,
85
- Self :: Symlink => text_effects:: italic ( & format ! ( "{} -> {}" , name, std:: fs:: read_link( file) . unwrap( ) . display( ) . to_string( ) ) ) ,
86
- Self :: Path => text_effects:: bold ( name) ,
87
- Self :: Pipe => text_effects:: bold ( & format ! ( "{}{}" , name, termion:: color:: Fg ( termion:: color:: White ) ) ) ,
88
- Self :: CharD => text_effects:: bold ( name) ,
89
- Self :: BlockD => text_effects:: bold ( name) ,
90
- Self :: Socket => text_effects:: bold ( & format ! ( "{}{}" , name, termion:: color:: Fg ( termion:: color:: White ) ) ) ,
95
+ Self :: Dir => text_effects:: bold ( & format ! ( "{}{}/" , name, termion:: color:: Fg ( termion:: color:: White ) ) ) ,
96
+ Self :: Symlink => text_effects:: italic ( & format ! ( "{} -> {}" , name, std:: fs:: read_link( file) . unwrap( ) . display( ) . to_string( ) ) ) ,
97
+ Self :: Path => text_effects:: bold ( name) ,
98
+ Self :: Pipe => text_effects:: bold ( & format ! ( "{}{}" , name, termion:: color:: Fg ( termion:: color:: White ) ) ) ,
99
+ Self :: CharD => text_effects:: bold ( name) ,
100
+ Self :: BlockD => text_effects:: bold ( name) ,
101
+ Self :: Socket => text_effects:: bold ( & format ! ( "{}{}" , name, termion:: color:: Fg ( termion:: color:: White ) ) ) ,
91
102
}
92
103
}
93
104
}
94
105
95
106
impl File {
96
107
fn new ( file : std:: path:: PathBuf ) -> Self {
97
108
Self {
98
- group : utils:: get_group :: group ( file. to_path_buf ( ) ) ,
99
- user : utils:: get_user :: user ( file. to_path_buf ( ) ) ,
109
+ group : utils:: group ( file. to_path_buf ( ) ) ,
110
+ user : utils:: user ( file. to_path_buf ( ) ) ,
100
111
modified : utils:: file_times:: modified ( file. to_path_buf ( ) , input:: Cli :: from_args ( ) . time_format ) ,
101
112
created : utils:: file_times:: created ( file. to_path_buf ( ) , input:: Cli :: from_args ( ) . time_format ) ,
102
113
size : utils:: size:: size ( file. to_path_buf ( ) ) ,
@@ -143,49 +154,6 @@ impl Directory {
143
154
Ok ( Self { paths } )
144
155
}
145
156
146
- fn self_name_sort ( & mut self ) {
147
- self . paths . sort_by ( |a, b| {
148
- a. path
149
- . file_name ( )
150
- . unwrap ( )
151
- . to_str ( )
152
- . unwrap ( )
153
- . to_lowercase ( )
154
- . cmp ( & b. path . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_lowercase ( ) )
155
- } )
156
- }
157
-
158
- fn self_create_sort ( & mut self ) {
159
- self . paths . sort_by ( |a, b| {
160
- a. path
161
- . symlink_metadata ( )
162
- . unwrap ( )
163
- . created ( )
164
- . unwrap ( )
165
- . cmp ( & b. path . symlink_metadata ( ) . unwrap ( ) . created ( ) . unwrap ( ) )
166
- } )
167
- }
168
-
169
- fn self_modified_sort ( & mut self ) {
170
- self . paths . sort_by ( |a, b| {
171
- a. path
172
- . symlink_metadata ( )
173
- . unwrap ( )
174
- . modified ( )
175
- . unwrap ( )
176
- . cmp ( & b. path . symlink_metadata ( ) . unwrap ( ) . modified ( ) . unwrap ( ) )
177
- } )
178
- }
179
-
180
- fn self_size_sort ( & mut self ) {
181
- self . paths . sort_by ( |a, b| {
182
- a. path
183
- . symlink_metadata ( )
184
- . unwrap ( )
185
- . size ( )
186
- . cmp ( & b. path . symlink_metadata ( ) . unwrap ( ) . size ( ) )
187
- } )
188
- }
189
157
190
158
fn sort_directory_then_path ( & mut self ) {
191
159
let new = & self . paths ;
@@ -235,14 +203,63 @@ impl Directory {
235
203
input:: Cli :: from_args ( ) . modified ,
236
204
input:: Cli :: from_args ( ) . size ,
237
205
] ) {
238
- DirSortType :: Name => self . self_name_sort ( ) ,
239
- DirSortType :: Created => self . self_create_sort ( ) ,
240
- DirSortType :: Modified => self . self_modified_sort ( ) ,
241
- DirSortType :: Size => self . self_size_sort ( ) ,
206
+ DirSortType :: Name => sort_as ( & mut self . paths , |a, b| {
207
+ a. path
208
+ . file_name ( )
209
+ . unwrap ( )
210
+ . to_str ( )
211
+ . unwrap ( )
212
+ . to_lowercase ( )
213
+ . cmp ( & b. path
214
+ . file_name ( )
215
+ . unwrap ( )
216
+ . to_str ( )
217
+ . unwrap ( )
218
+ . to_lowercase ( )
219
+ )
220
+ } ) ,
221
+ DirSortType :: Created => sort_as ( & mut self . paths , |a, b| {
222
+ a. path
223
+ . symlink_metadata ( )
224
+ . unwrap ( )
225
+ . created ( )
226
+ . unwrap ( )
227
+ . cmp ( & b. path
228
+ . symlink_metadata ( )
229
+ . unwrap ( )
230
+ . created ( )
231
+ . unwrap ( )
232
+ )
233
+ } ) ,
234
+ DirSortType :: Modified => sort_as ( & mut self . paths , |a, b| {
235
+ a. path
236
+ . symlink_metadata ( )
237
+ . unwrap ( )
238
+ . modified ( )
239
+ . unwrap ( )
240
+ . cmp ( & b. path
241
+ . symlink_metadata ( )
242
+ . unwrap ( )
243
+ . modified ( )
244
+ . unwrap ( )
245
+ )
246
+ } ) ,
247
+ DirSortType :: Size => sort_as ( & mut self . paths , |a, b| {
248
+ a. path
249
+ . symlink_metadata ( )
250
+ . unwrap ( )
251
+ . size ( )
252
+ . cmp ( & b. path .
253
+ symlink_metadata ( )
254
+ . unwrap ( )
255
+ . size ( )
256
+ )
257
+ } ) ,
242
258
DirSortType :: Not => ( ) ,
243
259
}
244
260
}
245
261
262
+
246
263
fn sort ( & mut self ) {
247
264
match input:: Cli :: from_args ( ) . gdf {
248
265
true => self . sort_directory_then_path ( ) ,
@@ -288,12 +305,18 @@ impl Directory {
288
305
}
289
306
}
290
307
291
- fn setup ( & mut self ) {
308
+ fn setup ( & mut self ) -> & mut Directory {
292
309
self . sort ( ) ;
293
310
self . add_space ( ) ;
311
+ self
294
312
}
295
313
}
296
314
315
+ fn sort_as < T > ( files : & mut Vec < File > , sort_method : T )
316
+ where T : Fn ( & File , & File ) -> Ordering {
317
+ files. sort_by ( sort_method)
318
+ }
319
+
297
320
fn name_sort ( dir : & mut Vec < File > ) {
298
321
dir. sort_by ( |a, b| {
299
322
a. path
@@ -346,7 +369,16 @@ impl std::fmt::Display for File {
346
369
res = format ! (
347
370
"{}{}" ,
348
371
v. get_color_for_type( ) ,
349
- v. get_text_traits_for_type( & self . path. components( ) . next_back( ) . unwrap( ) . as_os_str( ) . to_string_lossy( ) . to_string( ) , & self . path)
372
+ v. get_text_traits_for_type(
373
+ & self . path.
374
+ components( )
375
+ . next_back( )
376
+ . unwrap( )
377
+ . as_os_str( )
378
+ . to_string_lossy( )
379
+ . to_string( ) ,
380
+ & self . path
381
+ )
350
382
) ;
351
383
} else {
352
384
res = format ! (
@@ -365,8 +397,16 @@ impl std::fmt::Debug for File {
365
397
let mut res = String :: new ( ) ;
366
398
for ( i, v) in self . file_type . iter ( ) . enumerate ( ) {
367
399
if i == 0 {
368
- res =
369
- v. get_text_traits_for_type ( & self . path . components ( ) . next_back ( ) . unwrap ( ) . as_os_str ( ) . to_string_lossy ( ) . to_string ( ) , & self . path ) ;
400
+ res = v. get_text_traits_for_type (
401
+ & self . path
402
+ . components ( )
403
+ . next_back ( )
404
+ . unwrap ( )
405
+ . as_os_str ( )
406
+ . to_string_lossy ( )
407
+ . to_string ( ) ,
408
+ & self . path
409
+ ) ;
370
410
res = format ! ( "{}{}" , v. get_color_for_type( ) , res) ;
371
411
} else {
372
412
res = v. get_text_traits_for_type ( & res, & self . path ) ;
@@ -377,18 +417,11 @@ impl std::fmt::Debug for File {
377
417
if input:: Cli :: from_args ( ) . created_time {
378
418
time = & self . created ;
379
419
}
380
- writeln ! (
381
- f,
382
- "{} {}{} {}{} {} {}{} {}" ,
383
- self . perms,
384
- termion:: color:: Fg ( termion:: color:: LightGreen ) ,
385
- self . size,
386
- termion:: color:: Fg ( termion:: color:: Yellow ) ,
387
- self . user,
388
- self . group,
389
- termion:: color:: Fg ( termion:: color:: Blue ) ,
390
- time,
391
- res
420
+ writeln ! ( f, "{} {green}{} {yellow}{} {blue} {}{} {}" ,
421
+ self . perms, self . size, self . user, self . group, time, res,
422
+ green = termion:: color:: Fg ( termion:: color:: LightGreen ) ,
423
+ yellow = termion:: color:: Fg ( termion:: color:: Yellow ) ,
424
+ blue = termion:: color:: Fg ( termion:: color:: Blue ) ,
392
425
)
393
426
}
394
427
}
@@ -405,10 +438,11 @@ impl std::fmt::Display for Directory {
405
438
}
406
439
407
440
fn main ( ) {
408
- let mut dir = Directory :: new ( input:: Cli :: from_args ( ) . dir ) . expect ( "Failed to run natls" ) ;
409
- // let mut dir = Directory::new(std::path::PathBuf::from("wrong path")).expect("Failed to run natls");
410
- dir. setup ( ) ;
411
- println ! ( "{}" , dir) ;
441
+ println ! ( "{}" ,
442
+ Directory :: new( input:: Cli :: from_args( ) . dir)
443
+ . expect( "Failed to run natls" )
444
+ . setup( )
445
+ ) ;
412
446
}
413
447
414
448
#[ cfg( test) ]
0 commit comments