11use std:: {
2- cell:: Cell ,
32 cmp,
4- fmt:: { self , Display , Formatter , Write } ,
3+ fmt:: { self , Display , Write } ,
54} ;
65
76pub mod style;
@@ -12,28 +11,6 @@ use self::style::{Style, StyleClass, Stylesheet};
1211use crate :: stylesheets:: color:: AnsiTermStylesheet ;
1312use crate :: { display_list:: * , stylesheets:: no_color:: NoColorStylesheet } ;
1413
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-
3714fn format_repeat_char ( c : char , n : usize , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
3815 for _ in 0 ..n {
3916 f. write_char ( c) ?;
@@ -72,14 +49,18 @@ impl fmt::Display for DisplayList {
7249 lineno : Some ( lineno) ,
7350 ..
7451 } => {
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)
8054 }
8155 _ => max,
8256 } ) ;
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+ } ;
8364 let inline_marks_width = self . body . iter ( ) . fold ( 0 , |max, line| match line {
8465 DisplayLine :: Source { inline_marks, .. } => cmp:: max ( inline_marks. len ( ) , max) ,
8566 _ => max,
@@ -97,22 +78,38 @@ impl fmt::Display for DisplayList {
9778
9879impl DisplayList {
9980 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" ;
10086
87+ #[ inline]
10188 fn format_annotation_type (
102- & self ,
10389 annotation_type : & DisplayAnnotationType ,
10490 f : & mut fmt:: Formatter < ' _ > ,
10591 ) -> fmt:: Result {
10692 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 ) ,
11298 DisplayAnnotationType :: None => Ok ( ( ) ) ,
11399 }
114100 }
115101
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+
116113 fn get_annotation_style ( & self , annotation_type : & DisplayAnnotationType ) -> Box < dyn Style > {
117114 self . stylesheet . get_style ( match annotation_type {
118115 DisplayAnnotationType :: Error => StyleClass :: Error ,
@@ -148,37 +145,38 @@ impl DisplayList {
148145 f : & mut fmt:: Formatter < ' _ > ,
149146 ) -> fmt:: Result {
150147 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 )
160150 } else {
161- DisplayFn :: new ( |f| self . format_annotation_type ( & annotation. annotation_type , f) )
162- . to_string ( )
151+ Self :: annotation_type_len ( & annotation. annotation_type )
163152 } ;
164153
165154 if continuation {
166- let indent = formatted_type. len ( ) + 2 ;
167- format_repeat_char ( ' ' , indent, f) ?;
155+ format_repeat_char ( ' ' , formatted_len + 2 , f) ?;
168156 return self . format_label ( & annotation. label , f) ;
169157 }
170- if formatted_type . is_empty ( ) {
158+ if formatted_len == 0 {
171159 self . format_label ( & annotation. label , f)
172160 } 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+ ) ?;
174173 if !is_annotation_empty ( annotation) {
175174 if in_source {
176- color. paint (
177- & DisplayFn :: new ( |f| {
175+ color. paint_fn (
176+ Box :: new ( |f| {
178177 f. write_str ( ": " ) ?;
179178 self . format_label ( & annotation. label , f)
180- } )
181- . to_string ( ) ,
179+ } ) ,
182180 f,
183181 ) ?;
184182 } else {
@@ -230,21 +228,25 @@ impl DisplayList {
230228 _ => range. 0 ,
231229 } ;
232230
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+ ) ?;
235238
236239 if !is_annotation_empty ( & annotation) {
237240 f. write_char ( ' ' ) ?;
238- color. paint (
239- & DisplayFn :: new ( |f| {
241+ color. paint_fn (
242+ Box :: new ( |f| {
240243 self . format_annotation (
241244 annotation,
242245 annotation_part == & DisplayAnnotationPart :: LabelContinuation ,
243246 true ,
244247 f,
245248 )
246- } )
247- . to_string ( ) ,
249+ } ) ,
248250 f,
249251 ) ?;
250252 }
@@ -254,14 +256,6 @@ impl DisplayList {
254256 }
255257 }
256258
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-
265259 #[ inline]
266260 fn format_raw_line (
267261 & self ,
@@ -337,10 +331,22 @@ impl DisplayList {
337331 } => {
338332 let lineno_color = self . stylesheet . get_style ( StyleClass :: LineNo ) ;
339333 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+ ) ?;
341341 } 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+ } ) ,
344350 f,
345351 ) ?;
346352 }
@@ -376,11 +382,13 @@ impl DisplayList {
376382 ) -> fmt:: Result {
377383 format_repeat_char ( ' ' , inline_marks_width - inline_marks. len ( ) , f) ?;
378384 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+ } ) ,
384392 f,
385393 ) ?;
386394 }
0 commit comments