Skip to main content

navi/config/
yaml.rs

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}