@@ -16,12 +16,44 @@ use tracing_subscriber::{
16
16
registry:: LookupSpan ,
17
17
} ;
18
18
19
+ const LINE_VERT : & str = "│" ;
20
+ const LINE_HORIZ : & str = "─" ;
21
+ const LINE_BRANCH : & str = "├" ;
22
+
23
+ #[ derive( Debug ) ]
24
+ struct Config {
25
+ ansi : bool ,
26
+ indent_lines : bool ,
27
+ indent_amount : usize ,
28
+ }
29
+
30
+ impl Config {
31
+ fn with_ansi ( self , ansi : bool ) -> Self {
32
+ Self { ansi, ..self }
33
+ }
34
+ fn with_indent_lines ( self , indent_lines : bool ) -> Self {
35
+ Self {
36
+ indent_lines,
37
+ ..self
38
+ }
39
+ }
40
+ }
41
+
42
+ impl Default for Config {
43
+ fn default ( ) -> Self {
44
+ Self {
45
+ ansi : true ,
46
+ indent_lines : false ,
47
+ indent_amount : 2 ,
48
+ }
49
+ }
50
+ }
51
+
19
52
#[ derive( Debug ) ]
20
53
pub struct HierarchicalLayer {
21
54
stdout : io:: Stdout ,
22
- indent_amount : usize ,
23
- ansi : bool ,
24
55
bufs : Mutex < Buffers > ,
56
+ config : Config ,
25
57
}
26
58
27
59
#[ derive( Debug ) ]
@@ -48,12 +80,13 @@ impl Buffers {
48
80
self . indent_buf . clear ( ) ;
49
81
}
50
82
51
- fn indent_current ( & mut self , indent : usize , indent_amount : usize ) {
83
+ fn indent_current ( & mut self , indent : usize , config : & Config ) {
52
84
indent_block (
53
85
& mut self . current_buf ,
54
86
& mut self . indent_buf ,
55
87
indent,
56
- indent_amount,
88
+ config. indent_amount ,
89
+ config. indent_lines ,
57
90
) ;
58
91
self . current_buf . clear ( ) ;
59
92
}
@@ -102,9 +135,9 @@ impl<'a> Visit for FmtEvent<'a> {
102
135
}
103
136
104
137
impl < ' a > FmtEvent < ' a > {
105
- fn finish ( & mut self , indent : usize , indent_amount : usize ) {
138
+ fn finish ( & mut self , indent : usize , config : & Config ) {
106
139
self . bufs . current_buf . push ( '\n' ) ;
107
- self . bufs . indent_current ( indent, indent_amount ) ;
140
+ self . bufs . indent_current ( indent, config ) ;
108
141
self . bufs . flush_indent_buf ( ) ;
109
142
}
110
143
}
@@ -124,35 +157,111 @@ impl<'a> fmt::Display for ColorLevel<'a> {
124
157
}
125
158
}
126
159
127
- fn indent_block ( block : & mut String , buf : & mut String , indent : usize , indent_amount : usize ) {
128
- let lines: Vec < _ > = block. lines ( ) . collect ( ) ;
160
+ fn indent_block_with_lines ( lines : & [ & str ] , buf : & mut String , indent : usize , indent_amount : usize ) {
129
161
let indent_spaces = indent * indent_amount;
130
- buf. reserve ( block. len ( ) + ( lines. len ( ) * indent_spaces) ) ;
131
- let indent_str = String :: from ( " " ) . repeat ( indent_spaces) ;
132
- for line in lines {
133
- buf. push_str ( & indent_str) ;
162
+ if lines. len ( ) == 0 {
163
+ return ;
164
+ } else if indent_spaces == 0 {
165
+ for line in lines {
166
+ buf. push_str ( line) ;
167
+ buf. push ( '\n' ) ;
168
+ }
169
+ return ;
170
+ }
171
+ let mut s = String :: with_capacity ( indent_spaces) ;
172
+
173
+ // instead of using all spaces to indent, draw a vertical line at every indent level
174
+ // up until the last indent
175
+ for i in 0 ..( indent_spaces - indent_amount) {
176
+ if i % indent_amount == 0 {
177
+ s. push_str ( LINE_VERT ) ;
178
+ } else {
179
+ s. push ( ' ' ) ;
180
+ }
181
+ }
182
+
183
+ // draw branch
184
+ buf. push_str ( & s) ;
185
+ buf. push_str ( LINE_BRANCH ) ;
186
+
187
+ // add `indent_amount - 1` horizontal lines before the span/event
188
+ for _ in 0 ..( indent_amount - 1 ) {
189
+ buf. push_str ( LINE_HORIZ ) ;
190
+ }
191
+ buf. push_str ( & lines[ 0 ] ) ;
192
+ buf. push ( '\n' ) ;
193
+
194
+ // add the rest of the indentation, since we don't want to draw horizontal lines
195
+ // for subsequent lines
196
+ for i in 0 ..indent_amount {
197
+ if i % indent_amount == 0 {
198
+ s. push_str ( LINE_VERT ) ;
199
+ } else {
200
+ s. push ( ' ' ) ;
201
+ }
202
+ }
203
+
204
+ // add all of the actual content, with each line preceded by the indent string
205
+ for line in & lines[ 1 ..] {
206
+ buf. push_str ( & s) ;
134
207
buf. push_str ( line) ;
135
208
buf. push ( '\n' ) ;
136
209
}
137
210
}
138
211
212
+ fn indent_block (
213
+ block : & mut String ,
214
+ buf : & mut String ,
215
+ indent : usize ,
216
+ indent_amount : usize ,
217
+ indent_lines : bool ,
218
+ ) {
219
+ let lines: Vec < & str > = block. lines ( ) . collect ( ) ;
220
+ let indent_spaces = indent * indent_amount;
221
+ buf. reserve ( block. len ( ) + ( lines. len ( ) * indent_spaces) ) ;
222
+ if indent_lines {
223
+ indent_block_with_lines ( & lines, buf, indent, indent_amount) ;
224
+ } else {
225
+ let indent_str = String :: from ( " " ) . repeat ( indent_spaces) ;
226
+ for line in lines {
227
+ buf. push_str ( & indent_str) ;
228
+ buf. push_str ( line) ;
229
+ buf. push ( '\n' ) ;
230
+ }
231
+ }
232
+ }
233
+
139
234
impl HierarchicalLayer {
140
235
pub fn new ( indent_amount : usize ) -> Self {
141
236
let ansi = atty:: is ( atty:: Stream :: Stdout ) ;
142
- Self {
237
+ let config = Config {
238
+ ansi,
143
239
indent_amount,
240
+ ..Default :: default ( )
241
+ } ;
242
+ Self {
144
243
stdout : io:: stdout ( ) ,
145
- ansi,
146
244
bufs : Mutex :: new ( Buffers :: new ( ) ) ,
245
+ config,
147
246
}
148
247
}
149
248
150
249
pub fn with_ansi ( self , ansi : bool ) -> Self {
151
- Self { ansi, ..self }
250
+ Self {
251
+ config : self . config . with_ansi ( ansi) ,
252
+ ..self
253
+ }
254
+ }
255
+
256
+ pub fn with_indent_lines ( self , indent_lines : bool ) -> Self {
257
+ Self {
258
+ config : self . config . with_indent_lines ( indent_lines) ,
259
+ ..self
260
+ }
152
261
}
153
262
154
263
fn styled ( & self , style : Style , text : impl AsRef < str > ) -> String {
155
- if self . ansi {
264
+ if self . config . ansi {
156
265
style. paint ( text. as_ref ( ) ) . to_string ( )
157
266
} else {
158
267
text. as_ref ( ) . to_string ( )
@@ -200,7 +309,7 @@ where
200
309
let bufs = & mut * guard;
201
310
let mut current_buf = & mut bufs. current_buf ;
202
311
203
- let indent = ctx. scope ( ) . count ( ) - 1 ;
312
+ let indent = ctx. scope ( ) . count ( ) . saturating_sub ( 1 ) ;
204
313
205
314
write ! (
206
315
current_buf,
@@ -223,7 +332,7 @@ where
223
332
)
224
333
. unwrap ( ) ;
225
334
226
- bufs. indent_current ( indent, self . indent_amount ) ;
335
+ bufs. indent_current ( indent, & self . config ) ;
227
336
bufs. flush_indent_buf ( ) ;
228
337
bufs. flush_current_buf ( self . stdout . lock ( ) ) ;
229
338
}
@@ -271,7 +380,7 @@ where
271
380
. expect ( "Unable to write to buffer" ) ;
272
381
}
273
382
let level = event. metadata ( ) . level ( ) ;
274
- let level = if self . ansi {
383
+ let level = if self . config . ansi {
275
384
ColorLevel ( level) . to_string ( )
276
385
} else {
277
386
level. to_string ( )
@@ -282,9 +391,9 @@ where
282
391
bufs : & mut bufs,
283
392
} ;
284
393
event. record ( & mut visitor) ;
285
- visitor. finish ( indent, self . indent_amount ) ;
394
+ visitor. finish ( indent, & self . config ) ;
286
395
bufs. flush_current_buf ( self . stdout . lock ( ) ) ;
287
396
}
288
397
289
- fn on_close ( & self , _id : Id , _ctx : Context < S > ) { }
398
+ fn on_exit ( & self , _id : & Id , _ctx : Context < S > ) { }
290
399
}
0 commit comments