Skip to main content

miette/handlers/graphical/
handler.rs

1//! The [`GraphicalReportHandler`] type and its builder API.
2//!
3//! This module holds the handler's theme, terminal width, and link style. The
4//! actual rendering lives in the sibling modules (`report`, `snippet`, …).
5
6use std::io::{self, IsTerminal};
7
8use crate::GraphicalTheme;
9
10#[derive(Debug, Clone)]
11pub struct GraphicalReportHandler {
12    /// How to render links.
13    ///
14    /// Default: [`LinkStyle::Link`]
15    pub(crate) links: LinkStyle,
16    /// Terminal width to wrap at.
17    ///
18    /// Default: `400`
19    pub(crate) termwidth: usize,
20    /// How to style reports
21    pub(crate) theme: GraphicalTheme,
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25#[expect(clippy::redundant_pub_crate, reason = "prevents accidental glob re-export")]
26pub(crate) enum LinkStyle {
27    Link,
28    Text,
29}
30
31impl GraphicalReportHandler {
32    /// Create a new `GraphicalReportHandler` with the default
33    /// [`GraphicalTheme`]. This will use both unicode characters and colors.
34    #[must_use]
35    pub fn new() -> Self {
36        let is_terminal = io::stdout().is_terminal() && io::stderr().is_terminal();
37        Self {
38            links: if is_terminal { LinkStyle::Link } else { LinkStyle::Text },
39            termwidth: 400,
40            theme: GraphicalTheme::new(is_terminal),
41        }
42    }
43
44    /// Create a new `GraphicalReportHandler` with a given [`GraphicalTheme`].
45    #[must_use]
46    pub fn new_themed(theme: GraphicalTheme) -> Self {
47        Self { links: LinkStyle::Link, termwidth: 200, theme }
48    }
49
50    /// Whether to enable error code linkification using [`Diagnostic::url()`](crate::Diagnostic::url).
51    #[must_use]
52    pub fn with_links(mut self, links: bool) -> Self {
53        self.links = if links { LinkStyle::Link } else { LinkStyle::Text };
54        self
55    }
56
57    /// Set a theme for this handler.
58    #[must_use]
59    pub fn with_theme(mut self, theme: GraphicalTheme) -> Self {
60        self.theme = theme;
61        self
62    }
63
64    /// Sets the width to wrap the report at.
65    #[must_use]
66    pub fn with_width(mut self, width: usize) -> Self {
67        self.termwidth = width;
68        self
69    }
70}
71
72impl Default for GraphicalReportHandler {
73    fn default() -> Self {
74        Self::new()
75    }
76}