i3wsr_core/
config.rs

1use serde::Deserialize;
2use std::collections::HashMap;
3use std::fs::File;
4use std::io::{self, Read};
5use std::path::Path;
6use thiserror::Error;
7
8type StringMap = HashMap<String, String>;
9type IconMap = HashMap<String, String>;
10type OptionMap = HashMap<String, bool>;
11
12#[derive(Error, Debug)]
13pub enum ConfigError {
14    #[error("Failed to read config file: {0}")]
15    IoError(#[from] io::Error),
16    #[error("Failed to parse TOML: {0}")]
17    TomlError(#[from] toml::de::Error),
18}
19
20/// Represents aliases for different categories
21#[derive(Deserialize, Debug, Clone)]
22#[serde(default)]
23pub struct Aliases {
24    pub class: StringMap,
25    pub instance: StringMap,
26    pub name: StringMap,
27    pub app_id: StringMap,
28}
29
30impl Aliases {
31    /// Creates a new empty Aliases instance
32    pub fn new() -> Self {
33        Self::default()
34    }
35
36    /// Gets an alias by category and key
37    pub fn get_alias(&self, category: &str, key: &str) -> Option<&String> {
38        match category {
39            "app_id" => self.app_id.get(key),
40            "class" => self.class.get(key),
41            "instance" => self.instance.get(key),
42            "name" => self.name.get(key),
43            _ => None,
44        }
45    }
46}
47
48impl Default for Aliases {
49    fn default() -> Self {
50        Self {
51            class: StringMap::new(),
52            instance: StringMap::new(),
53            name: StringMap::new(),
54            app_id: StringMap::new(),
55        }
56    }
57}
58
59/// Main configuration structure
60#[derive(Deserialize, Debug, Clone)]
61#[serde(default)]
62pub struct Config {
63    pub icons: IconMap,
64    pub aliases: Aliases,
65    pub general: StringMap,
66    pub options: OptionMap,
67}
68
69impl Config {
70    /// Creates a new Config instance from a file
71    pub fn new(filename: &Path) -> Result<Self, ConfigError> {
72        let config = Self::from_file(filename)?;
73        Ok(config)
74    }
75
76    /// Loads configuration from a TOML file
77    pub fn from_file(filename: &Path) -> Result<Self, ConfigError> {
78        let mut file = File::open(filename)?;
79        let mut buffer = String::new();
80        file.read_to_string(&mut buffer)?;
81        let config: Config = toml::from_str(&buffer)?;
82        Ok(config)
83    }
84
85    /// Gets a general configuration value
86    pub fn get_general(&self, key: &str) -> Option<String> {
87        self.general.get(key).map(|s| s.to_string())
88    }
89
90    /// Gets an option value
91    pub fn get_option(&self, key: &str) -> Option<bool> {
92        self.options.get(key).copied()
93    }
94
95    /// Gets an icon by key
96    pub fn get_icon(&self, key: &str) -> Option<String> {
97        self.icons.get(key).map(|s| s.to_string())
98    }
99
100    /// Sets a general configuration value
101    pub fn set_general(&mut self, key: String, value: String) {
102        self.general.insert(key, value);
103    }
104
105    /// Sets a an option configuration value
106    pub fn set_option(&mut self, key: String, value: bool) {
107        self.options.insert(key, value);
108    }
109}
110
111impl Default for Config {
112    fn default() -> Self {
113        Self {
114            icons: IconMap::new(),
115            aliases: Aliases::default(),
116            general: StringMap::new(),
117            options: OptionMap::new(),
118        }
119    }
120}