feat(lsp): wire diary/auto_toc/links_space_char/list_margin; drop client-side keys
Consume several per-wiki config keys that the server deserialized but
ignored, and remove keys whose effect is purely client-side:
- diagnostics: re-publish open-doc diagnostics on
didChangeConfiguration so a link_severity change takes effect
immediately; fix the single-key unwrap in apply_change so a minimal
`{ diagnostic: {...} }` payload isn't mistaken for a namespace wrapper.
- auto_toc: rebuild an existing TOC section on save (new
ops::toc_rebuild_edit, no-op when the page has no TOC).
- diary index: honour diary_header, diary_sort and diary_caption_level
when rendering the diary index body.
- links_space_char: apply on rename so spaces in the link target and
the on-disk path become the configured glyph (default " " = verbatim).
- list_margin: thread the per-wiki value into render_page_html.
- remove nested_syntaxes, maxhi and diary_start_week_day from the server
config: nested-syntax and heading highlighting are client-side, and
the weekly diary is ISO-week based so a custom week start has no clean
server-side meaning.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -41,9 +41,6 @@ pub struct WikiConfig {
|
||||
/// diary commands use. `daily` is supported; the others fall through
|
||||
/// to vimwiki-style names but the commands are no-ops for them.
|
||||
pub diary_frequency: String,
|
||||
/// First day of the week (`monday`..`sunday`). Used by weekly
|
||||
/// diary entry naming.
|
||||
pub diary_start_week_day: String,
|
||||
/// Caption level for the diary index page headings (1 = h1).
|
||||
pub diary_caption_level: u8,
|
||||
/// Newest-first (`desc`) or oldest-first (`asc`) in the diary
|
||||
@@ -51,10 +48,6 @@ pub struct WikiConfig {
|
||||
pub diary_sort: String,
|
||||
/// H1 text for the diary index page.
|
||||
pub diary_header: String,
|
||||
/// Maximum heading level treated as a *navigation* anchor — beyond
|
||||
/// it the LSP doesn't synthesise an anchor symbol. Matches
|
||||
/// vimwiki's `g:vimwiki_maxhi` (default `1`).
|
||||
pub maxhi: u8,
|
||||
/// Vimwiki's `g:vimwiki_listsyms`. The 5-character string maps
|
||||
/// fractional progress states for checkboxes; the i-th char (0..=4)
|
||||
/// is the rendered marker for state `i / 4`. Default: `" .oOX"`.
|
||||
@@ -68,9 +61,6 @@ pub struct WikiConfig {
|
||||
/// targets when writing to disk (a single space `" "` by default,
|
||||
/// i.e. spaces are kept verbatim).
|
||||
pub links_space_char: String,
|
||||
/// `nested_syntaxes` — code-block language → editor filetype map
|
||||
/// used for syntax-highlighting fenced blocks. Empty by default.
|
||||
pub nested_syntaxes: std::collections::HashMap<String, String>,
|
||||
/// Rebuild the page's TOC on save when set.
|
||||
pub auto_toc: bool,
|
||||
/// HTML export options.
|
||||
@@ -183,16 +173,13 @@ impl WikiConfig {
|
||||
diary_rel_path: d.diary_rel_path,
|
||||
diary_index: d.diary_index,
|
||||
diary_frequency: d.diary_frequency,
|
||||
diary_start_week_day: d.diary_start_week_day,
|
||||
diary_caption_level: d.diary_caption_level,
|
||||
diary_sort: d.diary_sort,
|
||||
diary_header: d.diary_header,
|
||||
maxhi: d.maxhi,
|
||||
listsyms: d.listsyms,
|
||||
listsyms_propagate: d.listsyms_propagate,
|
||||
list_margin: d.list_margin,
|
||||
links_space_char: d.links_space_char,
|
||||
nested_syntaxes: d.nested_syntaxes,
|
||||
auto_toc: d.auto_toc,
|
||||
html: HtmlConfig::default(),
|
||||
}
|
||||
@@ -213,16 +200,13 @@ impl WikiConfig {
|
||||
diary_rel_path: d.diary_rel_path,
|
||||
diary_index: d.diary_index,
|
||||
diary_frequency: d.diary_frequency,
|
||||
diary_start_week_day: d.diary_start_week_day,
|
||||
diary_caption_level: d.diary_caption_level,
|
||||
diary_sort: d.diary_sort,
|
||||
diary_header: d.diary_header,
|
||||
maxhi: d.maxhi,
|
||||
listsyms: d.listsyms,
|
||||
listsyms_propagate: d.listsyms_propagate,
|
||||
list_margin: d.list_margin,
|
||||
links_space_char: d.links_space_char,
|
||||
nested_syntaxes: d.nested_syntaxes,
|
||||
auto_toc: d.auto_toc,
|
||||
html,
|
||||
}
|
||||
@@ -278,10 +262,6 @@ fn default_diary_frequency() -> String {
|
||||
"daily".to_string()
|
||||
}
|
||||
|
||||
fn default_diary_start_week_day() -> String {
|
||||
"monday".to_string()
|
||||
}
|
||||
|
||||
fn default_diary_sort() -> String {
|
||||
"desc".to_string()
|
||||
}
|
||||
@@ -307,16 +287,13 @@ fn wiki_defaults() -> WikiDefaults {
|
||||
diary_rel_path: default_diary_rel_path(),
|
||||
diary_index: default_diary_index(),
|
||||
diary_frequency: default_diary_frequency(),
|
||||
diary_start_week_day: default_diary_start_week_day(),
|
||||
diary_caption_level: 1,
|
||||
diary_sort: default_diary_sort(),
|
||||
diary_header: default_diary_header(),
|
||||
maxhi: 1,
|
||||
listsyms: default_listsyms(),
|
||||
listsyms_propagate: true,
|
||||
list_margin: -1,
|
||||
links_space_char: default_links_space_char(),
|
||||
nested_syntaxes: std::collections::HashMap::new(),
|
||||
auto_toc: false,
|
||||
}
|
||||
}
|
||||
@@ -326,16 +303,13 @@ struct WikiDefaults {
|
||||
diary_rel_path: String,
|
||||
diary_index: String,
|
||||
diary_frequency: String,
|
||||
diary_start_week_day: String,
|
||||
diary_caption_level: u8,
|
||||
diary_sort: String,
|
||||
diary_header: String,
|
||||
maxhi: u8,
|
||||
listsyms: String,
|
||||
listsyms_propagate: bool,
|
||||
list_margin: i32,
|
||||
links_space_char: String,
|
||||
nested_syntaxes: std::collections::HashMap<String, String>,
|
||||
auto_toc: bool,
|
||||
}
|
||||
|
||||
@@ -389,16 +363,15 @@ impl Config {
|
||||
/// editors that namespace settings by server name continue to work.
|
||||
pub fn apply_change(&mut self, value: &serde_json::Value) {
|
||||
// Unwrap { "nuwiki": { ... } } → { ... } so both clients work.
|
||||
// Only unwrap when the lone key isn't itself a recognised top-level
|
||||
// setting — otherwise a minimal payload like
|
||||
// `{ "diagnostic": { ... } }` would be mistaken for a namespace
|
||||
// wrapper and its contents silently dropped.
|
||||
let inner = value
|
||||
.as_object()
|
||||
.and_then(|m| {
|
||||
if m.len() == 1 {
|
||||
m.values().next()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|v| v.is_object())
|
||||
.and_then(|m| if m.len() == 1 { m.iter().next() } else { None })
|
||||
.filter(|(k, v)| v.is_object() && !is_init_option_key(k))
|
||||
.map(|(_, v)| v)
|
||||
.unwrap_or(value);
|
||||
|
||||
let raw: InitOptions = match serde_json::from_value(inner.clone()) {
|
||||
@@ -460,6 +433,17 @@ mod opt_bool_or_int {
|
||||
}
|
||||
}
|
||||
|
||||
/// Recognised top-level keys in the flat `initializationOptions` shape.
|
||||
/// Used to tell a real single-key payload (e.g. `{ "diagnostic": {…} }`)
|
||||
/// apart from an editor namespace wrapper (e.g. `{ "nuwiki": {…} }`) in
|
||||
/// [`Config::apply_change`].
|
||||
fn is_init_option_key(key: &str) -> bool {
|
||||
matches!(
|
||||
key,
|
||||
"wikis" | "wiki_root" | "file_extension" | "syntax" | "log_level" | "diagnostic"
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
#[serde(default, rename_all = "snake_case")]
|
||||
struct InitOptions {
|
||||
@@ -532,16 +516,12 @@ struct RawWiki {
|
||||
#[serde(default)]
|
||||
diary_frequency: Option<String>,
|
||||
#[serde(default)]
|
||||
diary_start_week_day: Option<String>,
|
||||
#[serde(default)]
|
||||
diary_caption_level: Option<u8>,
|
||||
#[serde(default)]
|
||||
diary_sort: Option<String>,
|
||||
#[serde(default)]
|
||||
diary_header: Option<String>,
|
||||
#[serde(default)]
|
||||
maxhi: Option<u8>,
|
||||
#[serde(default)]
|
||||
listsyms: Option<String>,
|
||||
#[serde(default, deserialize_with = "opt_bool_or_int::deserialize")]
|
||||
listsyms_propagate: Option<bool>,
|
||||
@@ -549,8 +529,6 @@ struct RawWiki {
|
||||
list_margin: Option<i32>,
|
||||
#[serde(default)]
|
||||
links_space_char: Option<String>,
|
||||
#[serde(default)]
|
||||
nested_syntaxes: Option<std::collections::HashMap<String, String>>,
|
||||
#[serde(default, deserialize_with = "opt_bool_or_int::deserialize")]
|
||||
auto_toc: Option<bool>,
|
||||
}
|
||||
@@ -603,16 +581,13 @@ impl From<RawWiki> for WikiConfig {
|
||||
diary_rel_path: r.diary_rel_path.unwrap_or(d.diary_rel_path),
|
||||
diary_index: r.diary_index.unwrap_or(d.diary_index),
|
||||
diary_frequency: r.diary_frequency.unwrap_or(d.diary_frequency),
|
||||
diary_start_week_day: r.diary_start_week_day.unwrap_or(d.diary_start_week_day),
|
||||
diary_caption_level: r.diary_caption_level.unwrap_or(d.diary_caption_level),
|
||||
diary_sort: r.diary_sort.unwrap_or(d.diary_sort),
|
||||
diary_header: r.diary_header.unwrap_or(d.diary_header),
|
||||
maxhi: r.maxhi.unwrap_or(d.maxhi),
|
||||
listsyms: r.listsyms.unwrap_or(d.listsyms),
|
||||
listsyms_propagate: r.listsyms_propagate.unwrap_or(d.listsyms_propagate),
|
||||
list_margin: r.list_margin.unwrap_or(d.list_margin),
|
||||
links_space_char: r.links_space_char.unwrap_or(d.links_space_char),
|
||||
nested_syntaxes: r.nested_syntaxes.unwrap_or(d.nested_syntaxes),
|
||||
auto_toc: r.auto_toc.unwrap_or(d.auto_toc),
|
||||
html,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user