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 {
3815for _in 0 ..n{
3916 f. write_char ( c) ?;
@@ -72,14 +49,18 @@ impl fmt::Display for DisplayList {
7249lineno : 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_widthas f64 ) . log10 ( ) . floor ( ) as usize ) +1
63+ } ;
8364let inline_marks_width =self . body . iter ( ) . fold ( 0 , |max, line|match line{
8465DisplayLine :: Source { inline_marks, ..} => cmp:: max ( inline_marks. len ( ) , max) ,
8566 _ => max,
@@ -97,22 +78,38 @@ impl fmt::Display for DisplayList {
9778
9879impl DisplayList {
9980const 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]
10188fn format_annotation_type (
102- & self ,
10389annotation_type : & DisplayAnnotationType ,
10490f : & mut fmt:: Formatter < ' _ > ,
10591) -> fmt:: Result {
10692match 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 ) ,
11298DisplayAnnotationType :: 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+
116113fn get_annotation_style ( & self , annotation_type : & DisplayAnnotationType ) ->Box < dyn Style > {
117114self . stylesheet . get_style ( match annotation_type{
118115DisplayAnnotationType :: Error =>StyleClass :: Error ,
@@ -148,37 +145,38 @@ impl DisplayList {
148145f : & mut fmt:: Formatter < ' _ > ,
149146) -> fmt:: Result {
150147let 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
165154if continuation{
166- let indent = formatted_type. len ( ) +2 ;
167- format_repeat_char ( ' ' , indent, f) ?;
155+ format_repeat_char ( ' ' , formatted_len +2 , f) ?;
168156return self . format_label ( & annotation. label , f) ;
169157}
170- if formatted_type . is_empty ( ) {
158+ if formatted_len == 0 {
171159self . 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+ ) ?;
174173if !is_annotation_empty ( annotation) {
175174if in_source{
176- color. paint (
177- & DisplayFn :: new ( |f|{
175+ color. paint_fn (
176+ Box :: new ( |f|{
178177 f. write_str ( ": " ) ?;
179178self . 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
236239if !is_annotation_empty ( & annotation) {
237240 f. write_char ( ' ' ) ?;
238- color. paint (
239- & DisplayFn :: new ( |f|{
241+ color. paint_fn (
242+ Box :: new ( |f|{
240243self . format_annotation (
241244 annotation,
242245 annotation_part ==& DisplayAnnotationPart :: LabelContinuation ,
243246true ,
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]
266260fn format_raw_line (
267261& self ,
@@ -337,10 +331,22 @@ impl DisplayList {
337331} =>{
338332let lineno_color =self . stylesheet . get_style ( StyleClass :: LineNo ) ;
339333if 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 {
377383format_repeat_char ( ' ' , inline_marks_width - inline_marks. len ( ) , f) ?;
378384for markin 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}