1 use std::fmt; 2 3 use crate::formatter::{get_term_style, style::Stylesheet}; 4 5 /// List of lines to be displayed. 6 pub struct DisplayList<'a> { 7 pub body: Vec<DisplayLine<'a>>, 8 pub stylesheet: Box<dyn Stylesheet>, 9 pub anonymized_line_numbers: bool, 10 } 11 12 impl<'a> From<Vec<DisplayLine<'a>>> for DisplayList<'a> { from(body: Vec<DisplayLine<'a>>) -> DisplayList<'a>13 fn from(body: Vec<DisplayLine<'a>>) -> DisplayList<'a> { 14 Self { 15 body, 16 anonymized_line_numbers: false, 17 stylesheet: get_term_style(false), 18 } 19 } 20 } 21 22 impl<'a> PartialEq for DisplayList<'a> { eq(&self, other: &Self) -> bool23 fn eq(&self, other: &Self) -> bool { 24 self.body == other.body && self.anonymized_line_numbers == other.anonymized_line_numbers 25 } 26 } 27 28 impl<'a> fmt::Debug for DisplayList<'a> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 30 f.debug_struct("DisplayList") 31 .field("body", &self.body) 32 .field("anonymized_line_numbers", &self.anonymized_line_numbers) 33 .finish() 34 } 35 } 36 37 #[derive(Debug, Default, Copy, Clone)] 38 pub struct FormatOptions { 39 pub color: bool, 40 pub anonymized_line_numbers: bool, 41 } 42 43 /// Inline annotation which can be used in either Raw or Source line. 44 #[derive(Debug, PartialEq)] 45 pub struct Annotation<'a> { 46 pub annotation_type: DisplayAnnotationType, 47 pub id: Option<&'a str>, 48 pub label: Vec<DisplayTextFragment<'a>>, 49 } 50 51 /// A single line used in `DisplayList`. 52 #[derive(Debug, PartialEq)] 53 pub enum DisplayLine<'a> { 54 /// A line with `lineno` portion of the slice. 55 Source { 56 lineno: Option<usize>, 57 inline_marks: Vec<DisplayMark>, 58 line: DisplaySourceLine<'a>, 59 }, 60 61 /// A line indicating a folded part of the slice. 62 Fold { inline_marks: Vec<DisplayMark> }, 63 64 /// A line which is displayed outside of slices. 65 Raw(DisplayRawLine<'a>), 66 } 67 68 /// A source line. 69 #[derive(Debug, PartialEq)] 70 pub enum DisplaySourceLine<'a> { 71 /// A line with the content of the Slice. 72 Content { 73 text: &'a str, 74 range: (usize, usize), // meta information for annotation placement. 75 }, 76 77 /// An annotation line which is displayed in context of the slice. 78 Annotation { 79 annotation: Annotation<'a>, 80 range: (usize, usize), 81 annotation_type: DisplayAnnotationType, 82 annotation_part: DisplayAnnotationPart, 83 }, 84 85 /// An empty source line. 86 Empty, 87 } 88 89 /// Raw line - a line which does not have the `lineno` part and is not considered 90 /// a part of the snippet. 91 #[derive(Debug, PartialEq)] 92 pub enum DisplayRawLine<'a> { 93 /// A line which provides information about the location of the given 94 /// slice in the project structure. 95 Origin { 96 path: &'a str, 97 pos: Option<(usize, usize)>, 98 header_type: DisplayHeaderType, 99 }, 100 101 /// An annotation line which is not part of any snippet. 102 Annotation { 103 annotation: Annotation<'a>, 104 105 /// If set to `true`, the annotation will be aligned to the 106 /// lineno delimiter of the snippet. 107 source_aligned: bool, 108 /// If set to `true`, only the label of the `Annotation` will be 109 /// displayed. It allows for a multiline annotation to be aligned 110 /// without displaing the meta information (`type` and `id`) to be 111 /// displayed on each line. 112 continuation: bool, 113 }, 114 } 115 116 /// An inline text fragment which any label is composed of. 117 #[derive(Debug, PartialEq)] 118 pub struct DisplayTextFragment<'a> { 119 pub content: &'a str, 120 pub style: DisplayTextStyle, 121 } 122 123 /// A style for the `DisplayTextFragment` which can be visually formatted. 124 /// 125 /// This information may be used to emphasis parts of the label. 126 #[derive(Debug, Clone, Copy, PartialEq)] 127 pub enum DisplayTextStyle { 128 Regular, 129 Emphasis, 130 } 131 132 /// An indicator of what part of the annotation a given `Annotation` is. 133 #[derive(Debug, Clone, PartialEq)] 134 pub enum DisplayAnnotationPart { 135 /// A standalone, single-line annotation. 136 Standalone, 137 /// A continuation of a multi-line label of an annotation. 138 LabelContinuation, 139 /// A consequitive annotation in case multiple annotations annotate a single line. 140 Consequitive, 141 /// A line starting a multiline annotation. 142 MultilineStart, 143 /// A line ending a multiline annotation. 144 MultilineEnd, 145 } 146 147 /// A visual mark used in `inline_marks` field of the `DisplaySourceLine`. 148 #[derive(Debug, Clone, PartialEq)] 149 pub struct DisplayMark { 150 pub mark_type: DisplayMarkType, 151 pub annotation_type: DisplayAnnotationType, 152 } 153 154 /// A type of the `DisplayMark`. 155 #[derive(Debug, Clone, PartialEq)] 156 pub enum DisplayMarkType { 157 /// A mark indicating a multiline annotation going through the current line. 158 AnnotationThrough, 159 /// A mark indicating a multiline annotation starting on the given line. 160 AnnotationStart, 161 } 162 163 /// A type of the `Annotation` which may impact the sigils, style or text displayed. 164 /// 165 /// There are several ways in which the `DisplayListFormatter` uses this information 166 /// when formatting the `DisplayList`: 167 /// 168 /// * An annotation may display the name of the type like `error` or `info`. 169 /// * An underline for `Error` may be `^^^` while for `Warning` it coule be `---`. 170 /// * `ColorStylesheet` may use different colors for different annotations. 171 #[derive(Debug, Clone, PartialEq)] 172 pub enum DisplayAnnotationType { 173 None, 174 Error, 175 Warning, 176 Info, 177 Note, 178 Help, 179 } 180 181 /// Information whether the header is the initial one or a consequitive one 182 /// for multi-slice cases. 183 // TODO: private 184 #[derive(Debug, Clone, PartialEq)] 185 pub enum DisplayHeaderType { 186 /// Initial header is the first header in the snippet. 187 Initial, 188 189 /// Continuation marks all headers of following slices in the snippet. 190 Continuation, 191 } 192