@@ -5,6 +5,7 @@ mod text_effects;
55mod utils;
66use std:: os:: unix:: fs:: { FileTypeExt , MetadataExt } ;
77use structopt:: StructOpt ;
8+ use std:: cmp:: Ordering ;
89
910struct Directory {
1011 paths : Vec < File > ,
@@ -44,59 +45,69 @@ enum PathType {
4445impl PathType {
4546 fn new ( file : & std:: path:: PathBuf ) -> Result < Vec < Self > , Box < dyn std:: error:: Error > > {
4647 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 ) }
5455
5556 Ok ( return_val)
5657 }
5758
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+
5869 fn get_letter_for_type ( & self ) -> String {
5970 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 ( "." ) ,
6778 }
6879 }
6980
7081 fn get_color_for_type ( & self ) -> String {
7182 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 ) ) ,
7990 }
8091 }
8192
8293 fn get_text_traits_for_type ( & self , name : & str , file : & std:: path:: PathBuf ) -> String {
8394 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 ) ) ) ,
91102 }
92103 }
93104}
94105
95106impl File {
96107 fn new ( file : std:: path:: PathBuf ) -> Self {
97108 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 ( ) ) ,
100111 modified : utils:: file_times:: modified ( file. to_path_buf ( ) , input:: Cli :: from_args ( ) . time_format ) ,
101112 created : utils:: file_times:: created ( file. to_path_buf ( ) , input:: Cli :: from_args ( ) . time_format ) ,
102113 size : utils:: size:: size ( file. to_path_buf ( ) ) ,
@@ -143,49 +154,6 @@ impl Directory {
143154 Ok ( Self { paths } )
144155 }
145156
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- }
189157
190158 fn sort_directory_then_path ( & mut self ) {
191159 let new = & self . paths ;
@@ -235,14 +203,63 @@ impl Directory {
235203 input:: Cli :: from_args ( ) . modified ,
236204 input:: Cli :: from_args ( ) . size ,
237205 ] ) {
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+ } ) ,
242258 DirSortType :: Not => ( ) ,
243259 }
244260 }
245261
262+
246263 fn sort ( & mut self ) {
247264 match input:: Cli :: from_args ( ) . gdf {
248265 true => self . sort_directory_then_path ( ) ,
@@ -288,12 +305,18 @@ impl Directory {
288305 }
289306 }
290307
291- fn setup ( & mut self ) {
308+ fn setup ( & mut self ) -> & mut Directory {
292309 self . sort ( ) ;
293310 self . add_space ( ) ;
311+ self
294312 }
295313}
296314
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+
297320fn name_sort ( dir : & mut Vec < File > ) {
298321 dir. sort_by ( |a, b| {
299322 a. path
@@ -346,7 +369,16 @@ impl std::fmt::Display for File {
346369 res = format ! (
347370 "{}{}" ,
348371 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+ )
350382 ) ;
351383 } else {
352384 res = format ! (
@@ -365,8 +397,16 @@ impl std::fmt::Debug for File {
365397 let mut res = String :: new ( ) ;
366398 for ( i, v) in self . file_type . iter ( ) . enumerate ( ) {
367399 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+ ) ;
370410 res = format ! ( "{}{}" , v. get_color_for_type( ) , res) ;
371411 } else {
372412 res = v. get_text_traits_for_type ( & res, & self . path ) ;
@@ -377,18 +417,11 @@ impl std::fmt::Debug for File {
377417 if input:: Cli :: from_args ( ) . created_time {
378418 time = & self . created ;
379419 }
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 ) ,
392425 )
393426 }
394427}
@@ -405,10 +438,11 @@ impl std::fmt::Display for Directory {
405438}
406439
407440fn 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+ ) ;
412446}
413447
414448#[ cfg( test) ]
0 commit comments