Skip to main content

hjkl_theme/
loader.rs

1//! Free-function loader API for [`Theme`].
2//!
3//! Wraps `Theme::from_toml_str` / `Theme::from_path` as top-level functions
4//! so callers can write `hjkl_theme::loader::load_from_path(p)?` without
5//! importing the `Theme` struct, and provides `default_theme()` with a
6//! minimal bundled dark palette.
7//!
8//! `resolve_palette_refs` is exposed here for symmetry, but resolution
9//! happens automatically inside `parse_toml` / `load_from_path`; callers
10//! that build a `Theme` via those functions get fully-resolved colors with
11//! no additional step required.
12
13use std::path::Path;
14
15use crate::{Theme, ThemeError};
16
17/// Built-in minimal dark theme source embedded at compile time.
18const DEFAULT_THEME_TOML: &str = include_str!("../themes/default.toml");
19
20/// Parse a TOML string into a fully-resolved [`Theme`].
21///
22/// Palette `$name` references are resolved automatically.
23///
24/// # Errors
25/// Returns [`ThemeError::Toml`] on parse failure or
26/// [`ThemeError::UnresolvedPalette`] / [`ThemeError::BadHex`] on bad
27/// color values.
28pub fn parse_toml(src: &str) -> Result<Theme, ThemeError> {
29    Theme::from_toml_str(src)
30}
31
32/// Read a TOML file from `path` and return a fully-resolved [`Theme`].
33///
34/// Palette `$name` references are resolved automatically.
35///
36/// # Errors
37/// Returns [`ThemeError::Io`] on read failure or any error that
38/// [`parse_toml`] can return.
39pub fn load_from_path(path: &Path) -> Result<Theme, ThemeError> {
40    Theme::from_path(path)
41}
42
43/// Walk a [`Theme`] and verify all palette references are resolved.
44///
45/// After a successful call to [`parse_toml`] or [`load_from_path`] this
46/// is always a no-op — resolution is performed during parsing. The
47/// function is provided as an explicit checkpoint for callers that
48/// construct a `Theme` by other means (e.g. merging two themes) and
49/// want to assert completeness before use.
50///
51/// Returns `Ok(())` when every color in the theme is already concrete.
52///
53/// # Errors
54/// Returns [`ThemeError::UnresolvedPalette`] if a `$name` palette
55/// reference could not be resolved. (This cannot happen for themes
56/// produced by [`parse_toml`] / [`load_from_path`].)
57pub fn resolve_palette_refs(_theme: &mut Theme) -> Result<(), ThemeError> {
58    // Resolution is performed eagerly during TOML parsing.
59    // For themes produced by `parse_toml` / `load_from_path` there is
60    // nothing left to do. This entry-point exists so that callers who
61    // merge or mutate themes have a stable hook point if resolution
62    // is added as a separate phase in the future.
63    Ok(())
64}
65
66/// Return the bundled default dark [`Theme`].
67///
68/// The theme is a minimal dark palette suitable as a fallback when no
69/// user theme file is found. It is embedded in the binary at compile
70/// time and always valid.
71///
72/// # Panics
73/// Panics if the bundled TOML is malformed — this would be a compile-time
74/// error caught by `cargo test`.
75pub fn default_theme() -> Theme {
76    parse_toml(DEFAULT_THEME_TOML).expect("bundled default.toml is always valid")
77}