Skip to main content

prj_core/
config.rs

1use std::path::PathBuf;
2
3use directories::ProjectDirs;
4use serde::{Deserialize, Serialize};
5
6/// User configuration loaded from `~/.config/prj/config.toml`.
7///
8/// All fields have sensible defaults so the config file is optional.
9#[derive(Debug, Serialize, Deserialize)]
10pub struct Config {
11    #[serde(default = "default_shell_cmd")]
12    pub shell_cmd: String,
13    #[serde(default = "default_scan_depth")]
14    pub scan_depth: usize,
15    pub database_path: Option<PathBuf>,
16}
17
18fn default_shell_cmd() -> String {
19    "prjp".to_string()
20}
21
22fn default_scan_depth() -> usize {
23    3
24}
25
26impl Default for Config {
27    fn default() -> Self {
28        Self {
29            shell_cmd: default_shell_cmd(),
30            scan_depth: default_scan_depth(),
31            database_path: None,
32        }
33    }
34}
35
36impl Config {
37    pub fn load() -> color_eyre::Result<Self> {
38        let config_path = Self::config_path();
39        if config_path.exists() {
40            let content = std::fs::read_to_string(&config_path)?;
41            Ok(toml::from_str(&content)?)
42        } else {
43            Ok(Self::default())
44        }
45    }
46
47    pub fn config_path() -> PathBuf {
48        Self::project_dirs().config_dir().join("config.toml")
49    }
50
51    pub fn database_path(&self) -> PathBuf {
52        self.database_path
53            .clone()
54            .unwrap_or_else(|| Self::project_dirs().data_dir().join("projects.toml"))
55    }
56
57    fn project_dirs() -> ProjectDirs {
58        ProjectDirs::from("", "", "prj").expect("could not determine project directories")
59    }
60}