rumk 0.0.1

A fast linter for Makefiles
Documentation
use crate::rules::{self, Rule};
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::{Path, PathBuf};

pub struct Config {
    pub rules: Vec<Box<dyn Rule>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuleConfig {
    pub enabled: bool,
    pub severity: Option<String>,
    pub options: HashMap<String, toml::Value>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct IgnoreConfig {
    pub paths: Vec<String>,
    pub rules: Vec<String>,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            rules: rules::get_default_rules(),
        }
    }
}

impl Config {
    pub fn from_file(path: &Path) -> Result<Self> {
        let content = std::fs::read_to_string(path)
            .with_context(|| format!("Failed to read config file: {}", path.display()))?;

        let toml_config: TomlConfig = toml::from_str(&content)
            .with_context(|| format!("Failed to parse config file: {}", path.display()))?;

        Ok(toml_config.into_config())
    }

    pub fn find_and_load() -> Result<Self> {
        let possible_paths = [
            PathBuf::from(".rumk.toml"),
            PathBuf::from("rumk.toml"),
            PathBuf::from(".config/rumk.toml"),
        ];

        for path in &possible_paths {
            if path.exists() {
                return Self::from_file(path);
            }
        }

        Ok(Self::default())
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct TomlConfig {
    #[serde(default)]
    rules: HashMap<String, RuleConfig>,

    #[serde(default)]
    ignore: IgnoreConfig,
}

impl TomlConfig {
    fn into_config(self) -> Config {
        let mut rules = Vec::new();
        let all_rules = rules::get_all_rules();

        for rule in all_rules {
            let rule_id = rule.id();

            if let Some(config) = self.rules.get(rule_id) {
                if config.enabled {
                    rules.push(rule);
                }
            } else {
                rules.push(rule);
            }
        }

        Config { rules }
    }
}