cargo_hatch/settings/
global.rs1use std::collections::{BTreeMap, HashMap, HashSet};
2
3use anyhow::Result;
4use camino::Utf8PathBuf;
5use serde::Deserialize;
6
7use crate::dirs::Utf8ProjectDirs;
8
9#[derive(Deserialize)]
10#[cfg_attr(test, derive(Debug, PartialEq))]
11pub struct Settings {
12 #[serde(default)]
13 pub git: Git,
14 #[serde(default)]
15 pub bookmarks: BTreeMap<String, Bookmark>,
16 #[serde(default)]
17 pub update_deps: bool,
18}
19
20#[derive(Default, Deserialize)]
21#[cfg_attr(test, derive(Debug, Eq, PartialEq))]
22pub struct Git {
23 pub ssh_key: Option<Utf8PathBuf>,
24}
25
26#[derive(Deserialize)]
27#[cfg_attr(test, derive(Debug, PartialEq))]
28pub struct Bookmark {
29 pub repository: String,
30 pub description: Option<String>,
31 pub folder: Option<Utf8PathBuf>,
32 #[serde(default)]
33 pub defaults: HashMap<String, DefaultSetting>,
34}
35
36#[derive(Deserialize)]
37#[cfg_attr(test, derive(Debug, PartialEq))]
38pub struct DefaultSetting {
39 pub value: DefaultValue,
40 pub skip_prompt: bool,
41}
42
43#[derive(Debug, Deserialize)]
44#[cfg_attr(test, derive(PartialEq))]
45#[serde(rename_all = "snake_case")]
46pub enum DefaultValue {
47 Bool(bool),
48 String(String),
49 Number(i64),
50 Float(f64),
51 List(String),
52 MultiList(HashSet<String>),
53}
54
55pub fn load(dirs: &Utf8ProjectDirs) -> Result<Settings> {
56 let buf = std::fs::read(dirs.config_dir().join("settings.toml"))?;
57 basic_toml::from_slice(&buf).map_err(Into::into)
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn defaults() {
66 let raw = r#"
67 update_deps = true
68
69 [git]
70 ssh_key = ".ssh/id_ed25519"
71
72 [bookmarks.server]
73 repository = "test"
74 description = "sample"
75 folder = "a/b/c"
76
77 [bookmarks.server.defaults]
78 test_bool = { value = { bool = true }, skip_prompt = false }
79 test_string = { value = { string = "value" }, skip_prompt = false }
80 test_number = { value = { number = 10 }, skip_prompt = false }
81 test_float = { value = { float = 2.5 }, skip_prompt = false }
82 test_list = { value = { list = "one" }, skip_prompt = true }
83 test_multi_list = { value = { multi_list = ["one", "two"] }, skip_prompt = true }
84 "#;
85 let expect = Settings {
86 git: Git {
87 ssh_key: Some(Utf8PathBuf::from(".ssh/id_ed25519")),
88 },
89 bookmarks: [(
90 "server".to_owned(),
91 Bookmark {
92 repository: "test".to_owned(),
93 description: Some("sample".to_owned()),
94 folder: Some(Utf8PathBuf::from("a/b/c")),
95 defaults: [
96 (
97 "test_bool".to_owned(),
98 DefaultSetting {
99 value: DefaultValue::Bool(true),
100 skip_prompt: false,
101 },
102 ),
103 (
104 "test_string".to_owned(),
105 DefaultSetting {
106 value: DefaultValue::String("value".to_owned()),
107 skip_prompt: false,
108 },
109 ),
110 (
111 "test_number".to_owned(),
112 DefaultSetting {
113 value: DefaultValue::Number(10),
114 skip_prompt: false,
115 },
116 ),
117 (
118 "test_float".to_owned(),
119 DefaultSetting {
120 value: DefaultValue::Float(2.5),
121 skip_prompt: false,
122 },
123 ),
124 (
125 "test_list".to_owned(),
126 DefaultSetting {
127 value: DefaultValue::List("one".to_owned()),
128 skip_prompt: true,
129 },
130 ),
131 (
132 "test_multi_list".to_owned(),
133 DefaultSetting {
134 value: DefaultValue::MultiList(
135 ["one".to_owned(), "two".to_owned()].into_iter().collect(),
136 ),
137 skip_prompt: true,
138 },
139 ),
140 ]
141 .into_iter()
142 .collect(),
143 },
144 )]
145 .into_iter()
146 .collect(),
147 update_deps: true,
148 };
149
150 let result = basic_toml::from_str::<Settings>(raw);
151 assert_eq!(expect, result.unwrap());
152 }
153}