1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
//! The renderer for [`Snippet`]s
//!
//! # Example
//! ```
//! use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet};
//! let snippet = Snippet {
//! title: Some(Annotation {
//! label: Some("mismatched types"),
//! id: None,
//! annotation_type: AnnotationType::Error,
//! }),
//! footer: vec![],
//! slices: vec![
//! Slice {
//! source: "Foo",
//! line_start: 51,
//! origin: Some("src/format.rs"),
//! fold: false,
//! annotations: vec![],
//! },
//! Slice {
//! source: "Faa",
//! line_start: 129,
//! origin: Some("src/display.rs"),
//! fold: false,
//! annotations: vec![],
//! },
//! ],
//! };
//!
//! let renderer = Renderer::styled();
//! println!("{}", renderer.render(snippet));
mod display_list;
mod margin;
pub(crate) mod stylesheet;
use crate::snippet::Snippet;
pub use anstyle::*;
use display_list::DisplayList;
pub use margin::Margin;
use std::fmt::Display;
use stylesheet::Stylesheet;
/// A renderer for [`Snippet`]s
#[derive(Clone)]
pub struct Renderer {
anonymized_line_numbers: bool,
margin: Option<Margin>,
stylesheet: Stylesheet,
}
impl Renderer {
/// No terminal styling
pub const fn plain() -> Self {
Self {
anonymized_line_numbers: false,
margin: None,
stylesheet: Stylesheet::plain(),
}
}
/// Default terminal styling
pub const fn styled() -> Self {
Self {
stylesheet: Stylesheet {
error: AnsiColor::BrightRed.on_default().effects(Effects::BOLD),
warning: AnsiColor::BrightYellow.on_default().effects(Effects::BOLD),
info: AnsiColor::BrightBlue.on_default().effects(Effects::BOLD),
note: Style::new().effects(Effects::BOLD),
help: AnsiColor::BrightCyan.on_default().effects(Effects::BOLD),
line_no: AnsiColor::BrightBlue.on_default().effects(Effects::BOLD),
emphasis: Style::new().effects(Effects::BOLD),
none: Style::new(),
},
..Self::plain()
}
}
/// Anonymize line numbers
///
/// This enables (or disables) line number anonymization. When enabled, line numbers are replaced
/// with `LL`.
///
/// # Example
///
/// ```text
/// --> $DIR/whitespace-trimming.rs:4:193
/// |
/// LL | ... let _: () = 42;
/// | ^^ expected (), found integer
/// |
/// ```
pub const fn anonymized_line_numbers(mut self, anonymized_line_numbers: bool) -> Self {
self.anonymized_line_numbers = anonymized_line_numbers;
self
}
/// Set the margin for the output
///
/// This controls the various margins of the output.
///
/// # Example
///
/// ```text
/// error: expected type, found `22`
/// --> examples/footer.rs:29:25
/// |
/// 26 | ... annotations: vec![SourceAnnotation {
/// | ---------------- info: while parsing this struct
/// ...
/// 29 | ... range: <22, 25>,
/// | ^^
/// |
/// ```
pub const fn margin(mut self, margin: Option<Margin>) -> Self {
self.margin = margin;
self
}
/// Set the output style for `error`
pub const fn error(mut self, style: Style) -> Self {
self.stylesheet.error = style;
self
}
/// Set the output style for `warning`
pub const fn warning(mut self, style: Style) -> Self {
self.stylesheet.warning = style;
self
}
/// Set the output style for `info`
pub const fn info(mut self, style: Style) -> Self {
self.stylesheet.info = style;
self
}
/// Set the output style for `note`
pub const fn note(mut self, style: Style) -> Self {
self.stylesheet.note = style;
self
}
/// Set the output style for `help`
pub const fn help(mut self, style: Style) -> Self {
self.stylesheet.help = style;
self
}
/// Set the output style for line numbers
pub const fn line_no(mut self, style: Style) -> Self {
self.stylesheet.line_no = style;
self
}
/// Set the output style for emphasis
pub const fn emphasis(mut self, style: Style) -> Self {
self.stylesheet.emphasis = style;
self
}
/// Set the output style for none
pub const fn none(mut self, style: Style) -> Self {
self.stylesheet.none = style;
self
}
/// Render a snippet into a `Display`able object
pub fn render<'a>(&'a self, snippet: Snippet<'a>) -> impl Display + 'a {
DisplayList::new(
snippet,
&self.stylesheet,
self.anonymized_line_numbers,
self.margin,
)
}
}