1
- //! `DisplayList` is an intermittent structure which converts the Snippet structure
2
- //! into a list of lines that resemble the final output.
3
- //!
4
- //! # Example:
5
- //!
6
- //! ```
7
- //! use annotate_snippets::snippet::{Snippet, Slice, Annotation, TitleAnnotation, AnnotationType};
8
- //! use annotate_snippets::display_list::{DisplayList, DisplayLine, DisplayAnnotationType,
9
- //! DisplaySnippetType};
10
- //!
11
- //! let snippet = Snippet {
12
- //! slice: Slice {
13
- //! source: "id: Option<>,\nlabel: Option<String>".to_string(),
14
- //! line_start: 145,
15
- //! origin: Some("src/display_list.rs".to_string())
16
- //! },
17
- //! title: Some(TitleAnnotation {
18
- //! id: Some("E0061".to_string()),
19
- //! label: Some("this function takes 1 parameter but 0 parameters were supplied".to_string()),
20
- //! annotation_type: AnnotationType::Error,
21
- //! }),
22
- //! fold: Some(false),
23
- //! annotations: vec![
24
- //! Annotation {
25
- //! label: "expected 1 parameter".to_string(),
26
- //! annotation_type: AnnotationType::Error,
27
- //! range: (4, 12)
28
- //! }
29
- //! ]
30
- //! };
31
- //! assert_eq!(DisplayList::from(snippet).body, vec![
32
- //! DisplayLine::Description {
33
- //! snippet_type: DisplaySnippetType::Error,
34
- //! id: Some("E0061".to_string()),
35
- //! label: "this function takes 1 parameter but 0 parameters were supplied".to_string(),
36
- //! },
37
- //! DisplayLine::Origin {
38
- //! path: "src/display_list.rs".to_string(),
39
- //! row: 145,
40
- //! col: 4,
41
- //! },
42
- //! DisplayLine::EmptySource,
43
- //! DisplayLine::Source {
44
- //! lineno: 145,
45
- //! inline_marks: vec![],
46
- //! content: "id: Option<>,".to_string(),
47
- //! range: (0, 14)
48
- //! },
49
- //! DisplayLine::Annotation {
50
- //! label: Some("expected 1 parameter".to_string()),
51
- //! range: (4, 12),
52
- //! inline_marks: vec![],
53
- //! annotation_type: DisplayAnnotationType::Error,
54
- //! },
55
- //! DisplayLine::Source {
56
- //! lineno: 146,
57
- //! inline_marks: vec![],
58
- //! content: "label: Option<String>".to_string(),
59
- //! range: (15, 37)
60
- //! },
61
- //! DisplayLine::EmptySource
62
- //! ]);
63
- //! ```
64
- use snippet:: { AnnotationType , Snippet } ;
1
+ use snippet:: { AnnotationType , Slice , Snippet , TitleAnnotation } ;
65
2
66
3
pub struct DisplayList {
67
4
pub body : Vec < DisplayLine > ,
@@ -76,8 +13,8 @@ pub enum DisplayLine {
76
13
} ,
77
14
Origin {
78
15
path : String ,
79
- row : usize ,
80
- col : usize ,
16
+ pos : Option < ( usize , usize ) > ,
17
+ header_type : DisplayHeaderType ,
81
18
} ,
82
19
EmptySource ,
83
20
Source {
@@ -117,25 +54,47 @@ pub enum DisplaySnippetType {
117
54
Warning ,
118
55
}
119
56
57
+ #[ derive( Debug , Clone , PartialEq ) ]
58
+ pub enum DisplayHeaderType {
59
+ Initial ,
60
+ Continuation ,
61
+ }
62
+
120
63
// Formatting
121
64
122
- fn format_header ( snippet : & Snippet , body : & [ DisplayLine ] ) -> Vec < DisplayLine > {
123
- let mut header = vec ! [ ] ;
65
+ fn format_title ( annotation : & TitleAnnotation ) -> DisplayLine {
66
+ let label = annotation. label . clone ( ) . unwrap_or ( "" . to_string ( ) ) ;
67
+ DisplayLine :: Description {
68
+ snippet_type : DisplaySnippetType :: from ( annotation. annotation_type ) ,
69
+ id : annotation. id . clone ( ) ,
70
+ label,
71
+ }
72
+ }
73
+
74
+ fn format_slice ( slice : & Slice , is_first : bool ) -> Vec < DisplayLine > {
75
+ let mut body = format_body ( slice) ;
76
+ let mut result = vec ! [ ] ;
124
77
125
- if let Some ( ref annotation) = snippet. title {
126
- let label = annotation. label . clone ( ) . unwrap_or ( "" . to_string ( ) ) ;
127
- header. push ( DisplayLine :: Description {
128
- snippet_type : DisplaySnippetType :: from ( annotation. annotation_type ) ,
129
- id : annotation. id . clone ( ) ,
130
- label,
131
- } )
78
+ let header = format_header ( slice, & body, is_first) ;
79
+ if let Some ( header) = header {
80
+ result. push ( header) ;
132
81
}
82
+ result. append ( & mut body) ;
83
+ result
84
+ }
133
85
134
- let main_annotation = snippet. annotations . get ( 0 ) ;
86
+ fn format_header ( slice : & Slice , body : & [ DisplayLine ] , is_first : bool ) -> Option < DisplayLine > {
87
+ let main_annotation = slice. annotations . get ( 0 ) ;
88
+
89
+ let display_header = if is_first {
90
+ DisplayHeaderType :: Initial
91
+ } else {
92
+ DisplayHeaderType :: Continuation
93
+ } ;
135
94
136
95
if let Some ( annotation) = main_annotation {
137
96
let mut col = 1 ;
138
- let mut row = snippet . slice . line_start ;
97
+ let mut row = slice. line_start ;
139
98
140
99
for idx in 0 ..body. len ( ) {
141
100
if let DisplayLine :: Source { range, .. } = body[ idx] {
@@ -146,15 +105,23 @@ fn format_header(snippet: &Snippet, body: &[DisplayLine]) -> Vec<DisplayLine> {
146
105
row += 1 ;
147
106
}
148
107
}
149
- if let Some ( ref path) = snippet. slice . origin {
150
- header. push ( DisplayLine :: Origin {
108
+ if let Some ( ref path) = slice. origin {
109
+ return Some ( DisplayLine :: Origin {
110
+ path : path. to_string ( ) ,
111
+ pos : Some ( ( row, col) ) ,
112
+ header_type : display_header,
113
+ } ) ;
114
+ }
115
+ } else {
116
+ if let Some ( ref path) = slice. origin {
117
+ return Some ( DisplayLine :: Origin {
151
118
path : path. to_string ( ) ,
152
- row ,
153
- col ,
119
+ pos : None ,
120
+ header_type : display_header ,
154
121
} ) ;
155
122
}
156
123
}
157
- header
124
+ None
158
125
}
159
126
160
127
fn fold_body ( body : & [ DisplayLine ] ) -> Vec < DisplayLine > {
@@ -204,14 +171,14 @@ fn fold_body(body: &[DisplayLine]) -> Vec<DisplayLine> {
204
171
return new_body;
205
172
}
206
173
207
- fn format_body ( snippet : & Snippet ) -> Vec < DisplayLine > {
174
+ fn format_body ( slice : & Slice ) -> Vec < DisplayLine > {
208
175
let mut body = vec ! [ ] ;
209
176
210
- let mut current_line = snippet . slice . line_start ;
177
+ let mut current_line = slice. line_start ;
211
178
let mut current_index = 0 ;
212
179
let mut line_index_ranges = vec ! [ ] ;
213
180
214
- for line in snippet . slice . source . lines ( ) {
181
+ for line in slice. source . lines ( ) {
215
182
let line_length = line. chars ( ) . count ( ) + 1 ;
216
183
let line_range = ( current_index, current_index + line_length) ;
217
184
body. push ( DisplayLine :: Source {
@@ -226,7 +193,7 @@ fn format_body(snippet: &Snippet) -> Vec<DisplayLine> {
226
193
}
227
194
228
195
let mut annotation_line_count = 0 ;
229
- let mut annotations = snippet . annotations . clone ( ) ;
196
+ let mut annotations = slice . annotations . clone ( ) ;
230
197
for idx in 0 ..body. len ( ) {
231
198
let ( line_start, line_end) = line_index_ranges[ idx] ;
232
199
annotations. drain_filter ( |annotation| {
@@ -309,7 +276,7 @@ fn format_body(snippet: &Snippet) -> Vec<DisplayLine> {
309
276
} ) ;
310
277
}
311
278
312
- if snippet . fold . unwrap_or ( false ) {
279
+ if slice . fold {
313
280
body = fold_body ( & body) ;
314
281
}
315
282
@@ -322,12 +289,18 @@ fn format_body(snippet: &Snippet) -> Vec<DisplayLine> {
322
289
323
290
impl From < Snippet > for DisplayList {
324
291
fn from ( snippet : Snippet ) -> Self {
325
- let body = format_body ( & snippet) ;
326
- let header = format_header ( & snippet, & body) ;
292
+ let mut body = vec ! [ ] ;
293
+ if let Some ( annotation) = snippet. title {
294
+ body. push ( format_title ( & annotation) ) ;
295
+ }
327
296
328
- Self {
329
- body : vec ! [ & header[ ..] , & body[ ..] ] . concat ( ) ,
297
+ let mut slice_idx = 0 ;
298
+ for slice in snippet. slices {
299
+ body. append ( & mut format_slice ( & slice, slice_idx == 0 ) ) ;
300
+ slice_idx += 1 ;
330
301
}
302
+
303
+ Self { body }
331
304
}
332
305
}
333
306
0 commit comments