1
- use std:: {
2
- cmp,
3
- fmt:: { self , Display , Write } ,
4
- iter:: once,
5
- } ;
6
-
7
1
pub mod style;
8
2
9
- use self :: style:: { Style , StyleClass , Stylesheet } ;
3
+ use self :: style:: Stylesheet ;
10
4
11
5
#[ cfg( feature = "color" ) ]
12
6
use crate :: stylesheets:: color:: AnsiTermStylesheet ;
13
- use crate :: { display_list:: * , stylesheets:: no_color:: NoColorStylesheet } ;
14
-
15
- fn format_repeat_char ( c : char , n : usize , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
16
- for _ in 0 ..n {
17
- f. write_char ( c) ?;
18
- }
19
- Ok ( ( ) )
20
- }
21
-
22
- #[ inline]
23
- fn is_annotation_empty ( annotation : & Annotation < ' _ > ) -> bool {
24
- annotation
25
- . label
26
- . iter ( )
27
- . all ( |fragment| fragment. content . is_empty ( ) )
28
- }
7
+ use crate :: stylesheets:: no_color:: NoColorStylesheet ;
29
8
30
9
#[ cfg( feature = "color" ) ]
31
10
#[ inline]
@@ -42,415 +21,3 @@ pub fn get_term_style(color: bool) -> Box<dyn Stylesheet> {
42
21
pub fn get_term_style ( _color : bool ) -> Box < dyn Stylesheet > {
43
22
Box :: new ( NoColorStylesheet )
44
23
}
45
-
46
- impl < ' a > fmt:: Display for DisplayList < ' a > {
47
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
48
- let lineno_width = self . body . iter ( ) . fold ( 0 , |max, line| match line {
49
- DisplayLine :: Source {
50
- lineno : Some ( lineno) ,
51
- ..
52
- } => {
53
- // The largest line is the largest width.
54
- cmp:: max ( * lineno, max)
55
- }
56
- _ => max,
57
- } ) ;
58
- let lineno_width = if lineno_width == 0 {
59
- lineno_width
60
- } else if self . anonymized_line_numbers {
61
- Self :: ANONYMIZED_LINE_NUM . len ( )
62
- } else {
63
- ( ( lineno_width as f64 ) . log10 ( ) . floor ( ) as usize ) + 1
64
- } ;
65
- let inline_marks_width = self . body . iter ( ) . fold ( 0 , |max, line| match line {
66
- DisplayLine :: Source { inline_marks, .. } => cmp:: max ( inline_marks. len ( ) , max) ,
67
- _ => max,
68
- } ) ;
69
-
70
- for ( i, line) in self . body . iter ( ) . enumerate ( ) {
71
- self . format_line ( line, lineno_width, inline_marks_width, f) ?;
72
- if i + 1 < self . body . len ( ) {
73
- f. write_char ( '\n' ) ?;
74
- }
75
- }
76
- Ok ( ( ) )
77
- }
78
- }
79
-
80
- impl < ' a > DisplayList < ' a > {
81
- const ANONYMIZED_LINE_NUM : & ' static str = "LL" ;
82
- const ERROR_TXT : & ' static str = "error" ;
83
- const HELP_TXT : & ' static str = "help" ;
84
- const INFO_TXT : & ' static str = "info" ;
85
- const NOTE_TXT : & ' static str = "note" ;
86
- const WARNING_TXT : & ' static str = "warning" ;
87
-
88
- #[ inline]
89
- fn format_annotation_type (
90
- annotation_type : & DisplayAnnotationType ,
91
- f : & mut fmt:: Formatter < ' _ > ,
92
- ) -> fmt:: Result {
93
- match annotation_type {
94
- DisplayAnnotationType :: Error => f. write_str ( Self :: ERROR_TXT ) ,
95
- DisplayAnnotationType :: Help => f. write_str ( Self :: HELP_TXT ) ,
96
- DisplayAnnotationType :: Info => f. write_str ( Self :: INFO_TXT ) ,
97
- DisplayAnnotationType :: Note => f. write_str ( Self :: NOTE_TXT ) ,
98
- DisplayAnnotationType :: Warning => f. write_str ( Self :: WARNING_TXT ) ,
99
- DisplayAnnotationType :: None => Ok ( ( ) ) ,
100
- }
101
- }
102
-
103
- fn annotation_type_len ( annotation_type : & DisplayAnnotationType ) -> usize {
104
- match annotation_type {
105
- DisplayAnnotationType :: Error => Self :: ERROR_TXT . len ( ) ,
106
- DisplayAnnotationType :: Help => Self :: HELP_TXT . len ( ) ,
107
- DisplayAnnotationType :: Info => Self :: INFO_TXT . len ( ) ,
108
- DisplayAnnotationType :: Note => Self :: NOTE_TXT . len ( ) ,
109
- DisplayAnnotationType :: Warning => Self :: WARNING_TXT . len ( ) ,
110
- DisplayAnnotationType :: None => 0 ,
111
- }
112
- }
113
-
114
- fn get_annotation_style ( & self , annotation_type : & DisplayAnnotationType ) -> Box < dyn Style > {
115
- self . stylesheet . get_style ( match annotation_type {
116
- DisplayAnnotationType :: Error => StyleClass :: Error ,
117
- DisplayAnnotationType :: Warning => StyleClass :: Warning ,
118
- DisplayAnnotationType :: Info => StyleClass :: Info ,
119
- DisplayAnnotationType :: Note => StyleClass :: Note ,
120
- DisplayAnnotationType :: Help => StyleClass :: Help ,
121
- DisplayAnnotationType :: None => StyleClass :: None ,
122
- } )
123
- }
124
-
125
- fn format_label (
126
- & self ,
127
- label : & [ DisplayTextFragment < ' _ > ] ,
128
- f : & mut fmt:: Formatter < ' _ > ,
129
- ) -> fmt:: Result {
130
- let emphasis_style = self . stylesheet . get_style ( StyleClass :: Emphasis ) ;
131
-
132
- for fragment in label {
133
- match fragment. style {
134
- DisplayTextStyle :: Regular => fragment. content . fmt ( f) ?,
135
- DisplayTextStyle :: Emphasis => emphasis_style. paint ( fragment. content , f) ?,
136
- }
137
- }
138
- Ok ( ( ) )
139
- }
140
-
141
- fn format_annotation (
142
- & self ,
143
- annotation : & Annotation < ' _ > ,
144
- continuation : bool ,
145
- in_source : bool ,
146
- f : & mut fmt:: Formatter < ' _ > ,
147
- ) -> fmt:: Result {
148
- let color = self . get_annotation_style ( & annotation. annotation_type ) ;
149
- let formatted_len = if let Some ( id) = & annotation. id {
150
- 2 + id. len ( ) + Self :: annotation_type_len ( & annotation. annotation_type )
151
- } else {
152
- Self :: annotation_type_len ( & annotation. annotation_type )
153
- } ;
154
-
155
- if continuation {
156
- format_repeat_char ( ' ' , formatted_len + 2 , f) ?;
157
- return self . format_label ( & annotation. label , f) ;
158
- }
159
- if formatted_len == 0 {
160
- self . format_label ( & annotation. label , f)
161
- } else {
162
- color. paint_fn (
163
- Box :: new ( |f| {
164
- Self :: format_annotation_type ( & annotation. annotation_type , f) ?;
165
- if let Some ( id) = & annotation. id {
166
- f. write_char ( '[' ) ?;
167
- f. write_str ( id) ?;
168
- f. write_char ( ']' ) ?;
169
- }
170
- Ok ( ( ) )
171
- } ) ,
172
- f,
173
- ) ?;
174
- if !is_annotation_empty ( annotation) {
175
- if in_source {
176
- color. paint_fn (
177
- Box :: new ( |f| {
178
- f. write_str ( ": " ) ?;
179
- self . format_label ( & annotation. label , f)
180
- } ) ,
181
- f,
182
- ) ?;
183
- } else {
184
- f. write_str ( ": " ) ?;
185
- self . format_label ( & annotation. label , f) ?;
186
- }
187
- }
188
- Ok ( ( ) )
189
- }
190
- }
191
-
192
- #[ inline]
193
- fn format_source_line (
194
- & self ,
195
- line : & DisplaySourceLine < ' _ > ,
196
- f : & mut fmt:: Formatter < ' _ > ,
197
- ) -> fmt:: Result {
198
- match line {
199
- DisplaySourceLine :: Empty => Ok ( ( ) ) ,
200
- DisplaySourceLine :: Content { text, .. } => {
201
- f. write_char ( ' ' ) ?;
202
- if let Some ( margin) = self . margin {
203
- let line_len = text. chars ( ) . count ( ) ;
204
- let mut left = margin. left ( line_len) ;
205
- let right = margin. right ( line_len) ;
206
-
207
- if margin. was_cut_left ( ) {
208
- // We have stripped some code/whitespace from the beginning, make it clear.
209
- "..." . fmt ( f) ?;
210
- left += 3 ;
211
- }
212
-
213
- // On long lines, we strip the source line, accounting for unicode.
214
- let mut taken = 0 ;
215
- let cut_right = if margin. was_cut_right ( line_len) {
216
- taken += 3 ;
217
- true
218
- } else {
219
- false
220
- } ;
221
- // Specifies that it will end on the next character, so it will return
222
- // until the next one to the final condition.
223
- let mut ended = false ;
224
- let range = text
225
- . char_indices ( )
226
- . skip ( left)
227
- // Complete char iterator with final character
228
- . chain ( once ( ( text. len ( ) , '\0' ) ) )
229
- // Take until the next one to the final condition
230
- . take_while ( |( _, ch) | {
231
- // Fast return to iterate over final byte position
232
- if ended {
233
- return false ;
234
- }
235
- // Make sure that the trimming on the right will fall within the terminal width.
236
- // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is.
237
- // For now, just accept that sometimes the code line will be longer than desired.
238
- taken += unicode_width:: UnicodeWidthChar :: width ( * ch) . unwrap_or ( 1 ) ;
239
- if taken > right - left {
240
- ended = true ;
241
- }
242
- true
243
- } )
244
- // Reduce to start and end byte position
245
- . fold ( ( None , 0 ) , |acc, ( i, _) | {
246
- if acc. 0 . is_some ( ) {
247
- ( acc. 0 , i)
248
- } else {
249
- ( Some ( i) , i)
250
- }
251
- } ) ;
252
-
253
- // Format text with margins
254
- text[ range. 0 . expect ( "One character at line" ) ..range. 1 ] . fmt ( f) ?;
255
-
256
- if cut_right {
257
- // We have stripped some code after the right-most span end, make it clear we did so.
258
- "..." . fmt ( f) ?;
259
- }
260
- Ok ( ( ) )
261
- } else {
262
- text. fmt ( f)
263
- }
264
- }
265
- DisplaySourceLine :: Annotation {
266
- range,
267
- annotation,
268
- annotation_type,
269
- annotation_part,
270
- } => {
271
- let indent_char = match annotation_part {
272
- DisplayAnnotationPart :: Standalone => ' ' ,
273
- DisplayAnnotationPart :: LabelContinuation => ' ' ,
274
- DisplayAnnotationPart :: Consequitive => ' ' ,
275
- DisplayAnnotationPart :: MultilineStart => '_' ,
276
- DisplayAnnotationPart :: MultilineEnd => '_' ,
277
- } ;
278
- let mark = match annotation_type {
279
- DisplayAnnotationType :: Error => '^' ,
280
- DisplayAnnotationType :: Warning => '-' ,
281
- DisplayAnnotationType :: Info => '-' ,
282
- DisplayAnnotationType :: Note => '-' ,
283
- DisplayAnnotationType :: Help => '-' ,
284
- DisplayAnnotationType :: None => ' ' ,
285
- } ;
286
- let color = self . get_annotation_style ( annotation_type) ;
287
- let indent_length = match annotation_part {
288
- DisplayAnnotationPart :: LabelContinuation => range. 1 ,
289
- DisplayAnnotationPart :: Consequitive => range. 1 ,
290
- _ => range. 0 ,
291
- } ;
292
-
293
- color. paint_fn (
294
- Box :: new ( |f| {
295
- format_repeat_char ( indent_char, indent_length + 1 , f) ?;
296
- format_repeat_char ( mark, range. 1 - indent_length, f)
297
- } ) ,
298
- f,
299
- ) ?;
300
-
301
- if !is_annotation_empty ( annotation) {
302
- f. write_char ( ' ' ) ?;
303
- color. paint_fn (
304
- Box :: new ( |f| {
305
- self . format_annotation (
306
- annotation,
307
- annotation_part == & DisplayAnnotationPart :: LabelContinuation ,
308
- true ,
309
- f,
310
- )
311
- } ) ,
312
- f,
313
- ) ?;
314
- }
315
-
316
- Ok ( ( ) )
317
- }
318
- }
319
- }
320
-
321
- #[ inline]
322
- fn format_raw_line (
323
- & self ,
324
- line : & DisplayRawLine < ' _ > ,
325
- lineno_width : usize ,
326
- f : & mut fmt:: Formatter < ' _ > ,
327
- ) -> fmt:: Result {
328
- match line {
329
- DisplayRawLine :: Origin {
330
- path,
331
- pos,
332
- header_type,
333
- } => {
334
- let header_sigil = match header_type {
335
- DisplayHeaderType :: Initial => "-->" ,
336
- DisplayHeaderType :: Continuation => ":::" ,
337
- } ;
338
- let lineno_color = self . stylesheet . get_style ( StyleClass :: LineNo ) ;
339
-
340
- if let Some ( ( col, row) ) = pos {
341
- format_repeat_char ( ' ' , lineno_width, f) ?;
342
- lineno_color. paint ( header_sigil, f) ?;
343
- f. write_char ( ' ' ) ?;
344
- path. fmt ( f) ?;
345
- f. write_char ( ':' ) ?;
346
- col. fmt ( f) ?;
347
- f. write_char ( ':' ) ?;
348
- row. fmt ( f)
349
- } else {
350
- format_repeat_char ( ' ' , lineno_width, f) ?;
351
- lineno_color. paint ( header_sigil, f) ?;
352
- f. write_char ( ' ' ) ?;
353
- path. fmt ( f)
354
- }
355
- }
356
- DisplayRawLine :: Annotation {
357
- annotation,
358
- source_aligned,
359
- continuation,
360
- } => {
361
- if * source_aligned {
362
- if * continuation {
363
- format_repeat_char ( ' ' , lineno_width + 3 , f) ?;
364
- } else {
365
- let lineno_color = self . stylesheet . get_style ( StyleClass :: LineNo ) ;
366
- format_repeat_char ( ' ' , lineno_width, f) ?;
367
- f. write_char ( ' ' ) ?;
368
- lineno_color. paint ( "=" , f) ?;
369
- f. write_char ( ' ' ) ?;
370
- }
371
- }
372
- self . format_annotation ( annotation, * continuation, false , f)
373
- }
374
- }
375
- }
376
-
377
- #[ inline]
378
- fn format_line (
379
- & self ,
380
- dl : & DisplayLine < ' _ > ,
381
- lineno_width : usize ,
382
- inline_marks_width : usize ,
383
- f : & mut fmt:: Formatter < ' _ > ,
384
- ) -> fmt:: Result {
385
- match dl {
386
- DisplayLine :: Source {
387
- lineno,
388
- inline_marks,
389
- line,
390
- } => {
391
- let lineno_color = self . stylesheet . get_style ( StyleClass :: LineNo ) ;
392
- if self . anonymized_line_numbers && lineno. is_some ( ) {
393
- lineno_color. paint_fn (
394
- Box :: new ( |f| {
395
- f. write_str ( Self :: ANONYMIZED_LINE_NUM ) ?;
396
- f. write_str ( " |" )
397
- } ) ,
398
- f,
399
- ) ?;
400
- } else {
401
- lineno_color. paint_fn (
402
- Box :: new ( |f| {
403
- match lineno {
404
- Some ( n) => write ! ( f, "{:>width$}" , n, width = lineno_width) ,
405
- None => format_repeat_char ( ' ' , lineno_width, f) ,
406
- } ?;
407
- f. write_str ( " |" )
408
- } ) ,
409
- f,
410
- ) ?;
411
- }
412
- if * line != DisplaySourceLine :: Empty {
413
- if !inline_marks. is_empty ( ) || 0 < inline_marks_width {
414
- f. write_char ( ' ' ) ?;
415
- self . format_inline_marks ( inline_marks, inline_marks_width, f) ?;
416
- }
417
- self . format_source_line ( line, f) ?;
418
- } else if !inline_marks. is_empty ( ) {
419
- f. write_char ( ' ' ) ?;
420
- self . format_inline_marks ( inline_marks, inline_marks_width, f) ?;
421
- }
422
- Ok ( ( ) )
423
- }
424
- DisplayLine :: Fold { inline_marks } => {
425
- f. write_str ( "..." ) ?;
426
- if !inline_marks. is_empty ( ) || 0 < inline_marks_width {
427
- format_repeat_char ( ' ' , lineno_width, f) ?;
428
- self . format_inline_marks ( inline_marks, inline_marks_width, f) ?;
429
- }
430
- Ok ( ( ) )
431
- }
432
- DisplayLine :: Raw ( line) => self . format_raw_line ( line, lineno_width, f) ,
433
- }
434
- }
435
-
436
- fn format_inline_marks (
437
- & self ,
438
- inline_marks : & [ DisplayMark ] ,
439
- inline_marks_width : usize ,
440
- f : & mut fmt:: Formatter < ' _ > ,
441
- ) -> fmt:: Result {
442
- format_repeat_char ( ' ' , inline_marks_width - inline_marks. len ( ) , f) ?;
443
- for mark in inline_marks {
444
- self . get_annotation_style ( & mark. annotation_type ) . paint_fn (
445
- Box :: new ( |f| {
446
- f. write_char ( match mark. mark_type {
447
- DisplayMarkType :: AnnotationThrough => '|' ,
448
- DisplayMarkType :: AnnotationStart => '/' ,
449
- } )
450
- } ) ,
451
- f,
452
- ) ?;
453
- }
454
- Ok ( ( ) )
455
- }
456
- }
0 commit comments