use anyhow::Result;
use serde::Deserialize;
use std::fs::read_to_string;
use std::path::PathBuf;
use std::{collections::BTreeMap, path::Path};
pub const FILENAME: &str = "treefmt.toml";
pub const FILENAMEALT: &str = ".treefmt.toml";
#[derive(Debug, Deserialize)]
pub struct Root {
pub global: Option<GlobalConfig>,
pub formatter: BTreeMap<String, FmtConfig>,
}
#[derive(Debug, Deserialize)]
pub struct GlobalConfig {
#[serde(default)]
pub excludes: Vec<String>,
}
#[derive(Debug, Deserialize)]
pub struct FmtConfig {
pub command: String,
#[serde(default = "cwd")]
pub work_dir: PathBuf,
#[serde(default)]
pub options: Vec<String>,
#[serde(default)]
pub includes: Vec<String>,
#[serde(default)]
pub excludes: Vec<String>,
}
fn cwd() -> PathBuf {
".".into()
}
#[must_use]
pub fn lookup(dir: &Path) -> Option<PathBuf> {
let mut cwd = dir.to_path_buf();
loop {
let config_file = cwd.join(FILENAME);
let config_file_alt = cwd.join(FILENAMEALT);
if config_file.exists() {
return Some(config_file);
} else if config_file_alt.exists() {
return Some(config_file_alt);
}
cwd = match cwd.parent() {
Some(x) => x.to_path_buf(),
None => return None,
};
}
}
pub fn from_path(file_path: &Path) -> Result<Root> {
let content = read_to_string(file_path)?;
let ret: Root = toml::from_str(&content)?;
Ok(ret)
}