swaycons 0.3.1

swaycons adds nerd font icons to sway window titles
Documentation
use std::collections::HashMap;
use config::{Config, ConfigError, File, FileFormat, Value};
use xdg::BaseDirectories;

#[derive(Clone, Debug)]
pub struct GlobalSettings {
    pub color: String,
    pub focused_color: Option<String>,
    pub icon: String,
    pub size: String,
    pub separator: String,
}

impl GlobalSettings {
    pub fn new(
        color: String,
        focused_color: Option<String>,
        icon: String,
        size: String,
        separator: String,
    ) -> GlobalSettings {
        GlobalSettings {
            color,
            focused_color,
            icon,
            size,
            separator,
        }
    }

    pub fn from(mut config: HashMap<String, String>) -> GlobalSettings {
        let color = config.remove("color").unwrap();
        let focused_color = match config.remove("focused_color") {
            Some(color) => if color.len() == 7 && color.starts_with("#") {
                Some(color)
            } else {
                None
            },
            None => None
        };
        let icon = config.remove("icon").unwrap();
        let size = config.remove("size").unwrap();
        let separator = config
            .remove("separator")
            .unwrap_or(String::from(" "));
        GlobalSettings {
            color,
            focused_color,
            icon,
            size,
            separator,
        }
    }
}

#[derive(Clone, Debug)]
pub struct BaseSettings {
    pub color: Option<String>,
    pub icon: Option<String>,
    pub size: Option<String>,
}

impl BaseSettings {
    pub fn new(mut config: HashMap<String, Value>) -> BaseSettings {
        let color = match config.remove("color") {
            Some(color) => match color.into_str() {
                Ok(color) => Some(color),
                Err(_e) => None,
            },
            None => None,
        };
        let icon = match config.remove("icon") {
            Some(icon) => match icon.into_str() {
                Ok(icon) => Some(icon),
                Err(_e) => None,
            },
            None => None,
        };
        let size = match config.remove("size") {
            Some(size) => match size.into_str() {
                Ok(size) => Some(size),
                Err(_e) => None,
            },
            None => None,
        };
        BaseSettings { color, icon, size }
    }
}

#[derive(Clone, Debug)]
pub struct TitleSettings {
    pub app_id: Option<Vec<String>>,
    pub base: BaseSettings,
}

impl TitleSettings {
    pub fn new(mut config: HashMap<String, Value>) -> TitleSettings {
        let app_id: Option<Vec<String>> = match config.remove("app_id") {
            Some(app_id) => {
                match app_id.try_into() {
                    Ok(app_id) => Some(app_id),
                    Err(_e) => None,
                }
            }
            None => None,
        };
        let base = BaseSettings::new(config);
        TitleSettings { app_id, base }
    }
}

#[derive(Clone, Debug)]
pub struct Settings {
    pub global: GlobalSettings,
    pub title: HashMap<String, TitleSettings>,
    pub app_id: HashMap<String, BaseSettings>,
}

static DEFAULT_SETTINGS: &str = include_str!(r"./config.toml");

pub fn get_settings() -> Result<Settings, ConfigError> {
    let xdg_dirs = BaseDirectories::with_prefix("swaycons").unwrap();
    let config_path = xdg_dirs
        .place_config_file("config.toml").unwrap();
    let mut settings = Config::new();
    settings.merge(File::from_str(DEFAULT_SETTINGS, FileFormat::Toml))?;
    settings.merge(File::from(config_path).required(false))?;
    let global_map: HashMap<String, String> = settings.get("global").unwrap();
    let global = GlobalSettings::from(global_map);
    let title_config: HashMap<String, HashMap<String, Value>> = settings.get("title").unwrap();
    let mut title = HashMap::new();
    for (key, value) in title_config {
        title.insert(key, TitleSettings::new(value));
    }
    let mut app_id = HashMap::new();
    let app_id_config: HashMap<String, HashMap<String, Value>> = settings.get("app_id").unwrap();
    for (key, value) in app_id_config {
        app_id.insert(key, BaseSettings::new(value));
    }
    Ok(Settings {
        global,
        title,
        app_id
    })
}