diff_tool/services/
config.rs

1use crate::update::message::Message;
2use anyhow::{bail, Result};
3use directories::ProjectDirs;
4use serde::Deserialize;
5use std::path::PathBuf;
6use std::{collections::HashMap, ops::Deref};
7
8#[derive(Debug, Default, Deserialize)]
9pub struct Config {
10    keymap: KeyMap,
11    // TODO: Colour schemes
12    // colour_scheme: HashMap<String, String>,
13}
14
15#[derive(Clone, Debug, Default, Deserialize)]
16pub struct KeyMap(HashMap<String, Message>);
17
18impl Deref for KeyMap {
19    type Target = HashMap<String, Message>;
20
21    fn deref(&self) -> &Self::Target {
22        &self.0
23    }
24}
25
26impl Config {
27    pub fn new() -> Result<Self> {
28        let config_dir = get_config_dir()?; // Assuming you have a function to get the config directory
29
30        // Specify the path to the config file
31        let config_path = config_dir.join("config.toml");
32
33        let config = config::Config::builder()
34            .add_source(config::File::from(config_path.clone()))
35            .build()
36            .unwrap_or(Self::default_config()?);
37
38        let config = config.try_deserialize()?;
39
40        Ok(config)
41    }
42
43    pub fn keymap(&self) -> &KeyMap {
44        &self.keymap
45    }
46
47    fn default_config() -> Result<config::Config, config::ConfigError> {
48        let default_keymap = r#"[keymap]
49"esc" = "Quit"
50"q" = "Quit"
51"ctrl+c" = "Quit"
52"ctrl+d" = "Quit"
53"Shift+g" = "LastRow"
54"g" = "FirstRow"
55"j" = "NextRow"
56"k" = "PrevRow"
57
58[colour_scheme]
59"fg" = "white"
60"bg" = "transparent"
61"text" = "white""#;
62
63        config::Config::builder()
64            .add_source(config::File::from_str(
65                default_keymap,
66                config::FileFormat::Toml,
67            ))
68            .build()
69    }
70}
71
72// INFO: probably won't need this
73// fn get_data_dir() -> Result<PathBuf> {
74//     let directory = if let Ok(s) = std::env::var("DIFF-TOOL-DATA") {
75//         PathBuf::from(s)
76//     } else if let Some(proj_dirs) = ProjectDirs::from("", "ddraigan", "diff-tool") {
77//         proj_dirs.data_local_dir().to_path_buf()
78//     } else {
79//         bail!("Unable to find data directory for Diff-Tool");
80//     };
81//     Ok(directory)
82// }
83
84fn get_config_dir() -> Result<PathBuf> {
85    let directory = if let Ok(s) = std::env::var("DIFF-TOOL-CONFIG") {
86        PathBuf::from(s)
87    } else if let Some(proj_dirs) = ProjectDirs::from("", "ddraigan", "diff-tool") {
88        proj_dirs.config_local_dir().to_path_buf()
89    } else {
90        bail!("Unable to find config directory for Diff-Tool")
91    };
92    Ok(directory)
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98    use std::fs::File;
99    use std::io::Write;
100    use std::path::Path;
101
102    #[test]
103    fn test_new() -> Result<()> {
104        // Create a mock configuration file
105        let config_path = Path::new("config.toml");
106        let mut file = File::create(&config_path)?;
107        write!(
108            file,
109            "[keymap]\n\"key1\" = \"Quit\"\n\n[colour_scheme]\n\"key1\" = \"Quit\""
110        )?;
111
112        // Call the function
113        let config = Config::new()?;
114
115        // Check the result
116        assert_eq!(config.keymap.0.get("key1"), Some(&Message::Quit));
117
118        // Clean up
119        std::fs::remove_file(config_path)?;
120
121        Ok(())
122    }
123}