@@ -5,6 +5,7 @@ use std::path::Path;
5
5
use lscolors:: { Indicator , LsColors , Style } ;
6
6
7
7
use crate :: config:: Config ;
8
+ use crate :: dir_entry:: DirEntry ;
8
9
use crate :: error:: print_error;
9
10
use crate :: exit_codes:: ExitCode ;
10
11
use crate :: filesystem:: strip_current_dir;
@@ -13,18 +14,21 @@ fn replace_path_separator(path: &str, new_path_separator: &str) -> String {
13
14
path. replace ( std:: path:: MAIN_SEPARATOR , new_path_separator)
14
15
}
15
16
16
- // TODO: this function is performance critical and can probably be optimized
17
- pub fn print_entry < W : Write > ( stdout : & mut W , entry : & Path , config : & Config ) {
18
- let path = if config. strip_cwd_prefix {
19
- strip_current_dir ( entry )
17
+ fn stripped_path < ' a > ( entry : & ' a DirEntry , config : & Config ) -> & ' a Path {
18
+ let path = entry . path ( ) ;
19
+ if config. strip_cwd_prefix {
20
+ strip_current_dir ( path )
20
21
} else {
21
- entry
22
- } ;
22
+ path
23
+ }
24
+ }
23
25
26
+ // TODO: this function is performance critical and can probably be optimized
27
+ pub fn print_entry < W : Write > ( stdout : & mut W , entry : & DirEntry , config : & Config ) {
24
28
let r = if let Some ( ref ls_colors) = config. ls_colors {
25
- print_entry_colorized ( stdout, path , config, ls_colors)
29
+ print_entry_colorized ( stdout, entry , config, ls_colors)
26
30
} else {
27
- print_entry_uncolorized ( stdout, path , config)
31
+ print_entry_uncolorized ( stdout, entry , config)
28
32
} ;
29
33
30
34
if let Err ( e) = r {
@@ -38,15 +42,39 @@ pub fn print_entry<W: Write>(stdout: &mut W, entry: &Path, config: &Config) {
38
42
}
39
43
}
40
44
45
+ // Display a trailing slash if the path is a directory and the config option is enabled.
46
+ // If the path_separator option is set, display that instead.
47
+ // The trailing slash will not be colored.
48
+ #[ inline]
49
+ fn print_trailing_slash < W : Write > (
50
+ stdout : & mut W ,
51
+ entry : & DirEntry ,
52
+ config : & Config ,
53
+ style : Option < & Style > ,
54
+ ) -> io:: Result < ( ) > {
55
+ if entry. file_type ( ) . map_or ( false , |ft| ft. is_dir ( ) ) {
56
+ write ! (
57
+ stdout,
58
+ "{}" ,
59
+ style
60
+ . map( Style :: to_ansi_term_style)
61
+ . unwrap_or_default( )
62
+ . paint( & config. actual_path_separator)
63
+ ) ?;
64
+ }
65
+ Ok ( ( ) )
66
+ }
67
+
41
68
// TODO: this function is performance critical and can probably be optimized
42
69
fn print_entry_colorized < W : Write > (
43
70
stdout : & mut W ,
44
- path : & Path ,
71
+ entry : & DirEntry ,
45
72
config : & Config ,
46
73
ls_colors : & LsColors ,
47
74
) -> io:: Result < ( ) > {
48
75
// Split the path between the parent and the last component
49
76
let mut offset = 0 ;
77
+ let path = stripped_path ( entry, config) ;
50
78
let path_str = path. to_string_lossy ( ) ;
51
79
52
80
if let Some ( parent) = path. parent ( ) {
@@ -74,11 +102,18 @@ fn print_entry_colorized<W: Write>(
74
102
}
75
103
76
104
let style = ls_colors
77
- . style_for_path ( path)
105
+ . style_for_path_with_metadata ( path, entry . metadata ( ) )
78
106
. map ( Style :: to_ansi_term_style)
79
107
. unwrap_or_default ( ) ;
80
108
write ! ( stdout, "{}" , style. paint( & path_str[ offset..] ) ) ?;
81
109
110
+ print_trailing_slash (
111
+ stdout,
112
+ entry,
113
+ config,
114
+ ls_colors. style_for_indicator ( Indicator :: Directory ) ,
115
+ ) ?;
116
+
82
117
if config. null_separator {
83
118
write ! ( stdout, "\0 " ) ?;
84
119
} else {
@@ -91,42 +126,46 @@ fn print_entry_colorized<W: Write>(
91
126
// TODO: this function is performance critical and can probably be optimized
92
127
fn print_entry_uncolorized_base < W : Write > (
93
128
stdout : & mut W ,
94
- path : & Path ,
129
+ entry : & DirEntry ,
95
130
config : & Config ,
96
131
) -> io:: Result < ( ) > {
97
132
let separator = if config. null_separator { "\0 " } else { "\n " } ;
133
+ let path = stripped_path ( entry, config) ;
98
134
99
135
let mut path_string = path. to_string_lossy ( ) ;
100
136
if let Some ( ref separator) = config. path_separator {
101
137
* path_string. to_mut ( ) = replace_path_separator ( & path_string, separator) ;
102
138
}
103
- write ! ( stdout, "{}{}" , path_string, separator)
139
+ write ! ( stdout, "{}" , path_string) ?;
140
+ print_trailing_slash ( stdout, entry, config, None ) ?;
141
+ write ! ( stdout, "{}" , separator)
104
142
}
105
143
106
144
#[ cfg( not( unix) ) ]
107
145
fn print_entry_uncolorized < W : Write > (
108
146
stdout : & mut W ,
109
- path : & Path ,
147
+ entry : & DirEntry ,
110
148
config : & Config ,
111
149
) -> io:: Result < ( ) > {
112
- print_entry_uncolorized_base ( stdout, path , config)
150
+ print_entry_uncolorized_base ( stdout, entry , config)
113
151
}
114
152
115
153
#[ cfg( unix) ]
116
154
fn print_entry_uncolorized < W : Write > (
117
155
stdout : & mut W ,
118
- path : & Path ,
156
+ entry : & DirEntry ,
119
157
config : & Config ,
120
158
) -> io:: Result < ( ) > {
121
159
use std:: os:: unix:: ffi:: OsStrExt ;
122
160
123
161
if config. interactive_terminal || config. path_separator . is_some ( ) {
124
162
// Fall back to the base implementation
125
- print_entry_uncolorized_base ( stdout, path , config)
163
+ print_entry_uncolorized_base ( stdout, entry , config)
126
164
} else {
127
165
// Print path as raw bytes, allowing invalid UTF-8 filenames to be passed to other processes
128
166
let separator = if config. null_separator { b"\0 " } else { b"\n " } ;
129
- stdout. write_all ( path. as_os_str ( ) . as_bytes ( ) ) ?;
167
+ stdout. write_all ( stripped_path ( entry, config) . as_os_str ( ) . as_bytes ( ) ) ?;
168
+ print_trailing_slash ( stdout, entry, config, None ) ?;
130
169
stdout. write_all ( separator)
131
170
}
132
171
}
0 commit comments