clone
ssh://git@git.notashelf.dev:33/notashelf/beer.gitCommit 27a509362bd3
tarballunverified3 files changed+57-11
@@ -42,6 +42,7 @@ dependencies = [ "pound", "rustix", "serde",+ "serde_ignored", "smithay-client-toolkit", "thiserror", "toml",@@ -489,6 +490,16 @@ dependencies = [ ] [[package]]+name = "serde_ignored"+version = "0.1.14"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "115dffd5f3853e06e746965a20dcbae6ee747ae30b543d91b0e089668bb07798"+dependencies = [+ "serde",+ "serde_core",+]++[[package]] name = "serde_spanned" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index"@@ -23,6 +23,7 @@ rustix = { version = "1.1.4", features = [ "fs", ] } serde = { version = "1.0.228", features = ["derive"] }+serde_ignored = "0.1.12" smithay-client-toolkit = "0.20.0" thiserror = "2.0.18" toml = "0.9"@@ -195,19 +195,32 @@ impl Config { if !path.exists() { return Self::default(); }- match std::fs::read_to_string(&path) {- Ok(text) => match toml::from_str(&text) {- Ok(config) => {- tracing::info!("loaded config from {}", path.display());- config- }- Err(err) => {- tracing::warn!("config {}: {err}; using defaults", path.display());- Self::default()- }- },+ let text = match std::fs::read_to_string(&path) {+ Ok(text) => text, Err(err) => { tracing::warn!("read config {}: {err}; using defaults", path.display());+ return Self::default();+ }+ };+ // Deserialize through serde_ignored so a typo'd key (`font-sze`) is+ // reported instead of silently dropped, while still loading: unknown+ // keys stay tolerated, keeping forward-compatibility with newer configs.+ let de = match toml::Deserializer::parse(&text) {+ Ok(de) => de,+ Err(err) => {+ tracing::warn!("config {}: {err}; using defaults", path.display());+ return Self::default();+ }+ };+ match serde_ignored::deserialize(de, |key| {+ tracing::warn!("config {}: unknown key `{key}` ignored", path.display());+ }) {+ Ok(config) => {+ tracing::info!("loaded config from {}", path.display());+ config+ }+ Err(err) => {+ tracing::warn!("config {}: {err}; using defaults", path.display()); Self::default() } }@@ -253,4 +266,25 @@ mod tests { assert_eq!(c.main.term, "beer"); assert_eq!(c.scrollback.lines, 10_000); }++ #[test]+ fn unknown_keys_are_reported_but_still_load() {+ let toml = r##"+ [main]+ font-sze = 14+ font = "JetBrains Mono"++ [made-up]+ x = 1+ "##;+ let mut unknown = Vec::new();+ let de = toml::Deserializer::parse(toml).unwrap();+ let c: Config =+ serde_ignored::deserialize(de, |key| unknown.push(key.to_string())).unwrap();+ // The typo and the bogus table are both surfaced...+ assert!(unknown.iter().any(|k| k == "main.font-sze"), "{unknown:?}");+ assert!(unknown.iter().any(|k| k == "made-up"), "{unknown:?}");+ // ...yet the valid key still loaded.+ assert_eq!(c.main.font, "JetBrains Mono");+ } }