git_iris/theme/
error.rs

1//! Theme error types.
2
3use std::fmt;
4use std::path::PathBuf;
5
6use super::color::ColorParseError;
7
8/// Errors that can occur when loading or resolving themes.
9#[derive(Debug)]
10pub enum ThemeError {
11    /// Failed to read theme file.
12    IoError {
13        path: PathBuf,
14        source: std::io::Error,
15    },
16    /// Failed to parse TOML.
17    ParseError {
18        path: Option<PathBuf>,
19        source: toml::de::Error,
20    },
21    /// Invalid color value.
22    InvalidColor {
23        token: String,
24        source: ColorParseError,
25    },
26    /// Circular reference detected in token resolution.
27    CircularReference { token: String, chain: Vec<String> },
28    /// Referenced token not found.
29    UnresolvedToken { token: String, reference: String },
30    /// Missing required section in theme file.
31    MissingSection { section: String },
32    /// Theme not found by name.
33    ThemeNotFound { name: String },
34}
35
36impl fmt::Display for ThemeError {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        match self {
39            Self::IoError { path, source } => {
40                write!(
41                    f,
42                    "failed to read theme file '{}': {}",
43                    path.display(),
44                    source
45                )
46            }
47            Self::ParseError { path, source } => {
48                if let Some(path) = path {
49                    write!(f, "failed to parse theme '{}': {}", path.display(), source)
50                } else {
51                    write!(f, "failed to parse theme: {source}")
52                }
53            }
54            Self::InvalidColor { token, source } => {
55                write!(f, "invalid color for token '{token}': {source}")
56            }
57            Self::CircularReference { token, chain } => {
58                write!(
59                    f,
60                    "circular reference detected for token '{token}': {}",
61                    chain.join(" -> ")
62                )
63            }
64            Self::UnresolvedToken { token, reference } => {
65                write!(f, "token '{token}' references unknown token '{reference}'")
66            }
67            Self::MissingSection { section } => {
68                write!(f, "missing required section '[{section}]' in theme file")
69            }
70            Self::ThemeNotFound { name } => {
71                write!(f, "theme '{name}' not found")
72            }
73        }
74    }
75}
76
77impl std::error::Error for ThemeError {
78    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
79        match self {
80            Self::IoError { source, .. } => Some(source),
81            Self::ParseError { source, .. } => Some(source),
82            Self::InvalidColor { source, .. } => Some(source),
83            _ => None,
84        }
85    }
86}
87
88impl From<ColorParseError> for ThemeError {
89    fn from(err: ColorParseError) -> Self {
90        Self::InvalidColor {
91            token: String::new(),
92            source: err,
93        }
94    }
95}