diff --git a/Cargo.lock b/Cargo.lock index 3e5aaa6..3f9fbea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1135,9 +1135,9 @@ checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "libcorn" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5684465f57a903e77cd58cc0bd9fcdc75b2b1a361731966183bf1f1743da4553" +checksum = "ec3c43083c921e27422ac8b8e96b75b55156cc1f6e176d9dbed0f02d57a86832" dependencies = [ "cfg-if", "pest", diff --git a/Cargo.toml b/Cargo.toml index d39641e..89361cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ serde = { version = "1.0.141", features = ["derive"] } serde_json = "1.0.82" serde_yaml = "0.9.4" toml = "0.5.9" -libcorn = "0.6.0" +libcorn = "0.6.1" lazy_static = "1.4.0" async_once = "0.2.6" indexmap = "1.9.1" diff --git a/src/config.rs b/src/config.rs index 9e96900..b619ef4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,7 +13,7 @@ use color_eyre::{eyre, Help, Report}; use dirs::config_dir; use eyre::Result; use gtk::Orientation; -use serde::Deserialize; +use serde::{Deserialize, Deserializer}; use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::{env, fs}; @@ -40,13 +40,44 @@ pub enum ModuleConfig { Custom(CustomModule), } -#[derive(Debug, Deserialize, Clone)] -#[serde(untagged)] +#[derive(Debug, Clone)] pub enum MonitorConfig { Single(Config), Multiple(Vec), } +// Manually implement for better untagged enum error handling: +// currently open pr: https://github.com/serde-rs/serde/pull/1544 +impl<'de> Deserialize<'de> for MonitorConfig { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + let content = + ::deserialize(deserializer)?; + + match ::deserialize( + serde::__private::de::ContentRefDeserializer::::new(&content), + ) { + Ok(config) => Ok(Self::Single(config)), + Err(outer) => match as serde::Deserialize>::deserialize( + serde::__private::de::ContentRefDeserializer::::new(&content), + ) { + Ok(config) => Ok(Self::Multiple(config)), + Err(inner) => { + let report = Report::msg(format!(" multi-bar (c): {inner}").replace("An error occurred when deserializing: ", "")) + .wrap_err(format!("single-bar (b): {outer}").replace("An error occurred when deserializing: ", "")) + .wrap_err("An invalid config was found. The following errors were encountered:") + .note("Both the single-bar (type b / error 1) and multi-bar (type c / error 2) config variants were tried. You can likely ignore whichever of these is not relevant to you.") + .suggestion("Please see https://github.com/JakeStanger/ironbar/wiki/configuration-guide#2-pick-your-use-case for more info on the above"); + + Err(serde::de::Error::custom(format!("{report:?}"))) + } + }, + } + } +} + #[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum BarPosition { @@ -111,7 +142,6 @@ const fn default_bar_height() -> i32 { impl Config { /// Attempts to load the config file from file, /// parse it and return a new instance of `Self`. - #[instrument] pub fn load() -> Result { let config_path = env::var("IRONBAR_CONFIG").map_or_else( |_| Self::try_find_config(),