diff_tool/services/
config.rs1use 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 }
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()?; 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
72fn 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 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 let config = Config::new()?;
114
115 assert_eq!(config.keymap.0.get("key1"), Some(&Message::Quit));
117
118 std::fs::remove_file(config_path)?;
120
121 Ok(())
122 }
123}