app: improve config loading and merging

This commit is contained in:
Schrottkatze 2024-01-15 10:43:35 +01:00
parent ea2e5d6075
commit 7c9dca0ae2
Signed by: schrottkatze
GPG key ID: DFD0FD205943C14A
4 changed files with 73 additions and 54 deletions

View file

@ -6,7 +6,7 @@ use clap::Parser;
pub(crate) struct Args {
/// Read this config file.
#[arg(short, long)]
pub config_file: Option<PathBuf>,
pub config_path: Option<PathBuf>,
#[arg(long, env = "NO_STARTUP_MESSAGE", default_value = "false")]
pub no_startup_message: bool,
}

View file

@ -1,12 +1,11 @@
use std::{
fs,
path::{Path, PathBuf},
process,
};
use serde::{Deserialize, Serialize};
use crate::error_reporting::{report_serde_json_err, report_serde_ron_err};
use super::error::ConfigError;
#[derive(Debug, Serialize, Deserialize)]
pub struct Configs {
@ -17,59 +16,37 @@ pub struct Configs {
}
/// what the fuck serde why do i need this
pub(crate) fn default_example_value() -> i32 {
fn default_example_value() -> i32 {
43
}
pub(crate) fn default_no_startup_msg() -> bool {
fn default_no_startup_msg() -> bool {
false
}
pub(super) fn find_config_file() -> Result<PathBuf, ConfigError> {
let Some(config_path) = dirs::config_dir() else {
return Err(ConfigError::NoConfigDir);
};
let ron_path = config_path.with_file_name("config.ron");
let json_path = config_path.with_file_name("config.json");
if Path::new(&ron_path).exists() {
Ok(ron_path)
} else if Path::new(&json_path).exists() {
Ok(json_path)
} else {
Err(ConfigError::NoConfigFileFound)
}
}
impl Configs {
pub fn read(custom_path: Option<PathBuf>) -> Self {
use owo_colors::OwoColorize;
let p = match custom_path {
Some(p) => p,
None => {
let config_path = dirs::config_dir().expect("config dir should exist");
let ron_path = config_path.with_file_name("config.ron");
let json_path = config_path.with_file_name("config.json");
if Path::new(&ron_path).exists() {
ron_path
} else if Path::new(&json_path).exists() {
json_path
} else {
eprintln!("{}: couldn't find config file", "Fatal error".red());
process::exit(1)
}
}
};
pub fn read(p: PathBuf) -> Result<Self, ConfigError> {
match p.extension().map(|v| v.to_str().unwrap()) {
Some("ron") => Self::read_json(&fs::read_to_string(p).unwrap()),
Some("json") => Self::read_ron(&fs::read_to_string(p).unwrap()),
None | Some(_) => {
eprintln!(
"{}: couldn't determine config file type",
"Fatal error".red()
);
process::exit(1)
}
}
}
pub fn read_json(config_text: &str) -> Configs {
match serde_json::from_str(config_text) {
Ok(c) => c,
Err(e) => report_serde_json_err(config_text, e),
}
}
pub fn read_ron(config_text: &str) -> Configs {
match ron::from_str(config_text) {
Ok(c) => c,
Err(e) => report_serde_ron_err(config_text, e),
Some("ron") => Ok(serde_json::from_str(&fs::read_to_string(p)?)?),
Some("json") => Ok(ron::from_str(&fs::read_to_string(p)?)?),
e => Err(ConfigError::UnknownExtension(e.map(|v| v.to_owned()))),
}
}
}