Add lenient_config to ignore unknown config fields instead of failing - #73
Open
HoneyHazard wants to merge 1 commit into
Open
Add lenient_config to ignore unknown config fields instead of failing#73HoneyHazard wants to merge 1 commit into
HoneyHazard wants to merge 1 commit into
Conversation
Every config struct currently uses #[serde(deny_unknown_fields)], so any unrecognized field anywhere in wiremix.toml - a typo, or a key from a newer/older wiremix version, including this fork's own not-yet-upstream keys - makes wiremix refuse to start at all, with no way to opt out. Adds a lenient_config config option (default false) with matching --lenient-config/--no-lenient-config CLI flags. When enabled, unknown fields are logged as warnings and ignored instead of erroring, using serde_ignored to collect every ignored field path across the whole file in one pass (not just the first one hit) regardless of nesting depth, so --lenient-config's warning output and the default strict error message both report everything at once. Requires removing #[serde(deny_unknown_fields)] from the individual structs, since serde_ignored's callback only fires for fields a struct's own Deserialize impl would otherwise silently drop - deny_unknown_fields makes that struct error out before serde_ignored ever sees it, bypassing the lenient/strict decision entirely. The one exception is the test-only strict::ConfigFile used to validate the shipped example wiremix.toml stays exhaustive - that one keeps deny_unknown_fields since catching drift there is its whole purpose.
HoneyHazard
marked this pull request as ready for review
August 10, 2026 05:16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
That being said, I hope these can be helpful and useful additions that users could appreciate.
Every config struct currently uses
#[serde(deny_unknown_fields)], so any unrecognized field anywhere inwiremix.toml- a typo, or a key from a different wiremix version than the config was written for - makes wiremix refuse to start at all, with no way to opt out. This came up concretely on my own machine: I keep a couple of not-yet-upstream fork-only theme keys (row_selected,row_unselected) in my config, and anything invoking stock/usr/bin/wiremixdirectly (bypassingPATH) would fail outright rather than just not styling those rows.This adds a
lenient_configconfig option (defaultfalse, so today's strict-by-default behavior is unchanged) with matching--lenient-config/--no-lenient-configCLI flags, following the same pattern asmouse/--mouse/--no-mouseand friends. When enabled, unknown fields are logged as warnings and ignored instead of erroring:serde_ignoredcrate to collect every ignored field's path across the whole file in one pass - not just the first one hit - regardless of nesting depth (themes.default.foo,[[keybindings]]entries, etc.), so both the default strict error and--lenient-config's warnings report everything at once rather than one-at-a-time-per-run.#[serde(deny_unknown_fields)]from the individual structs (ConfigFile,Keybinding,Names,Filter,ThemeOverlay,StyleDef,CharSetOverlay, and the raw struct behindNameOverride's customDeserializeimpl) -serde_ignored's callback only fires for fields a struct's ownDeserializeimpl would otherwise silently drop, anddeny_unknown_fieldsmakes that struct hard error beforeserde_ignoredever gets a chance to see it, bypassing the lenient/strict decision entirely.strict::ConfigFileused to validate that the shipped examplewiremix.tomldocuments every field exhaustively - that one keepsdeny_unknown_fields, since catching drift there is its whole purpose and has nothing to do with runtime behavior.Tested:
cargo test --release: 147/147 passing (includes new tests for: unknown fields at the top level, inside[[keybindings]],[names]/[[names.overrides]],[themes.*], and[char_sets.*]all still erroring by default;lenient_config = truein the file and--lenient-configon the CLI both suppressing the error;--no-lenient-configoverriding alenient_config = trueset in the file back to strict)cargo fmt --check/cargo clippy --release --all-targets -- -D warnings/cargo doc --no-deps(matching this repo's CI): all clean--lenient-config; alenient_config = trueline in the config file has the same effect, and--no-lenient-configon the command line correctly overrides that back to strict