use dampen_core::ir::theme::ThemeDocument;
use dampen_core::parser::theme_parser::parse_theme_document;
use dampen_core::state::ThemeContext;
use std::fs;
use std::path::{Path, PathBuf};
pub fn load_theme_context(project_dir: &Path) -> Result<Option<ThemeContext>, ThemeLoadError> {
load_theme_context_with_preference(project_dir, None)
}
pub fn load_theme_context_with_preference(
project_dir: &Path,
system_preference: Option<&str>,
) -> Result<Option<ThemeContext>, ThemeLoadError> {
match discover_theme_file(project_dir) {
Some(Ok(doc)) => {
let ctx = ThemeContext::from_document(doc, system_preference)
.map_err(ThemeLoadError::InvalidDocument)?;
Ok(Some(ctx))
}
Some(Err(e)) => Err(ThemeLoadError::ParseError(e)),
None => Ok(None),
}
}
pub fn discover_theme_file(project_dir: &Path) -> Option<Result<ThemeDocument, String>> {
let theme_path = find_theme_file_path(project_dir)?;
if !theme_path.exists() {
return None;
}
match fs::read_to_string(&theme_path) {
Ok(content) => match parse_theme_document(&content) {
Ok(doc) => Some(Ok(doc)),
Err(e) => Some(Err(format!("Failed to parse theme: {}", e))),
},
Err(e) => Some(Err(format!("Failed to read theme file: {}", e))),
}
}
pub fn find_theme_file_path(project_dir: &Path) -> Option<PathBuf> {
let paths = vec![project_dir.join("src/ui/theme/theme.dampen")];
paths.into_iter().find(|path| path.exists())
}
pub fn find_project_root() -> Option<PathBuf> {
if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
let path = PathBuf::from(&manifest_dir);
if path.join("src/ui/theme/theme.dampen").exists() {
return Some(path);
}
}
if let Ok(exe_path) = std::env::current_exe() {
let exe_name = exe_path
.file_stem()
.and_then(|s| s.to_str())
.map(|s| s.to_string());
if let Some(exe_dir) = exe_path.parent() {
for ancestor in exe_dir.ancestors() {
let theme_path = ancestor.join("src/ui/theme/theme.dampen");
if theme_path.exists() {
return Some(ancestor.to_path_buf());
}
if let Some(ref name) = exe_name {
let examples_path = ancestor.join("examples").join(name);
let theme_in_examples = examples_path.join("src/ui/theme/theme.dampen");
if theme_in_examples.exists() {
return Some(examples_path);
}
}
}
}
}
if let Ok(cwd) = std::env::current_dir() {
for ancestor in cwd.ancestors() {
let theme_path = ancestor.join("src/ui/theme/theme.dampen");
if theme_path.exists() {
return Some(ancestor.to_path_buf());
}
}
}
None
}
pub fn create_minimal_dampen_app(dir: &Path) {
let src_dir = dir.join("src");
let ui_dir = src_dir.join("ui");
let theme_dir = ui_dir.join("theme");
let _ = fs::create_dir_all(&theme_dir);
}
#[derive(Debug, thiserror::Error)]
pub enum ThemeLoadError {
#[error("Failed to parse theme file: {0}")]
ParseError(String),
#[error("Invalid theme document: {0}")]
InvalidDocument(#[from] dampen_core::ir::theme::ThemeError),
}