hyprshell_config_lib/
save.rs1use 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
12const CONFIG_EXPLANATION: &str = "Edit with `hyprshell config edit`";
13
14pub fn write_config(
15 config_file: &Path,
16 config: &Config,
17 override_file: bool,
18) -> anyhow::Result<()> {
19 let _span = debug_span!("write_config").entered();
20 let config_file_display = config_file.display();
21 if config_file.exists() && !override_file {
22 bail!(
23 "Config file at {config_file_display} already exists, delete it before generating a new one or use -f to override"
24 );
25 }
26 if let Some(parent) = config_file.parent() {
27 create_dir_all(parent)
28 .with_context(|| format!("Failed to create config dir at ({})", parent.display()))?;
29 }
30 let str = match config_file.extension().and_then(OsStr::to_str) {
31 None | Some("ron") => Options::default()
32 .with_default_extension(Extensions::IMPLICIT_SOME)
33 .with_default_extension(Extensions::UNWRAP_NEWTYPES)
34 .with_default_extension(Extensions::UNWRAP_VARIANT_NEWTYPES)
35 .to_string_pretty(config, PrettyConfig::default())
36 .with_context(|| format!("Failed to write RON config to ({config_file_display})")),
37 Some("json5" | "json") => {
38 serde_json::to_string_pretty(config).context("Failed to generate JSON config")
39 }
40 Some("toml") => toml::to_string_pretty(config).context("Failed to generate TOML config"),
41 Some(ext) => bail!(
42 "Invalid config file extension: {ext} (run with -vv and check `FEATURES: ` debug log to see enabled extensions)"
43 ),
44 }?;
45 #[allow(clippy::match_same_arms)]
46 let header = match config_file.extension().and_then(OsStr::to_str) {
47 None | Some("ron") => format!("// {CONFIG_EXPLANATION}"),
48 Some("json5") => format!("// {CONFIG_EXPLANATION}"),
49 Some("toml") => format!("# {CONFIG_EXPLANATION}"),
50 _ => String::new(),
51 };
52 let content = format!("{header}\n{str}");
53 let mut file = File::create(config_file)
54 .with_context(|| format!("Failed to create config file at ({config_file_display})"))?;
55 file.write_all(content.as_bytes())
56 .with_context(|| format!("Failed to write to config file at ({config_file_display})"))
57 .inspect_err(|_| {
58 info!("New config contents: {config:?}");
59 })?;
60
61 debug!("Config file written successfully at {config_file_display}");
62 Ok(())
63}