@@ -5,8 +5,7 @@ use crate::snippet;
5
5
fn format_label ( label : Option < & str > , style : Option < DisplayTextStyle > ) -> Vec < DisplayTextFragment > {
6
6
let mut result = vec ! [ ] ;
7
7
if let Some ( label) = label {
8
- let elements: Vec < & str > = label. split ( "__" ) . collect ( ) ;
9
- for ( idx, element) in elements. iter ( ) . enumerate ( ) {
8
+ for ( idx, element) in label. split ( "__" ) . enumerate ( ) {
10
9
let element_style = match style {
11
10
Some ( s) => s,
12
11
None => {
@@ -26,22 +25,22 @@ fn format_label(label: Option<&str>, style: Option<DisplayTextStyle>) -> Vec<Dis
26
25
result
27
26
}
28
27
29
- fn format_title ( annotation : & snippet:: Annotation ) -> DisplayLine {
30
- let label = annotation. label . clone ( ) . unwrap_or_default ( ) ;
28
+ fn format_title ( annotation : snippet:: Annotation ) -> DisplayLine {
29
+ let label = annotation. label . unwrap_or_default ( ) ;
31
30
DisplayLine :: Raw ( DisplayRawLine :: Annotation {
32
31
annotation : Annotation {
33
32
annotation_type : DisplayAnnotationType :: from ( annotation. annotation_type ) ,
34
- id : annotation. id . clone ( ) ,
33
+ id : annotation. id ,
35
34
label : format_label ( Some ( & label) , Some ( DisplayTextStyle :: Emphasis ) ) ,
36
35
} ,
37
36
source_aligned : false ,
38
37
continuation : false ,
39
38
} )
40
39
}
41
40
42
- fn format_annotation ( annotation : & snippet:: Annotation ) -> Vec < DisplayLine > {
41
+ fn format_annotation ( annotation : snippet:: Annotation ) -> Vec < DisplayLine > {
43
42
let mut result = vec ! [ ] ;
44
- let label = annotation. label . clone ( ) . unwrap_or_default ( ) ;
43
+ let label = annotation. label . unwrap_or_default ( ) ;
45
44
for ( i, line) in label. lines ( ) . enumerate ( ) {
46
45
result. push ( DisplayLine :: Raw ( DisplayRawLine :: Annotation {
47
46
annotation : Annotation {
@@ -56,11 +55,14 @@ fn format_annotation(annotation: &snippet::Annotation) -> Vec<DisplayLine> {
56
55
result
57
56
}
58
57
59
- fn format_slice ( slice : & snippet:: Slice , is_first : bool , has_footer : bool ) -> Vec < DisplayLine > {
58
+ fn format_slice ( mut slice : snippet:: Slice , is_first : bool , has_footer : bool ) -> Vec < DisplayLine > {
59
+ let main_range = slice. annotations . get ( 0 ) . map ( |x| x. range . 0 ) ;
60
+ let row = slice. line_start ;
61
+ let origin = slice. origin . take ( ) ;
60
62
let mut body = format_body ( slice, has_footer) ;
63
+ let header = format_header ( origin, main_range, row, & body, is_first) ;
61
64
let mut result = vec ! [ ] ;
62
65
63
- let header = format_header ( slice, & body, is_first) ;
64
66
if let Some ( header) = header {
65
67
result. push ( header) ;
66
68
}
@@ -69,46 +71,45 @@ fn format_slice(slice: &snippet::Slice, is_first: bool, has_footer: bool) -> Vec
69
71
}
70
72
71
73
fn format_header (
72
- slice : & snippet:: Slice ,
74
+ origin : Option < String > ,
75
+ main_range : Option < usize > ,
76
+ mut row : usize ,
73
77
body : & [ DisplayLine ] ,
74
78
is_first : bool ,
75
79
) -> Option < DisplayLine > {
76
- let main_annotation = slice. annotations . get ( 0 ) ;
77
-
78
80
let display_header = if is_first {
79
81
DisplayHeaderType :: Initial
80
82
} else {
81
83
DisplayHeaderType :: Continuation
82
84
} ;
83
85
84
- if let Some ( annotation ) = main_annotation {
86
+ if let Some ( main_range ) = main_range {
85
87
let mut col = 1 ;
86
- let mut row = slice. line_start ;
87
88
88
- for item in body. iter ( ) {
89
+ for item in body {
89
90
if let DisplayLine :: Source {
90
91
line : DisplaySourceLine :: Content { range, .. } ,
91
92
..
92
93
} = item
93
94
{
94
- if annotation . range . 0 >= range. 0 && annotation . range . 0 <= range. 1 {
95
- col = annotation . range . 0 - range. 0 + 1 ;
95
+ if main_range >= range. 0 && main_range <= range. 1 {
96
+ col = main_range - range. 0 + 1 ;
96
97
break ;
97
98
}
98
99
row += 1 ;
99
100
}
100
101
}
101
- if let Some ( ref path) = slice . origin {
102
+ if let Some ( path) = origin {
102
103
return Some ( DisplayLine :: Raw ( DisplayRawLine :: Origin {
103
- path : path . to_string ( ) ,
104
+ path,
104
105
pos : Some ( ( row, col) ) ,
105
106
header_type : display_header,
106
107
} ) ) ;
107
108
}
108
109
}
109
- if let Some ( ref path) = slice . origin {
110
+ if let Some ( path) = origin {
110
111
return Some ( DisplayLine :: Raw ( DisplayRawLine :: Origin {
111
- path : path . to_string ( ) ,
112
+ path,
112
113
pos : None ,
113
114
header_type : display_header,
114
115
} ) ) ;
@@ -175,15 +176,30 @@ fn fold_body(body: &[DisplayLine]) -> Vec<DisplayLine> {
175
176
new_body
176
177
}
177
178
178
- fn format_body ( slice : & snippet:: Slice , has_footer : bool ) -> Vec < DisplayLine > {
179
- let mut body = vec ! [ ] ;
179
+ fn format_body ( slice : snippet:: Slice , has_footer : bool ) -> Vec < DisplayLine > {
180
+ let source_len = slice. source . chars ( ) . count ( ) ;
181
+ if let Some ( bigger) = slice. annotations . iter ( ) . find_map ( |x| {
182
+ if source_len < x. range . 1 {
183
+ Some ( x. range )
184
+ } else {
185
+ None
186
+ }
187
+ } ) {
188
+ panic ! (
189
+ "SourceAnnotation range `{:?}` is bigger than source length `{}`" ,
190
+ bigger, source_len
191
+ )
192
+ }
180
193
194
+ let mut body = vec ! [ ] ;
181
195
let mut current_line = slice. line_start ;
182
196
let mut current_index = 0 ;
183
197
let mut line_index_ranges = vec ! [ ] ;
184
198
185
- for line in slice. source . lines ( ) {
186
- let line_length = line. chars ( ) . count ( ) + 1 ;
199
+ let lines = slice. source . lines ( ) ;
200
+ let lines_len = lines. clone ( ) . count ( ) ;
201
+ for ( i, line) in lines. enumerate ( ) {
202
+ let line_length = line. chars ( ) . count ( ) ;
187
203
let line_range = ( current_index, current_index + line_length) ;
188
204
body. push ( DisplayLine :: Source {
189
205
lineno : Some ( current_line) ,
@@ -195,13 +211,14 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
195
211
} ) ;
196
212
line_index_ranges. push ( line_range) ;
197
213
current_line += 1 ;
198
- current_index += line_length + 1 ;
214
+ if i + 1 < lines_len {
215
+ current_index += line_length + 1 ;
216
+ }
199
217
}
200
218
201
219
let mut annotation_line_count = 0 ;
202
- let mut annotations = slice. annotations . clone ( ) ;
203
- for idx in 0 ..body. len ( ) {
204
- let ( line_start, line_end) = line_index_ranges[ idx] ;
220
+ let mut annotations = slice. annotations ;
221
+ for ( idx, ( line_start, line_end) ) in line_index_ranges. into_iter ( ) . enumerate ( ) {
205
222
// It would be nice to use filter_drain here once it's stable.
206
223
annotations = annotations
207
224
. into_iter ( )
@@ -214,7 +231,10 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
214
231
} ;
215
232
match annotation. range {
216
233
( start, _) if start > line_end => true ,
217
- ( start, end) if start >= line_start && end <= line_end => {
234
+ ( start, end)
235
+ if start >= line_start && end <= line_end
236
+ || start == line_end && end - start <= 1 =>
237
+ {
218
238
let range = ( start - line_start, end - line_start) ;
219
239
body. insert (
220
240
body_idx + 1 ,
@@ -305,6 +325,7 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
305
325
) ,
306
326
} ) ;
307
327
}
328
+
308
329
let range = ( end - line_start, end - line_start + 1 ) ;
309
330
body. insert (
310
331
body_idx + 1 ,
@@ -368,22 +389,24 @@ fn format_body(slice: &snippet::Slice, has_footer: bool) -> Vec<DisplayLine> {
368
389
}
369
390
370
391
impl From < snippet:: Snippet > for DisplayList {
371
- fn from ( snippet : snippet:: Snippet ) -> Self {
392
+ fn from (
393
+ snippet:: Snippet {
394
+ title,
395
+ footer,
396
+ slices,
397
+ } : snippet:: Snippet ,
398
+ ) -> Self {
372
399
let mut body = vec ! [ ] ;
373
- if let Some ( annotation) = snippet . title {
374
- body. push ( format_title ( & annotation) ) ;
400
+ if let Some ( annotation) = title {
401
+ body. push ( format_title ( annotation) ) ;
375
402
}
376
403
377
- for ( idx, slice) in snippet. slices . iter ( ) . enumerate ( ) {
378
- body. append ( & mut format_slice (
379
- & slice,
380
- idx == 0 ,
381
- !snippet. footer . is_empty ( ) ,
382
- ) ) ;
404
+ for ( idx, slice) in slices. into_iter ( ) . enumerate ( ) {
405
+ body. append ( & mut format_slice ( slice, idx == 0 , !footer. is_empty ( ) ) ) ;
383
406
}
384
407
385
- for annotation in snippet . footer {
386
- body. append ( & mut format_annotation ( & annotation) ) ;
408
+ for annotation in footer {
409
+ body. append ( & mut format_annotation ( annotation) ) ;
387
410
}
388
411
389
412
Self { body }
0 commit comments