feat(config): read g:vimwiki_list on Neovim too (lazy.nvim drop-in)
CI / cargo fmt --check (push) Successful in 2m12s
CI / cargo clippy (push) Successful in 2m18s
CI / cargo test (push) Successful in 2m24s
CI / editor keymaps (push) Successful in 1m27s

The g:vimwiki_* drop-in was Vim-only: the Lua client read only setup()
opts and g:nuwiki_wikis, so swapping the vimwiki plugin for nuwiki under
lazy.nvim left the existing vim.g.vimwiki_list ignored and nuwiki pointed
at the default ~/vimwiki.

Mirror autoload/nuwiki/config.vim on the Lua side: config.lua now owns a
single resolver (M.wikis / M.scalar_globals) that resolves setup() wikis →
g:nuwiki_wikis → g:vimwiki_list (translating path->root, path_html->html_path,
template_*, ext->file_extension, …) and folds the global scalar defaults
(g:vimwiki_* then g:nuwiki_* then explicit setup() values; built-in defaults
excluded). lsp.lua (payload) and wiki_cfg/wiki_list (buffer commands) both
route through it, so the server and <Leader>ww agree on the wikis.

Extends test-global-shorthand (15 checks) with the vimwiki_list drop-in +
buffer-command resolution + native-wins cases. Config-parity goldens and
keymap harnesses green on both clients. README + known-issues updated
(drop-in is now Vim & Neovim).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 01:15:43 +00:00
parent 96d53dddf3
commit e6f400b370
5 changed files with 163 additions and 78 deletions
+110 -10
View File
@@ -114,15 +114,115 @@ function M.apply(user)
M.options = vim.tbl_deep_extend('force', M.defaults, user or {})
end
-- ===== Upstream vimwiki config compatibility (drop-in) =====
--
-- Single source of truth for the configured wikis, shared by the LSP payload
-- (lsp.lua) and the buffer-side commands. Mirrors autoload/nuwiki/config.vim so
-- a user who keeps their original vim.g.vimwiki_list + g:vimwiki_* config (e.g.
-- swapping the vimwiki plugin for nuwiki under lazy.nvim) needs no rewrite.
-- Native config (setup() wikis / g:nuwiki_*) always wins.
-- Upstream vimwiki per-wiki dict key -> nuwiki/server key.
local VIMWIKI_WIKI_MAP = {
path = 'root',
path_html = 'html_path',
template_path = 'template_path',
template_default = 'template_default',
template_ext = 'template_ext',
css_name = 'css_name',
auto_export = 'auto_export',
auto_toc = 'auto_toc',
syntax = 'syntax',
ext = 'file_extension',
index = 'index',
diary_rel_path = 'diary_rel_path',
diary_index = 'diary_index',
name = 'name',
}
-- Per-wiki settings that double as wiki-wide global defaults.
local SCALAR_GLOBAL_KEYS = {
'toc_header', 'toc_header_level', 'toc_link_format',
'links_header', 'links_header_level',
'tags_header', 'tags_header_level',
'html_header_numbering', 'html_header_numbering_sym',
'links_space_char', 'list_margin',
'listsyms', 'listsym_rejected',
'auto_export', 'auto_toc',
'auto_generate_links', 'auto_generate_tags', 'auto_diary_index',
}
-- Resolve the global scalar defaults applied to every wiki. Priority (low to
-- high): g:vimwiki_<key>, g:nuwiki_<key>, explicit setup() value. Built-in
-- defaults are excluded (reads M.user, not M.options) so they don't get folded
-- onto every wiki and override per-wiki values.
function M.scalar_globals()
local g = {}
for _, key in ipairs(SCALAR_GLOBAL_KEYS) do
if vim.g['vimwiki_' .. key] ~= nil then
g[key] = vim.g['vimwiki_' .. key]
end
if vim.g['nuwiki_' .. key] ~= nil then
g[key] = vim.g['nuwiki_' .. key]
end
if M.user[key] ~= nil then
g[key] = M.user[key]
end
end
return g
end
-- Translate vim.g.vimwiki_list into nuwiki's wiki list (server key names),
-- folding the global scalars into each entry. Returns {} when unset/malformed.
local function wikis_from_vimwiki(globals)
local list = vim.g.vimwiki_list
if type(list) ~= 'table' or vim.tbl_isempty(list) then
return {}
end
local out = {}
for _, vw in ipairs(list) do
if type(vw) == 'table' then
local w = vim.tbl_extend('force', {}, globals)
for src, dst in pairs(VIMWIKI_WIKI_MAP) do
if vw[src] ~= nil then
w[dst] = vw[src]
end
end
if w.root ~= nil then
table.insert(out, w)
end
end
end
return out
end
-- The configured wikis as normalized dicts (nuwiki/server key names), with the
-- global scalars folded in (per-wiki value wins). Priority:
-- 1. setup() opts.wikis
-- 2. g:nuwiki_wikis
-- 3. g:vimwiki_list (upstream drop-in)
-- Returns {} when none is set — callers fall back to the single-wiki shorthand.
function M.wikis()
local globals = M.scalar_globals()
local native = M.options.wikis or vim.g.nuwiki_wikis
if type(native) == 'table' and #native > 0 then
local out = {}
for i, w in ipairs(native) do
out[i] = vim.tbl_extend('force', globals, w)
end
return out
end
return wikis_from_vimwiki(globals)
end
-- Resolve the config for wiki #n (0-based) without touching the LSP.
-- Priority: setup() opts.wikis → g:nuwiki_wikis (VimL) → scalar opts/g: vars.
-- Returns { name, root, ext, idx, diary_rel, diary_idx }.
-- Returns { name, root, ext, idx, diary_rel, diary_idx, space }.
function M.wiki_cfg(n)
local opts = M.options
local wikis = opts.wikis or vim.g.nuwiki_wikis or nil
local w = wikis and wikis[(n or 0) + 1] or nil
local root = (w and w.root) or opts.wiki_root or vim.g.nuwiki_wiki_root or '~/vimwiki'
local ext = (w and w.file_extension) or opts.file_extension or vim.g.nuwiki_file_extension or '.wiki'
local wikis = M.wikis()
local w = wikis[(n or 0) + 1]
local root = (w and w.root) or M.options.wiki_root or vim.g.nuwiki_wiki_root or '~/vimwiki'
local ext = (w and w.file_extension) or M.options.file_extension
or vim.g.nuwiki_file_extension or '.wiki'
if not ext:match('^%.') then ext = '.' .. ext end
return {
name = (w and w.name) or vim.fn.fnamemodify(vim.fn.expand(root), ':t'),
@@ -131,7 +231,7 @@ function M.wiki_cfg(n)
idx = (w and w.index) or 'index',
diary_rel = (w and w.diary_rel_path) or vim.g.nuwiki_diary_rel_path or 'diary',
diary_idx = (w and w.diary_index) or 'diary',
space = (w and w.links_space_char) or opts.links_space_char
space = (w and w.links_space_char) or M.options.links_space_char
or vim.g.nuwiki_links_space_char or ' ',
}
end
@@ -139,9 +239,9 @@ end
-- The full list of configured wikis as wiki_cfg dicts. Falls back to a single
-- entry built from the scalar wiki_root config when no list is configured.
function M.wiki_list()
local wikis = M.options.wikis or vim.g.nuwiki_wikis or nil
local wikis = M.wikis()
local list = {}
if type(wikis) == 'table' and #wikis > 0 then
if #wikis > 0 then
for i = 1, #wikis do
list[i] = M.wiki_cfg(i - 1)
end
+13 -54
View File
@@ -14,63 +14,22 @@ local function command()
return { install.expected_path() }
end
-- Per-wiki settings that double as wiki-wide defaults (vimwiki-style global
-- shorthand): set once at the top level — via setup() or `g:nuwiki_<key>` —
-- and every wiki inherits it; a per-wiki value overrides. Mirrors the Vim
-- client's `s:scalar_global_map`.
local SCALAR_GLOBALS = {
'toc_header', 'toc_header_level', 'toc_link_format',
'links_header', 'links_header_level',
'tags_header', 'tags_header_level',
'html_header_numbering', 'html_header_numbering_sym',
'links_space_char', 'list_margin',
'listsyms', 'listsym_rejected',
'auto_export', 'auto_toc',
'auto_generate_links', 'auto_generate_tags', 'auto_diary_index',
}
-- Resolve the global scalar defaults from config the user *explicitly* set:
-- the raw setup() table first, then the `g:nuwiki_<key>` global. Built-in
-- defaults are deliberately excluded so they don't get folded into every wiki
-- (that would diverge from the Vim client and override per-wiki values with a
-- default).
local function scalar_globals()
local user = config.user or {}
local g = {}
for _, key in ipairs(SCALAR_GLOBALS) do
if user[key] ~= nil then
g[key] = user[key]
elseif vim.g['nuwiki_' .. key] ~= nil then
g[key] = vim.g['nuwiki_' .. key]
end
end
return g
end
-- Merge g:nuwiki_wikis (VimL config) into opts.wikis when the user has not
-- passed wikis through setup(). This lets users who configure via a .vim
-- file avoid duplicating the list in their Lua setup() call.
-- Build the server config payload. The wiki list comes from the shared
-- resolver (config.wikis) — native setup() wikis, g:nuwiki_wikis, or an
-- upstream g:vimwiki_list, with global scalar defaults already folded — so the
-- payload and the buffer-side commands agree on which wikis exist.
local function resolved_opts()
local opts = config.options
if not opts.wikis and vim.g.nuwiki_wikis then
opts = vim.tbl_extend('force', opts, { wikis = vim.g.nuwiki_wikis })
end
local globals = scalar_globals()
if vim.tbl_isempty(globals) then
return opts
end
if opts.wikis then
-- Fold the globals into each wiki as defaults (per-wiki value wins),
-- without mutating the user's setup table.
local folded = {}
for i, w in ipairs(opts.wikis) do
folded[i] = vim.tbl_extend('force', globals, w)
end
opts = vim.tbl_extend('force', opts, { wikis = folded })
local wikis = config.wikis()
if #wikis > 0 then
opts = vim.tbl_extend('force', opts, { wikis = wikis })
else
-- Single-wiki shorthand: ensure the globals (incl. the g:nuwiki_* form)
-- sit at the top level for the server's single-wiki desugaring.
opts = vim.tbl_extend('keep', opts, globals)
-- Single-wiki shorthand: fold the global scalars into the top-level payload
-- so the server's single-wiki desugaring honours them.
local globals = config.scalar_globals()
if not vim.tbl_isempty(globals) then
opts = vim.tbl_extend('keep', opts, globals)
end
end
return opts
end