openweather_cli/
config.rs

1use clap::ValueEnum;
2use serde::{Deserialize, Serialize};
3use std::{fs, path::PathBuf};
4
5#[derive(Serialize, Deserialize)]
6pub struct Config {
7    pub api_key: String,
8    pub geometry_mode: GeometryMode,
9    #[serde(default)]
10    pub minutely: bool,
11    #[serde(default)]
12    pub hourly: bool,
13    #[serde(default)]
14    pub daily: bool,
15}
16
17#[derive(Serialize, Deserialize, Clone, Debug, ValueEnum)]
18pub enum GeometryMode {
19    #[serde(rename = "location", alias = "Location")]
20    Location,
21    #[serde(rename = "city", alias = "City")]
22    City,
23}
24
25impl Default for Config {
26    fn default() -> Self {
27        Self {
28            api_key: Default::default(),
29            geometry_mode: GeometryMode::Location,
30            minutely: false,
31            hourly: false,
32            daily: false,
33        }
34    }
35}
36
37impl Config {
38    fn config_path() -> anyhow::Result<PathBuf> {
39        use directories_next::ProjectDirs;
40        let project_dirs = ProjectDirs::from("", "LitiaEeloo", "OpenWeather")
41            .ok_or_else(|| anyhow::anyhow!("No valid config directory fomulated"))?;
42        let config_file = "config.toml";
43        let mut config_path = project_dirs.config_dir().to_owned();
44        fs::create_dir_all(&config_path)?;
45        config_path.push(config_file);
46        Ok(config_path)
47    }
48    pub fn of_file() -> anyhow::Result<Self> {
49        let config_text = fs::read_to_string(&Self::config_path()?).map_err(|_| {
50            anyhow::anyhow!("error opening config file; did you run `open-weather init`?")
51        })?;
52        let config: Self = toml::from_str(&config_text)?;
53        if config.api_key.is_empty() {
54            Err(anyhow::anyhow!("empty key"))?
55        }
56        Ok(config)
57    }
58    pub fn fresh() -> Self {
59        Config::default()
60    }
61    pub fn edit() -> anyhow::Result<()> {
62        let editor = std::env::var("EDITOR").or_else(|err| {
63            println!("Please set $EDITOR to your preferred editor.");
64            Err(err)
65        })?;
66        let mut child = std::process::Command::new(editor)
67            .args([Config::config_path()?])
68            .spawn()?;
69        child.wait()?;
70        Ok(())
71    }
72    pub fn to_file(&self) -> anyhow::Result<()> {
73        let text = toml::to_string(self)?;
74        fs::write(&Self::config_path()?, text)
75            .map_err(|_| anyhow::anyhow!("error writing config file"))?;
76        Ok(())
77    }
78}