use crate::{
PrompterError, collect_profiles, library_dir, load_config_bundle, resolve_config_path,
};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone)]
pub struct ProfileDef {
pub(crate) deps: Vec<String>,
pub(crate) library_root: PathBuf,
}
#[derive(Debug)]
pub struct Config {
pub(crate) profiles: HashMap<String, ProfileDef>,
pub(crate) post_prompt: Option<String>,
}
impl Config {
#[must_use]
pub fn library_roots(&self) -> Vec<PathBuf> {
let mut roots: Vec<PathBuf> = Vec::new();
for def in self.profiles.values() {
if !roots.contains(&def.library_root) {
roots.push(def.library_root.clone());
}
}
roots.sort();
roots
}
}
pub(crate) fn load_bundle(
config_override: Option<&Path>,
) -> Result<(PathBuf, Config), PrompterError> {
let cfg_path = resolve_config_path(config_override)?;
let default_library = if config_override.is_some() {
None
} else {
Some(library_dir()?)
};
let cfg = load_config_bundle(&cfg_path, default_library.as_deref())?;
Ok((cfg_path, cfg))
}
#[derive(Debug)]
pub(crate) struct RawConfigFile {
pub(crate) profiles: HashMap<String, Vec<String>>,
pub(crate) imports: Vec<String>,
pub(crate) library: Option<String>,
pub(crate) post_prompt: Option<String>,
}
pub(crate) fn parse_config_file(input: &str) -> Result<RawConfigFile, PrompterError> {
let table: toml::Table = toml::from_str(input)?;
let mut raw = RawConfigFile {
profiles: HashMap::new(),
imports: Vec::new(),
library: None,
post_prompt: None,
};
for (key, value) in &table {
match key.as_str() {
"import" => {
let arr = value.as_array().ok_or_else(|| {
PrompterError::ConfigField("`import` must be an array of strings".to_string())
})?;
for entry in arr {
let s = entry.as_str().ok_or_else(|| {
PrompterError::ConfigField("`import` entries must be strings".to_string())
})?;
raw.imports.push(s.to_string());
}
}
"library" => {
let s = value.as_str().ok_or_else(|| {
PrompterError::ConfigField("`library` must be a string".to_string())
})?;
raw.library = Some(s.to_string());
}
"post_prompt" => {
let s = value.as_str().ok_or_else(|| {
PrompterError::ConfigField("`post_prompt` must be a string".to_string())
})?;
raw.post_prompt = Some(s.to_string());
}
_ => collect_profiles(key, value, &mut raw.profiles)?,
}
}
Ok(raw)
}