hyprshell_config_lib/
save.rs

1use crate::Config;
2use anyhow::{Context, bail};
3use ron::Options;
4use ron::extensions::Extensions;
5use ron::ser::PrettyConfig;
6use std::ffi::OsStr;
7use std::fs::{File, create_dir_all};
8use std::io::Write;
9use std::path::Path;
10use tracing::{debug, debug_span, info};
11
12pub fn write_config(
13    config_path: &Path,
14    config: &Config,
15    override_file: bool,
16) -> anyhow::Result<()> {
17    let _span = debug_span!("write_config").entered();
18    let config_path_display = config_path.display();
19    if config_path.exists() && !override_file {
20        bail!(
21            "Config file at {config_path_display} already exists, delete it before generating a new one or use -f to override"
22        );
23    }
24    if let Some(parent) = config_path.parent() {
25        create_dir_all(parent)
26            .with_context(|| format!("Failed to create config dir at ({})", parent.display()))?;
27    }
28    let str = match config_path.extension().and_then(OsStr::to_str) {
29        None | Some("ron") => Options::default()
30            .with_default_extension(Extensions::IMPLICIT_SOME)
31            .with_default_extension(Extensions::UNWRAP_NEWTYPES)
32            .with_default_extension(Extensions::UNWRAP_VARIANT_NEWTYPES)
33            .to_string_pretty(config, PrettyConfig::default())
34            .with_context(|| format!("Failed to write RON config to ({config_path_display})")),
35        Some("json5" | "json") => {
36            serde_json::to_string_pretty(config).context("Failed to generate JSON config")
37        }
38        Some("toml") => toml::to_string_pretty(config).context("Failed to generate TOML config"),
39        Some(ext) => bail!(
40            "Invalid config file extension: {ext} (run with -vv and check `FEATURES: ` debug log to see enabled extensions)"
41        ),
42    }?;
43    let mut file = File::create(config_path)
44        .with_context(|| format!("Failed to create config file at ({config_path_display})"))?;
45    file.write_all(str.as_bytes())
46        .with_context(|| format!("Failed to write to config file at ({config_path_display})"))
47        .inspect_err(|_| {
48            info!("New config contents: {config:?}");
49        })?;
50
51    debug!("Config file written successfully at {config_path_display}");
52    Ok(())
53}