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, Default, Debug)]
82#[serde(default)]
83pub struct YamlConfig {
84 pub style: Style,
85 pub finder: Finder,
86 pub cheats: Cheats,
87 pub search: Search,
88 pub shell: Shell,
89}
90
91impl YamlConfig {
92 fn from_str(text: &str) -> Result<Self> {
93 serde_yaml::from_str(text).map_err(|e| e.into())
94 }
95
96 fn from_path(path: &Path) -> Result<Self> {
97 let file = fs::open(path)?;
98 let reader = BufReader::new(file);
99 serde_yaml::from_reader(reader).map_err(|e| e.into())
100 }
101
102 pub fn get(env: &EnvConfig) -> Result<Self> {
103 if let Some(yaml) = env.config_yaml.as_ref() {
104 return Self::from_str(yaml);
105 }
106 if let Some(path_str) = env.config_path.as_ref() {
107 let p = PathBuf::from(path_str);
108 return YamlConfig::from_path(&p);
109 }
110 if let Ok(p) = default_config_pathbuf() {
111 if p.exists() {
112 return YamlConfig::from_path(&p);
113 }
114 }
115 Ok(YamlConfig::default())
116 }
117}
118
119impl Default for ColorWidth {
120 fn default() -> Self {
121 Self {
122 color: Color(TerminalColor::Blue),
123 width_percentage: 26,
124 min_width: 20,
125 }
126 }
127}
128
129impl Default for Style {
130 fn default() -> Self {
131 Self {
132 tag: ColorWidth {
133 color: Color(TerminalColor::Cyan),
134 width_percentage: 26,
135 min_width: 20,
136 },
137 comment: ColorWidth {
138 color: Color(TerminalColor::Blue),
139 width_percentage: 42,
140 min_width: 45,
141 },
142 snippet: Default::default(),
143 }
144 }
145}
146
147impl Default for Finder {
148 fn default() -> Self {
149 Self {
150 command: FinderChoice::Fzf,
151 overrides: None,
152 overrides_var: None,
153 }
154 }
155}
156
157impl Default for Shell {
158 fn default() -> Self {
159 Self {
160 command: "bash".to_string(),
161 finder_command: None,
162 }
163 }
164}