1use super::env::EnvConfig;
2use crate::common::fs;
3use crate::filesystem::default_config_pathbuf;
4use crate::finder::FinderChoice;
5use crate::prelude::*;
6use crossterm::style::Color as TerminalColor;
7use serde::de;
8
9#[derive(Deserialize, Debug)]
10pub struct Color(#[serde(deserialize_with = "color_deserialize")] TerminalColor);
11
12impl Color {
13 pub fn get(&self) -> TerminalColor {
14 self.0
15 }
16}
17
18fn color_deserialize<'de, D>(deserializer: D) -> Result<TerminalColor, D::Error>
19where
20 D: de::Deserializer<'de>,
21{
22 let s: String = Deserialize::deserialize(deserializer)?;
23 TerminalColor::try_from(s.as_str())
24 .map_err(|_| de::Error::custom(format!("Failed to deserialize color: {s}")))
25}
26
27#[derive(Deserialize, Debug)]
28#[serde(default)]
29pub struct ColorWidth {
30 pub color: Color,
31 pub width_percentage: u16,
32 pub min_width: u16,
33}
34
35#[derive(Deserialize, Debug)]
36#[serde(default)]
37pub struct Style {
38 pub tag: ColorWidth,
39 pub comment: ColorWidth,
40 pub snippet: ColorWidth,
41}
42
43#[derive(Deserialize, Debug)]
44#[serde(default)]
45pub struct Finder {
46 #[serde(deserialize_with = "finder_deserialize")]
47 pub command: FinderChoice,
48 pub overrides: Option<String>,
49 pub overrides_var: Option<String>,
50}
51
52fn finder_deserialize<'de, D>(deserializer: D) -> Result<FinderChoice, D::Error>
53where
54 D: de::Deserializer<'de>,
55{
56 let s: String = Deserialize::deserialize(deserializer)?;
57 FinderChoice::from_str(s.to_lowercase().as_str())
58 .map_err(|_| de::Error::custom(format!("Failed to deserialize finder: {s}")))
59}
60
61#[derive(Deserialize, Default, Debug)]
62#[serde(default)]
63pub struct Cheats {
64 pub path: Option<String>,
65 pub paths: Vec<String>,
66}
67
68#[derive(Deserialize, Default, Debug)]
69#[serde(default)]
70pub struct Search {
71 pub tags: Option<String>,
72}
73
74#[derive(Deserialize, Debug)]
75#[serde(default)]
76pub struct Shell {
77 pub command: String,
78 pub finder_command: Option<String>,
79}
80
81#[derive(Deserialize, Debug)]
82#[serde(default)]
83#[derive(Default)]
84pub struct Client {
85 pub tealdeer: bool,
86}
87
88#[derive(Deserialize, Default, Debug)]
89#[serde(default)]
90pub struct YamlConfig {
91 pub style: Style,
92 pub finder: Finder,
93 pub cheats: Cheats,
94 pub search: Search,
95 pub shell: Shell,
96 pub client: Client,
97}
98
99impl YamlConfig {
100 fn from_str(text: &str) -> Result<Self> {
101 serde_yaml::from_str(text).map_err(|e| e.into())
102 }
103
104 fn from_path(path: &Path) -> Result<Self> {
105 let file = fs::open(path)?;
106 let reader = BufReader::new(file);
107 serde_yaml::from_reader(reader).map_err(|e| e.into())
108 }
109
110 pub fn get(env: &EnvConfig) -> Result<Self> {
111 if let Some(yaml) = env.config_yaml.as_ref() {
112 return Self::from_str(yaml);
113 }
114 if let Some(path_str) = env.config_path.as_ref() {
115 let p = PathBuf::from(path_str);
116 return YamlConfig::from_path(&p);
117 }
118 if let Ok(p) = default_config_pathbuf() {
119 if p.exists() {
120 return YamlConfig::from_path(&p);
121 }
122 }
123 Ok(YamlConfig::default())
124 }
125}
126
127impl Default for ColorWidth {
128 fn default() -> Self {
129 Self {
130 color: Color(TerminalColor::Blue),
131 width_percentage: 26,
132 min_width: 20,
133 }
134 }
135}
136
137impl Default for Style {
138 fn default() -> Self {
139 Self {
140 tag: ColorWidth {
141 color: Color(TerminalColor::Cyan),
142 width_percentage: 26,
143 min_width: 20,
144 },
145 comment: ColorWidth {
146 color: Color(TerminalColor::Blue),
147 width_percentage: 42,
148 min_width: 45,
149 },
150 snippet: Default::default(),
151 }
152 }
153}
154
155impl Default for Finder {
156 fn default() -> Self {
157 Self {
158 command: FinderChoice::Fzf,
159 overrides: None,
160 overrides_var: None,
161 }
162 }
163}
164
165impl Default for Shell {
166 fn default() -> Self {
167 Self {
168 command: "bash".to_string(),
169 finder_command: None,
170 }
171 }
172}