From 6ae642dbee41fa03f4dac9e5d036b81333c4bf0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Fr=C3=B3es=20Franco?= Date: Thu, 21 May 2026 23:24:51 -0300 Subject: [PATCH] fix(config): unwrap {nuwiki:{...}} wrapper in apply_change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit workspace/didChangeConfiguration settings from Neovim arrive as { "nuwiki": { "wiki_root": ..., "wikis": [...] } } because server_settings() in lua/nuwiki/lsp.lua wraps the payload in a "nuwiki" namespace key. apply_change() was trying to deserialise that outer object directly as InitOptions, which always succeeded but produced all-None fields (unknown keys are ignored by serde), so every settings refresh was silently dropped. Unwrap single-key objects whose value is also an object before deserialising — this handles the Neovim wrapper while keeping the flat VimL shape working unchanged. Co-Authored-By: Claude Sonnet 4.6 --- crates/nuwiki-lsp/src/config.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/nuwiki-lsp/src/config.rs b/crates/nuwiki-lsp/src/config.rs index 9871c15..a8f1aa1 100644 --- a/crates/nuwiki-lsp/src/config.rs +++ b/crates/nuwiki-lsp/src/config.rs @@ -367,8 +367,21 @@ impl Config { /// Re-apply settings received via `workspace/didChangeConfiguration`. /// On parse failure the existing config is returned unchanged. + /// + /// Accepts both the flat shape (`{ "wikis": [...] }`) produced by the + /// VimL client, **and** the Neovim-style wrapper (`{ "nuwiki": { ... } }`) + /// that `server_settings()` in `lua/nuwiki/lsp.lua` produces. Any other + /// single-key object whose value is an object is also unwrapped so + /// editors that namespace settings by server name continue to work. pub fn apply_change(&mut self, value: &serde_json::Value) { - let raw: InitOptions = match serde_json::from_value(value.clone()) { + // Unwrap { "nuwiki": { ... } } → { ... } so both clients work. + let inner = value + .as_object() + .and_then(|m| if m.len() == 1 { m.values().next() } else { None }) + .filter(|v| v.is_object()) + .unwrap_or(value); + + let raw: InitOptions = match serde_json::from_value(inner.clone()) { Ok(r) => r, Err(_) => return, };