1use std::fs;
2use std::path::PathBuf;
3
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "kebab-case")]
9pub enum ThemeId {
10 CatppuccinMocha,
11 Everforest,
12}
13
14impl Default for ThemeId {
15 fn default() -> Self {
16 Self::CatppuccinMocha
17 }
18}
19
20impl ThemeId {
21 pub const ALL: [ThemeId; 2] = [ThemeId::CatppuccinMocha, ThemeId::Everforest];
22
23 pub fn label(self) -> &'static str {
24 match self {
25 ThemeId::CatppuccinMocha => "Catppuccin Mocha",
26 ThemeId::Everforest => "Everforest",
27 }
28 }
29
30 pub fn next(self) -> Self {
31 match self {
32 ThemeId::CatppuccinMocha => ThemeId::Everforest,
33 ThemeId::Everforest => ThemeId::CatppuccinMocha,
34 }
35 }
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
42#[serde(default)]
43pub struct Config {
44 pub theme: ThemeId,
45 pub ui_font: String,
46 pub mono_font: String,
47 pub font_size: f32,
49 pub panel_width: f32,
50 pub gap: f32,
51 pub corner_radius: f32,
52}
53
54impl Default for Config {
55 fn default() -> Self {
56 Self {
57 theme: ThemeId::CatppuccinMocha,
58 ui_font: "Noto Sans".to_string(),
59 mono_font: "JetBrainsMono Nerd Font".to_string(),
60 font_size: 16.0,
61 panel_width: 268.0,
62 gap: 12.0,
63 corner_radius: 12.0,
64 }
65 }
66}
67
68impl Config {
69 pub fn path() -> PathBuf {
70 config_dir().join("termden").join("config.toml")
71 }
72
73 pub fn load() -> Self {
74 let path = Self::path();
75 let Ok(text) = fs::read_to_string(&path) else {
76 return Self::default();
77 };
78
79 match toml::from_str(&text) {
80 Ok(config) => config,
81 Err(error) => {
82 eprintln!("termden: could not parse {}: {error}", path.display());
83 Self::default()
84 }
85 }
86 }
87
88 pub fn save(&self) -> std::io::Result<()> {
89 let path = Self::path();
90 if let Some(parent) = path.parent() {
91 fs::create_dir_all(parent)?;
92 }
93 let text = toml::to_string_pretty(self).map_err(std::io::Error::other)?;
94 fs::write(path, text)
95 }
96}
97
98fn config_dir() -> PathBuf {
99 crate::state::xdg_dir("XDG_CONFIG_HOME", ".config")
100}