perfectstar2k 0.1.1

A modern TUI homage to WordStar & WordPerfect for DOS — a real writing tool built on WordStar's touch-typist command language and long-hand-page metaphor.
//! User configuration — the tool adapts to the writer.
//! `~/.config/perfectstar2k/config.toml` (or the platform equivalent).

use std::path::PathBuf;

use serde::{Deserialize, Serialize};

use crate::theme::Theme;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Config {
    /// "wp-blue", "wordstar", or "terminal".
    pub theme: String,
    /// How long a prefix key waits before its menu appears.
    pub menu_delay_ms: u64,
    /// Seconds of idle time before a dirty buffer autosaves; 0 disables.
    pub autosave_secs: u64,
    /// Soft word wrap on startup.
    pub wrap: bool,
    /// Wrap margin in columns; 0 wraps at the window width.
    pub wrap_margin: usize,
    /// 0 = clean screen (no menus), 1 = delayed menus, 2 = menus + hint bar.
    pub help_level: u8,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            theme: String::from("wp-blue"),
            menu_delay_ms: 700,
            autosave_secs: 60,
            wrap: true,
            wrap_margin: 0,
            help_level: 1,
        }
    }
}

fn config_path() -> Option<PathBuf> {
    Some(dirs::config_dir()?.join("perfectstar2k").join("config.toml"))
}

impl Config {
    pub fn load() -> Self {
        let Some(path) = config_path() else {
            return Config::default();
        };
        match std::fs::read_to_string(&path) {
            Ok(data) => toml::from_str(&data).unwrap_or_default(),
            Err(_) => Config::default(),
        }
    }

    pub fn theme(&self) -> Theme {
        match self.theme.as_str() {
            "wordstar" => Theme::wordstar(),
            "terminal" => Theme::terminal_default(),
            _ => Theme::wp_blue(),
        }
    }
}