aboutsummaryrefslogtreecommitdiff
path: root/src/config/write.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config/write.rs')
-rw-r--r--src/config/write.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/config/write.rs b/src/config/write.rs
new file mode 100644
index 00000000..75244583
--- /dev/null
+++ b/src/config/write.rs
@@ -0,0 +1,75 @@
+#[derive(Clone, Copy)]
+pub(crate) enum ConfigEdit<'a> {
+ Theme(&'a str),
+ StatusIndicators(super::StatusIndicatorStyle),
+ Sound(bool),
+ ToastDelivery(super::ToastDelivery),
+}
+
+impl ConfigEdit<'_> {
+ pub(crate) fn description(self) -> &'static str {
+ match self {
+ Self::Theme(_) => "theme",
+ Self::StatusIndicators(_) => "status indicators",
+ Self::Sound(_) => "sound setting",
+ Self::ToastDelivery(_) => "toast setting",
+ }
+ }
+
+ pub(crate) fn apply(self, content: &str) -> String {
+ match self {
+ Self::Theme(name) => {
+ let content =
+ super::upsert_section_value(content, "theme", "name", &format!("\"{name}\""));
+ super::upsert_section_bool(&content, "theme", "auto_switch", false)
+ }
+ Self::StatusIndicators(style) => super::upsert_section_value(
+ content,
+ "ui",
+ "status_indicators",
+ &format!("\"{}\"", style.as_str()),
+ ),
+ Self::Sound(enabled) => {
+ super::upsert_section_bool(content, "ui.sound", "enabled", enabled)
+ }
+ Self::ToastDelivery(delivery) => {
+ let value = match delivery {
+ super::ToastDelivery::Off => "\"off\"",
+ super::ToastDelivery::Herdr => "\"herdr\"",
+ super::ToastDelivery::Terminal => "\"terminal\"",
+ super::ToastDelivery::System => "\"system\"",
+ };
+ let content = super::upsert_section_value(content, "ui.toast", "delivery", value);
+ super::remove_section_key(&content, "ui.toast", "enabled")
+ }
+ }
+ }
+}
+
+pub(crate) fn update_file_at(
+ path: &std::path::Path,
+ description: &str,
+ update: impl FnOnce(&str) -> String,
+) -> Result<(), String> {
+ if let Some(parent) = path.parent() {
+ std::fs::create_dir_all(parent)
+ .map_err(|error| format!("failed to create config directory: {error}"))?;
+ }
+ let content = match std::fs::read_to_string(path) {
+ Ok(content) => content,
+ Err(error) if error.kind() == std::io::ErrorKind::NotFound => String::new(),
+ Err(error) => {
+ return Err(format!(
+ "failed to read config before saving {description}: {error}"
+ ));
+ }
+ };
+ std::fs::write(path, update(&content))
+ .map_err(|error| format!("failed to save {description}: {error}"))
+}
+
+pub(crate) fn write_edit(edit: ConfigEdit<'_>) -> Result<(), String> {
+ update_file_at(&super::config_path(), edit.description(), |content| {
+ edit.apply(content)
+ })
+}