1
1
use std:: {
2
- cell:: Cell ,
3
2
cmp,
4
- fmt:: { self , Display , Formatter , Write } ,
3
+ fmt:: { self , Display , Write } ,
5
4
} ;
6
5
7
6
pub mod style;
@@ -12,28 +11,6 @@ use self::style::{Style, StyleClass, Stylesheet};
12
11
use crate :: stylesheets:: color:: AnsiTermStylesheet ;
13
12
use crate :: { display_list:: * , stylesheets:: no_color:: NoColorStylesheet } ;
14
13
15
- pub struct DisplayFn < F : FnOnce ( & mut Formatter < ' _ > ) -> fmt:: Result > ( std:: cell:: Cell < Option < F > > ) ;
16
-
17
- impl < F : FnOnce ( & mut Formatter < ' _ > ) -> fmt:: Result > DisplayFn < F > {
18
- pub fn new ( f : F ) -> Self {
19
- Self ( Cell :: new ( Some ( f) ) )
20
- }
21
- }
22
-
23
- impl < F : FnOnce ( & mut Formatter < ' _ > ) -> fmt:: Result > Display for DisplayFn < F > {
24
- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
25
- self . 0 . take ( ) . ok_or ( fmt:: Error ) . and_then ( |cl| cl ( f) )
26
- }
27
- }
28
-
29
- fn repeat_char ( c : char , n : usize ) -> String {
30
- let mut s = String :: with_capacity ( c. len_utf8 ( ) * n) ;
31
- for _ in 0 ..n {
32
- s. push ( c) ;
33
- }
34
- s
35
- }
36
-
37
14
fn format_repeat_char ( c : char , n : usize , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
38
15
for _ in 0 ..n {
39
16
f. write_char ( c) ?;
@@ -72,14 +49,18 @@ impl fmt::Display for DisplayList {
72
49
lineno : Some ( lineno) ,
73
50
..
74
51
} => {
75
- if self . anonymized_line_numbers {
76
- Self :: ANONYMIZED_LINE_NUM . len ( )
77
- } else {
78
- cmp:: max ( lineno. to_string ( ) . len ( ) , max)
79
- }
52
+ // The largest line is the largest width.
53
+ cmp:: max ( * lineno, max)
80
54
}
81
55
_ => max,
82
56
} ) ;
57
+ let lineno_width = if lineno_width == 0 {
58
+ lineno_width
59
+ } else if self . anonymized_line_numbers {
60
+ Self :: ANONYMIZED_LINE_NUM . len ( )
61
+ } else {
62
+ ( ( lineno_width as f64 ) . log10 ( ) . floor ( ) as usize ) + 1
63
+ } ;
83
64
let inline_marks_width = self . body . iter ( ) . fold ( 0 , |max, line| match line {
84
65
DisplayLine :: Source { inline_marks, .. } => cmp:: max ( inline_marks. len ( ) , max) ,
85
66
_ => max,
@@ -97,22 +78,38 @@ impl fmt::Display for DisplayList {
97
78
98
79
impl DisplayList {
99
80
const ANONYMIZED_LINE_NUM : & ' static str = "LL" ;
81
+ const ERROR_TXT : & ' static str = "error" ;
82
+ const HELP_TXT : & ' static str = "help" ;
83
+ const INFO_TXT : & ' static str = "info" ;
84
+ const NOTE_TXT : & ' static str = "note" ;
85
+ const WARNING_TXT : & ' static str = "warning" ;
100
86
87
+ #[ inline]
101
88
fn format_annotation_type (
102
- & self ,
103
89
annotation_type : & DisplayAnnotationType ,
104
90
f : & mut fmt:: Formatter < ' _ > ,
105
91
) -> fmt:: Result {
106
92
match annotation_type {
107
- DisplayAnnotationType :: Error => f. write_str ( "error" ) ,
108
- DisplayAnnotationType :: Warning => f. write_str ( "warning" ) ,
109
- DisplayAnnotationType :: Info => f. write_str ( "info" ) ,
110
- DisplayAnnotationType :: Note => f. write_str ( "note" ) ,
111
- DisplayAnnotationType :: Help => f. write_str ( "help" ) ,
93
+ DisplayAnnotationType :: Error => f. write_str ( Self :: ERROR_TXT ) ,
94
+ DisplayAnnotationType :: Help => f. write_str ( Self :: HELP_TXT ) ,
95
+ DisplayAnnotationType :: Info => f. write_str ( Self :: INFO_TXT ) ,
96
+ DisplayAnnotationType :: Note => f. write_str ( Self :: NOTE_TXT ) ,
97
+ DisplayAnnotationType :: Warning => f. write_str ( Self :: WARNING_TXT ) ,
112
98
DisplayAnnotationType :: None => Ok ( ( ) ) ,
113
99
}
114
100
}
115
101
102
+ fn annotation_type_len ( annotation_type : & DisplayAnnotationType ) -> usize {
103
+ match annotation_type {
104
+ DisplayAnnotationType :: Error => Self :: ERROR_TXT . len ( ) ,
105
+ DisplayAnnotationType :: Help => Self :: HELP_TXT . len ( ) ,
106
+ DisplayAnnotationType :: Info => Self :: INFO_TXT . len ( ) ,
107
+ DisplayAnnotationType :: Note => Self :: NOTE_TXT . len ( ) ,
108
+ DisplayAnnotationType :: Warning => Self :: WARNING_TXT . len ( ) ,
109
+ DisplayAnnotationType :: None => 0 ,
110
+ }
111
+ }
112
+
116
113
fn get_annotation_style ( & self , annotation_type : & DisplayAnnotationType ) -> Box < dyn Style > {
117
114
self . stylesheet . get_style ( match annotation_type {
118
115
DisplayAnnotationType :: Error => StyleClass :: Error ,
@@ -148,37 +145,38 @@ impl DisplayList {
148
145
f : & mut fmt:: Formatter < ' _ > ,
149
146
) -> fmt:: Result {
150
147
let color = self . get_annotation_style ( & annotation. annotation_type ) ;
151
-
152
- let formatted_type = if let Some ( id) = & annotation. id {
153
- DisplayFn :: new ( |f| {
154
- self . format_annotation_type ( & annotation. annotation_type , f) ?;
155
- f. write_char ( '[' ) ?;
156
- f. write_str ( id) ?;
157
- f. write_char ( ']' )
158
- } )
159
- . to_string ( )
148
+ let formatted_len = if let Some ( id) = & annotation. id {
149
+ 2 + id. len ( ) + Self :: annotation_type_len ( & annotation. annotation_type )
160
150
} else {
161
- DisplayFn :: new ( |f| self . format_annotation_type ( & annotation. annotation_type , f) )
162
- . to_string ( )
151
+ Self :: annotation_type_len ( & annotation. annotation_type )
163
152
} ;
164
153
165
154
if continuation {
166
- let indent = formatted_type. len ( ) + 2 ;
167
- format_repeat_char ( ' ' , indent, f) ?;
155
+ format_repeat_char ( ' ' , formatted_len + 2 , f) ?;
168
156
return self . format_label ( & annotation. label , f) ;
169
157
}
170
- if formatted_type . is_empty ( ) {
158
+ if formatted_len == 0 {
171
159
self . format_label ( & annotation. label , f)
172
160
} else {
173
- color. paint ( & formatted_type, f) ?;
161
+ color. paint_fn (
162
+ Box :: new ( |f| {
163
+ Self :: format_annotation_type ( & annotation. annotation_type , f) ?;
164
+ if let Some ( id) = & annotation. id {
165
+ f. write_char ( '[' ) ?;
166
+ f. write_str ( id) ?;
167
+ f. write_char ( ']' ) ?;
168
+ }
169
+ Ok ( ( ) )
170
+ } ) ,
171
+ f,
172
+ ) ?;
174
173
if !is_annotation_empty ( annotation) {
175
174
if in_source {
176
- color. paint (
177
- & DisplayFn :: new ( |f| {
175
+ color. paint_fn (
176
+ Box :: new ( |f| {
178
177
f. write_str ( ": " ) ?;
179
178
self . format_label ( & annotation. label , f)
180
- } )
181
- . to_string ( ) ,
179
+ } ) ,
182
180
f,
183
181
) ?;
184
182
} else {
@@ -230,21 +228,25 @@ impl DisplayList {
230
228
_ => range. 0 ,
231
229
} ;
232
230
233
- color. paint ( & repeat_char ( indent_char, indent_length + 1 ) , f) ?;
234
- color. paint ( & repeat_char ( mark, range. 1 - indent_length) , f) ?;
231
+ color. paint_fn (
232
+ Box :: new ( |f| {
233
+ format_repeat_char ( indent_char, indent_length + 1 , f) ?;
234
+ format_repeat_char ( mark, range. 1 - indent_length, f)
235
+ } ) ,
236
+ f,
237
+ ) ?;
235
238
236
239
if !is_annotation_empty ( & annotation) {
237
240
f. write_char ( ' ' ) ?;
238
- color. paint (
239
- & DisplayFn :: new ( |f| {
241
+ color. paint_fn (
242
+ Box :: new ( |f| {
240
243
self . format_annotation (
241
244
annotation,
242
245
annotation_part == & DisplayAnnotationPart :: LabelContinuation ,
243
246
true ,
244
247
f,
245
248
)
246
- } )
247
- . to_string ( ) ,
249
+ } ) ,
248
250
f,
249
251
) ?;
250
252
}
@@ -254,14 +256,6 @@ impl DisplayList {
254
256
}
255
257
}
256
258
257
- #[ inline]
258
- fn format_lineno ( & self , lineno : Option < usize > , lineno_width : usize ) -> String {
259
- match lineno {
260
- Some ( n) => format ! ( "{:>width$}" , n, width = lineno_width) ,
261
- None => repeat_char ( ' ' , lineno_width) ,
262
- }
263
- }
264
-
265
259
#[ inline]
266
260
fn format_raw_line (
267
261
& self ,
@@ -337,10 +331,22 @@ impl DisplayList {
337
331
} => {
338
332
let lineno_color = self . stylesheet . get_style ( StyleClass :: LineNo ) ;
339
333
if self . anonymized_line_numbers && lineno. is_some ( ) {
340
- lineno_color. paint ( & format ! ( "{} |" , Self :: ANONYMIZED_LINE_NUM ) , f) ?;
334
+ lineno_color. paint_fn (
335
+ Box :: new ( |f| {
336
+ f. write_str ( Self :: ANONYMIZED_LINE_NUM ) ?;
337
+ f. write_str ( " |" )
338
+ } ) ,
339
+ f,
340
+ ) ?;
341
341
} else {
342
- lineno_color. paint (
343
- & format ! ( "{} |" , self . format_lineno( * lineno, lineno_width) ) ,
342
+ lineno_color. paint_fn (
343
+ Box :: new ( |f| {
344
+ match lineno {
345
+ Some ( n) => write ! ( f, "{:>width$}" , n, width = lineno_width) ,
346
+ None => format_repeat_char ( ' ' , lineno_width, f) ,
347
+ } ?;
348
+ f. write_str ( " |" )
349
+ } ) ,
344
350
f,
345
351
) ?;
346
352
}
@@ -376,11 +382,13 @@ impl DisplayList {
376
382
) -> fmt:: Result {
377
383
format_repeat_char ( ' ' , inline_marks_width - inline_marks. len ( ) , f) ?;
378
384
for mark in inline_marks {
379
- self . get_annotation_style ( & mark. annotation_type ) . paint (
380
- match mark. mark_type {
381
- DisplayMarkType :: AnnotationThrough => "|" ,
382
- DisplayMarkType :: AnnotationStart => "/" ,
383
- } ,
385
+ self . get_annotation_style ( & mark. annotation_type ) . paint_fn (
386
+ Box :: new ( |f| {
387
+ f. write_char ( match mark. mark_type {
388
+ DisplayMarkType :: AnnotationThrough => '|' ,
389
+ DisplayMarkType :: AnnotationStart => '/' ,
390
+ } )
391
+ } ) ,
384
392
f,
385
393
) ?;
386
394
}
0 commit comments