Skip to main content

wisp/settings/
themes.rs

1//! The theme files kept beside the settings: listing them for the picker and
2//! loading the one the user chose.
3
4use crate::settings::UiSettings;
5use crate::theme::Theme;
6use std::path::{Path, PathBuf};
7
8pub fn resolve_theme_file_path(settings: &UiSettings) -> Option<PathBuf> {
9    let file_name = settings.theme.file.as_deref()?.trim();
10    resolve_theme_file_path_from_name(file_name)
11}
12
13fn themes_dir_path() -> Option<PathBuf> {
14    let home = super::store()?.home().to_path_buf();
15    Some(home.join("themes"))
16}
17
18pub fn list_theme_files() -> Vec<String> {
19    let Some(themes_dir) = themes_dir_path() else {
20        return Vec::new();
21    };
22    let Ok(entries) = std::fs::read_dir(themes_dir) else {
23        return Vec::new();
24    };
25    let mut files: Vec<String> = entries
26        .filter_map(Result::ok)
27        .filter_map(|entry| {
28            let Ok(file_type) = entry.file_type() else {
29                return None;
30            };
31            if !file_type.is_file() {
32                return None;
33            }
34            let name = entry.file_name().into_string().ok()?;
35            if !name.ends_with(".tmTheme") {
36                return None;
37            }
38            Some(name)
39        })
40        .collect();
41    files.sort_unstable();
42    files
43}
44
45pub fn load_theme_file(file_name: &str) -> Theme {
46    let Some(path) = resolve_theme_file_path_from_name(file_name) else {
47        return Theme::default();
48    };
49    Theme::load_from_path(&path)
50}
51
52fn resolve_theme_file_path_from_name(file_name: &str) -> Option<PathBuf> {
53    let trimmed = file_name.trim();
54    if trimmed.is_empty() {
55        return None;
56    }
57    let candidate = Path::new(trimmed);
58    let base_name = candidate.file_name()?.to_str()?;
59    if base_name != trimmed {
60        return None;
61    }
62    if matches!(base_name, "." | "..") {
63        return None;
64    }
65    Some(themes_dir_path()?.join(base_name))
66}