use std::path::PathBuf;
use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
pub struct Config {
pub todo_files: Vec<PathBuf>,
}
impl Config {
fn new() -> Result<Self> {
let mut todo_txt_paths: Vec<PathBuf> = Vec::new();
set_default_path(&mut todo_txt_paths, toddi::TODO_FILE)?;
Ok(Config {
todo_files: todo_txt_paths,
})
}
pub fn load(config_file_path: PathBuf) -> Result<Config> {
match std::fs::exists(&config_file_path) {
Ok(value) => {
if !value {
println!("Default configuration file does not exist.");
match Config::new() {
Ok(config) => {
match toml::to_string(&config) {
Ok(conf_str) => {
if let Some(parent_dir) = config_file_path.parent() {
if !parent_dir.exists() {
std::fs::create_dir_all(parent_dir)?;
}
}
println!(
"Writing default configuration file: {}",
config_file_path.display()
);
std::fs::write(&config_file_path, &conf_str).with_context(
|| {
format!(
"Could not write file `{}`\nwith config: {}",
config_file_path.display(),
&conf_str
)
},
)?;
}
Err(err) => {
return Err(anyhow!(
"Could not serialize default configuration!\nError: {:?}",
err
));
}
};
}
Err(err) => {
return Err(anyhow!("Could not load configuration!\nError: {:?}", err))
}
};
}
}
Err(err) => {
return Err(anyhow!(
"Could not assess whether configuration file exists or not!\nError: {:?}",
err
))
}
}
let config_file = std::fs::read_to_string(&config_file_path)
.with_context(|| format!("could not read file `{}`", config_file_path.display()))?;
match toml::from_str(&config_file) {
Ok(parsed_config) => {
let parsed_config: Config = parsed_config;
Ok(parsed_config)
}
Err(err) => Err(anyhow!("Could not parse configuration!\nError: {:?}", err)),
}
}
}
fn set_default_path(paths: &mut Vec<PathBuf>, filename: &str) -> Result<()> {
let home_folder = get_homedir()?;
let default_folder = ".todo-txt";
let mut path_buffer = std::path::PathBuf::new();
path_buffer.push(&home_folder);
path_buffer.push(default_folder);
path_buffer.push(filename);
paths.push(path_buffer);
Ok(())
}
fn get_homedir() -> Result<PathBuf> {
if let Some(dir) = dirs::home_dir() {
Ok(dir)
} else {
Err(anyhow!(
"Issue with `dirs` crate: could not fetch home directory."
))
}
}