use std::path::{Path, PathBuf};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LogDirSource {
EnvVar,
Home,
StateDir,
CurrentDir,
None,
}
impl std::fmt::Display for LogDirSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::EnvVar => write!(f, "ALC_LOG_DIR"),
Self::Home => write!(f, "~/.algocline/logs"),
Self::StateDir => write!(f, "state_dir"),
Self::CurrentDir => write!(f, "current_dir"),
Self::None => write!(f, "none (stderr only)"),
}
}
}
#[derive(Clone, Debug)]
pub struct AppConfig {
pub log_dir: Option<PathBuf>,
pub log_dir_source: LogDirSource,
pub log_enabled: bool,
}
impl AppConfig {
pub fn from_env() -> Self {
let (log_dir, log_dir_source) = Self::resolve_log_dir();
let log_enabled = std::env::var("ALC_LOG_LEVEL")
.map(|v| v.to_lowercase() != "off")
.unwrap_or(true);
Self {
log_dir,
log_dir_source,
log_enabled,
}
}
fn resolve_log_dir() -> (Option<PathBuf>, LogDirSource) {
if let Ok(dir) = std::env::var("ALC_LOG_DIR") {
let path = PathBuf::from(dir);
if Self::ensure_dir(&path) {
return (Some(path), LogDirSource::EnvVar);
}
}
if let Some(home) = dirs::home_dir() {
let path = home.join(".algocline").join("logs");
if Self::ensure_dir(&path) {
return (Some(path), LogDirSource::Home);
}
}
if let Some(state) = dirs::state_dir() {
let path = state.join("algocline").join("logs");
if Self::ensure_dir(&path) {
return (Some(path), LogDirSource::StateDir);
}
}
if let Ok(cwd) = std::env::current_dir() {
let path = cwd.join("algocline-logs");
if Self::ensure_dir(&path) {
return (Some(path), LogDirSource::CurrentDir);
}
}
(None, LogDirSource::None)
}
fn ensure_dir(path: &Path) -> bool {
std::fs::create_dir_all(path).is_ok() && path.is_dir()
}
}