leetcode_tui_config/
config.rs

1use super::theme::Theme;
2use crate::utils::{get_config_file_path, get_default_database_file_path, get_solutions_dir_path};
3use color_eyre::Result;
4use leetcode_tui_shared::RoCell;
5use serde::{Deserialize, Serialize};
6use std::fs::File;
7use std::io::prelude::*;
8use std::{fs::create_dir_all, path::PathBuf};
9pub static CONFIG: RoCell<Config> = RoCell::new();
10
11pub fn init() -> Result<()> {
12    CONFIG.init({
13        let config_file = get_config_file_path();
14        if !config_file.exists() {
15            Config::create_default_config(&config_file);
16            Config::create_default_solution_dir();
17            println!(
18                "Please fill in leetcode_sesion and csrftoken in config file \n @ {}",
19                config_file.display()
20            );
21            std::process::exit(0);
22        }
23
24        let contents = std::fs::read_to_string(&config_file)?;
25        let parsed_config: Config = toml::from_str(&contents)?;
26
27        if parsed_config.db.path.to_str() == Some("") {
28            println!(
29                "Either fill in field \"db\" in config file or remove the field for default setting\n@ {}",
30                config_file.display()
31            );
32            std::process::exit(0);
33        }
34
35        if parsed_config.solutions_dir.to_str() == Some("") {
36            println!(
37                "Either provide the \"solutions_dir\" path in config file or remove the field for default setting\n@ {}",
38                config_file.display()
39            );
40            std::process::exit(0);
41        }
42
43        if !parsed_config.solutions_dir.exists() {
44            create_dir_all(parsed_config.solutions_dir.clone())?;
45        }
46
47        if !parsed_config.db.path.exists() {
48            parsed_config
49                .db
50                .path
51                .parent()
52                .map(|parent| create_dir_all(parent));
53        }
54
55        parsed_config
56    });
57    Ok(())
58}
59
60#[derive(Serialize, Deserialize, Debug, Default)]
61pub struct Config {
62    pub csrftoken: String,
63    pub lc_session: String,
64    #[serde(default, skip_serializing)]
65    pub db: Database,
66    #[serde(default = "get_solutions_dir_path", skip_serializing)]
67    pub solutions_dir: PathBuf,
68    #[serde(default, skip_serializing)]
69    pub theme: Theme,
70}
71
72impl Config {
73    fn create_default_solution_dir() {
74        create_dir_all(get_solutions_dir_path()).unwrap();
75    }
76
77    fn create_default_config(config_file: &PathBuf) {
78        let config_dir = config_file.as_path().parent().expect(&format!(
79            "Cannot get parent of the file path: {}",
80            config_file.display()
81        ));
82        create_dir_all(config_dir)
83            .expect(format!("Cannot create config directory @ {}", config_dir.display()).as_str());
84        let default_config = Self::default();
85        let default_config_str =
86            toml::to_string(&default_config).expect("Cannot serialize default config to string.");
87        let mut file = File::create(&config_file)
88            .expect(format!("Cannot create file @ {}", config_file.display()).as_str());
89        file.write_all(default_config_str.as_bytes()).expect(
90            format!(
91                "Cannot write to the config file @ {}",
92                config_file.display()
93            )
94            .as_str(),
95        );
96    }
97}
98
99#[derive(Serialize, Deserialize, Debug)]
100pub struct Database {
101    pub path: PathBuf,
102}
103
104impl Default for Database {
105    fn default() -> Self {
106        Self {
107            path: get_default_database_file_path(),
108        }
109    }
110}