2025-03-18 16:00:57 +13:00

93 lines
2.7 KiB
Rust

use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ConfigError {
#[error("Failed to read config file: {0}")]
FileRead(#[from] std::io::Error),
#[error("Failed to parse config file: {0}")]
Parse(#[from] toml::ser::Error),
#[error("Failed to parse config file: {0}")]
ParseDeserialise(#[from] toml::de::Error),
#[error("Failed to write config file: {0}")]
FileWrite(std::io::Error),
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct Config {
// theme = grey / night / day / catppuccin_mocha
pub default: bool,
pub theme: String,
// bind = "Delete"
pub bind: String,
pub shift_enter_newline: bool,
}
// this is hack as fvck
// allows for removing the "default" line entirely
// basically if "default" is missing from the config then infer as false (hide default warning)
impl Default for Config {
fn default() -> Self {
Config {
default: false,
..Self::default()
}
}
}
impl Config {
// Provide default values
pub fn default() -> Self {
Self {
default: true,
theme: "grey".to_string(),
bind: "Delete".to_string(),
shift_enter_newline: true,
}
}
// Load config from a file, creating it with defaults if it doesn't exist
pub fn load_or_create(path: PathBuf) -> Result<Self, ConfigError> {
let full_path = path.join("config.toml");
// create a file with using the default config if it does not exist
if !full_path.exists() {
println!("Creating default config");
let config = Self::default();
fs::create_dir_all(&path)?;
config.save(&full_path)?;
return Ok(config);
}
println!("Loading default config from {full_path:?}");
let content = fs::read_to_string(&full_path)?;
let config: Config = toml::from_str(&content)?;
Ok(config)
}
// Save config to a file
pub fn save(&self, path: &PathBuf) -> Result<(), ConfigError> {
let content = toml::to_string_pretty(&self).map_err(|e| ConfigError::Parse(e))?;
fs::write(path, content).map_err(ConfigError::FileWrite)?;
// Ensure proper permissions on Unix-like systems
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mut perms = fs::metadata(path)
.map_err(ConfigError::FileWrite)?
.permissions();
perms.set_mode(0o600); // Read/write for owner only
fs::set_permissions(path, perms).map_err(ConfigError::FileWrite)?;
}
Ok(())
}
}