hyprshell-config-lib 4.10.0

A library for reading, writing and migrating configuration files for hyprshell
Documentation
use crate::Config;
use anyhow::bail;

pub fn check(config: &Config) -> anyhow::Result<()> {
    if config
        .windows
        .as_ref()
        .is_some_and(|w| w.general.scale >= 15f64 || w.general.scale <= 0f64)
    {
        bail!("Scale factor must be less than 15 and greater than 0");
    }

    if config
        .windows
        .as_ref()
        .and_then(|w| w.overview.as_ref())
        .is_some_and(|o| matches!(&*o.key, "super" | "alt" | "control" | "ctrl"))
    {
        bail!(
            "If a modifier key is used to open it must include _l or _r at the end. (e.g. super_l, alt_r, etc)\nctrl_l / _r is NOT a valid modifier key, only control_l / _r is"
        );
    }

    if let Some(l) = &config
        .windows
        .as_ref()
        .and_then(|w| w.overview.as_ref().map(|o| &o.launcher))
    {
        if let Some(dt) = &l.default_terminal
            && dt.is_empty()
        {
            bail!("Default terminal command cannot be empty");
        }

        let mut used: Vec<char> = vec![];
        for engine in l
            .plugins
            .websearch
            .as_ref()
            .map_or(&vec![], |ws| &ws.engines)
        {
            if engine.url.is_empty() {
                bail!("Search engine url cannot be empty");
            }
            if engine.name.is_empty() {
                bail!("Search engine name cannot be empty");
            }
            if used.contains(&engine.key) {
                bail!("Duplicate search engine key: {}", engine.key);
            }
            used.push(engine.key);
        }
        if l.plugins.calc.is_some() {
            #[cfg(not(feature = "launcher_calc_plugin"))]
            {
                bail!("Calc Plugin enabled but not compiled in, please enable the calc feature");
            }
        }
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::structs::*;

    fn full() -> Config {
        Config {
            windows: Some(Windows {
                overview: Some(Overview::default()),
                switch: Some(Switch::default()),
                ..Default::default()
            }),
            ..Default::default()
        }
    }

    #[test_log::test]
    #[test_log(default_log_filter = "trace")]
    fn test_valid_config() {
        let config = full();
        println!("{:?}", check(&config));
        assert!(check(&config).is_ok());
    }

    #[test_log::test]
    #[test_log(default_log_filter = "trace")]
    fn test_invalid_scale() {
        let mut config = full();
        config
            .windows
            .as_mut()
            .expect("config option missing")
            .general
            .scale = 20.0;
        assert!(check(&config).is_err());
        config
            .windows
            .as_mut()
            .expect("config option missing")
            .general
            .scale = 0.0;
        assert!(check(&config).is_err());
    }

    #[test_log::test]
    #[test_log(default_log_filter = "trace")]
    fn test_invalid_key() {
        let mut config = full();
        let overview = config
            .windows
            .as_mut()
            .expect("config option missing")
            .overview
            .as_mut()
            .expect("config option missing");
        overview.key = Box::from("super");
        assert!(check(&config).is_err());
    }

    #[test_log::test]
    #[test_log(default_log_filter = "trace")]
    fn test_duplicate_engine_key() {
        let mut config = full();
        let launcher = &mut config
            .windows
            .as_mut()
            .expect("config option missing")
            .overview
            .as_mut()
            .expect("config option missing")
            .launcher;
        if let Some(ws) = launcher.plugins.websearch.as_mut() {
            ws.engines.push(SearchEngine {
                key: 'g',
                name: Box::from("Google2"),
                url: Box::from("https://google2.com"),
            });
        }
        assert!(check(&config).is_err());
    }

    #[test_log::test]
    #[test_log(default_log_filter = "trace")]
    fn test_empty_engine_url() {
        let mut config = full();
        let launcher = &mut config
            .windows
            .as_mut()
            .expect("config option missing")
            .overview
            .as_mut()
            .expect("config option missing")
            .launcher;
        if let Some(ws) = launcher.plugins.websearch.as_mut() {
            ws.engines[0].url = Box::from("");
        }
        assert!(check(&config).is_err());
    }

    #[test_log::test]
    #[test_log(default_log_filter = "trace")]
    fn test_empty_engine_name() {
        let mut config = full();
        let launcher = &mut config
            .windows
            .as_mut()
            .expect("config option missing")
            .overview
            .as_mut()
            .expect("config option missing")
            .launcher;
        if let Some(ws) = launcher.plugins.websearch.as_mut() {
            ws.engines[0].name = Box::from("");
        }
        assert!(check(&config).is_err());
    }

    #[test_log::test]
    #[test_log(default_log_filter = "trace")]
    fn test_empty_terminal() {
        let mut config = full();
        let launcher = &mut config
            .windows
            .as_mut()
            .expect("config option missing")
            .overview
            .as_mut()
            .expect("config option missing")
            .launcher;
        launcher.default_terminal = Some(Box::from(""));
        assert!(check(&config).is_err());
    }
}