iris-reader 1.0.0

A terminal-native viewer for documents, structured data, images, PDFs, databases, and stdin.
Documentation
use std::{fs, path::PathBuf};

use anyhow::{Context, Result};
use serde::Deserialize;

use crate::{cli::Cli, options::IconMode};

#[derive(Debug, Clone, Deserialize)]
#[serde(default)]
pub struct Config {
    pub theme: String,
    pub wrap: bool,
    pub tab_width: usize,
    pub icons: IconMode,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            theme: "ember".to_string(),
            wrap: true,
            tab_width: 4,
            icons: IconMode::NerdFont,
        }
    }
}

impl Config {
    pub fn load() -> Result<Self> {
        let Some(path) = config_path() else {
            return Ok(Self::default());
        };

        if !path.exists() {
            return Ok(Self::default());
        }

        let source = fs::read_to_string(&path)
            .with_context(|| format!("failed to read config '{}'", path.display()))?;
        let mut config: Self = toml::from_str(&source)
            .with_context(|| format!("invalid config '{}'", path.display()))?;
        config.tab_width = config.tab_width.clamp(1, 16);
        Ok(config)
    }

    pub fn apply_cli(mut self, cli: &Cli) -> Self {
        if let Some(theme) = &cli.theme {
            self.theme = theme.clone();
        }
        if cli.wrap {
            self.wrap = true;
        }
        if cli.no_wrap {
            self.wrap = false;
        }
        if let Some(icons) = cli.icons {
            self.icons = icons;
        }
        self
    }
}

pub fn config_path() -> Option<PathBuf> {
    dirs::config_dir().map(|dir| dir.join("iris").join("config.toml"))
}