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 } ;
652
663pub struct DisplayList {
674 pub body : Vec < DisplayLine > ,
@@ -76,8 +13,8 @@ pub enum DisplayLine {
7613 } ,
7714 Origin {
7815 path : String ,
79- row : usize ,
80- col : usize ,
16+ pos : Option < ( usize , usize ) > ,
17+ header_type : DisplayHeaderType ,
8118 } ,
8219 EmptySource ,
8320 Source {
@@ -117,25 +54,47 @@ pub enum DisplaySnippetType {
11754 Warning ,
11855}
11956
57+ #[ derive( Debug , Clone , PartialEq ) ]
58+ pub enum DisplayHeaderType {
59+ Initial ,
60+ Continuation ,
61+ }
62+
12063// Formatting
12164
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 ! [ ] ;
12477
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) ;
13281 }
82+ result. append ( & mut body) ;
83+ result
84+ }
13385
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+ } ;
13594
13695 if let Some ( annotation) = main_annotation {
13796 let mut col = 1 ;
138- let mut row = snippet . slice . line_start ;
97+ let mut row = slice. line_start ;
13998
14099 for idx in 0 ..body. len ( ) {
141100 if let DisplayLine :: Source { range, .. } = body[ idx] {
@@ -146,15 +105,23 @@ fn format_header(snippet: &Snippet, body: &[DisplayLine]) -> Vec<DisplayLine> {
146105 row += 1 ;
147106 }
148107 }
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 {
151118 path : path. to_string ( ) ,
152- row ,
153- col ,
119+ pos : None ,
120+ header_type : display_header ,
154121 } ) ;
155122 }
156123 }
157- header
124+ None
158125}
159126
160127fn fold_body ( body : & [ DisplayLine ] ) -> Vec < DisplayLine > {
@@ -204,14 +171,14 @@ fn fold_body(body: &[DisplayLine]) -> Vec<DisplayLine> {
204171 return new_body;
205172}
206173
207- fn format_body ( snippet : & Snippet ) -> Vec < DisplayLine > {
174+ fn format_body ( slice : & Slice ) -> Vec < DisplayLine > {
208175 let mut body = vec ! [ ] ;
209176
210- let mut current_line = snippet . slice . line_start ;
177+ let mut current_line = slice. line_start ;
211178 let mut current_index = 0 ;
212179 let mut line_index_ranges = vec ! [ ] ;
213180
214- for line in snippet . slice . source . lines ( ) {
181+ for line in slice. source . lines ( ) {
215182 let line_length = line. chars ( ) . count ( ) + 1 ;
216183 let line_range = ( current_index, current_index + line_length) ;
217184 body. push ( DisplayLine :: Source {
@@ -226,7 +193,7 @@ fn format_body(snippet: &Snippet) -> Vec<DisplayLine> {
226193 }
227194
228195 let mut annotation_line_count = 0 ;
229- let mut annotations = snippet . annotations . clone ( ) ;
196+ let mut annotations = slice . annotations . clone ( ) ;
230197 for idx in 0 ..body. len ( ) {
231198 let ( line_start, line_end) = line_index_ranges[ idx] ;
232199 annotations. drain_filter ( |annotation| {
@@ -309,7 +276,7 @@ fn format_body(snippet: &Snippet) -> Vec<DisplayLine> {
309276 } ) ;
310277 }
311278
312- if snippet . fold . unwrap_or ( false ) {
279+ if slice . fold {
313280 body = fold_body ( & body) ;
314281 }
315282
@@ -322,12 +289,18 @@ fn format_body(snippet: &Snippet) -> Vec<DisplayLine> {
322289
323290impl From < Snippet > for DisplayList {
324291 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+ }
327296
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 ;
330301 }
302+
303+ Self { body }
331304 }
332305}
333306
0 commit comments