e6f400b370
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>
269 lines
9.9 KiB
Lua
269 lines
9.9 KiB
Lua
-- lua/nuwiki/config.lua — defaults and user-config merge.
|
|
--
|
|
-- Keep this aligned with `doc/nuwiki.txt`.
|
|
|
|
local M = {}
|
|
|
|
M.defaults = {
|
|
-- Single-wiki shorthand. The server desugars these into a
|
|
-- one-entry `wikis = {…}` list. Use either this or the multi-wiki
|
|
-- form below; if both are set, `wikis` wins.
|
|
wiki_root = '~/vimwiki',
|
|
file_extension = '.wiki',
|
|
syntax = 'vimwiki',
|
|
log_level = 'warn',
|
|
|
|
-- Prefix for the global/buffer wiki command family (`<prefix>w`,
|
|
-- `<prefix>t`, `<prefix><Leader>w`, …). Mirrors vimwiki's
|
|
-- `g:vimwiki_map_prefix`. Vim users set `g:nuwiki_map_prefix` instead.
|
|
map_prefix = '<Leader>w',
|
|
|
|
-- Multi-wiki shape. Each entry honours every per-wiki key the
|
|
-- server understands. Leave nil to fall through to the shorthand
|
|
-- above.
|
|
--
|
|
-- Per-wiki keys (all optional, server defaults documented in
|
|
-- `doc/nuwiki.txt`):
|
|
-- name, root, file_extension, syntax, index
|
|
-- diary_rel_path, diary_index, diary_frequency,
|
|
-- diary_weekly_style, diary_start_week_day,
|
|
-- diary_caption_level, diary_sort, diary_header
|
|
-- html_path, template_path, template_default, template_ext,
|
|
-- template_date_format, css_name, auto_export, auto_toc,
|
|
-- auto_generate_links, auto_generate_tags, auto_diary_index,
|
|
-- html_filename_parameterization, exclude_files, color_dic,
|
|
-- custom_wiki2html, custom_wiki2html_args, base_url,
|
|
-- toc_header, toc_header_level, links_header, links_header_level,
|
|
-- tags_header, tags_header_level,
|
|
-- html_header_numbering, html_header_numbering_sym,
|
|
-- listsyms, listsym_rejected, listsyms_propagate, list_margin,
|
|
-- links_space_char
|
|
wikis = nil,
|
|
|
|
-- TOC defaults (per-wiki, also accepted as top-level for single-wiki setups)
|
|
toc_header = 'Contents',
|
|
toc_header_level = 1,
|
|
|
|
-- HTML export defaults (per-wiki, also accepted as top-level for single-wiki setups)
|
|
html_header_numbering = 0,
|
|
html_header_numbering_sym = '',
|
|
|
|
-- Per-buffer glue. Each subgroup mirrors vimwiki's
|
|
-- `g:vimwiki_key_mappings` shape and can be flipped off
|
|
-- independently to suppress that group of keymaps.
|
|
-- The <Leader>w prefix in wiki_prefix/links/html_export follows map_prefix.
|
|
mappings = {
|
|
enabled = true,
|
|
wiki_prefix = true, -- <Leader>w{w,t,s,i}, <Leader>w<Leader>{w,y,t,m,i}
|
|
links = true, -- <CR>, <S-CR>, <C-CR>, <C-S-CR>, <D-CR>, <M-CR>, <BS>, <Tab>, <S-Tab>, + (n/x), <Leader>w{n,d,r}, <Leader>wc (n/x)
|
|
lists = true, -- <C-Space>, gnt, gln, glp, glx, glh, gll, gLh, gLl, glr, gLr, gl{-,*,#,1,i,I,a,A}, gL{…}, gl, gL, o, O; insert <C-D>, <C-T>, <C-L><C-J/K/M>, <CR>
|
|
headers = true, -- =, -, ]], [[, ]=, [=, ]u, [u
|
|
table_editing = true, -- gqq, gq1, gww, gw1, <A-Left>, <A-Right>; insert <Tab>, <S-Tab>
|
|
diary = true, -- <C-Down>, <C-Up>
|
|
html_export = true, -- <Leader>wh, <Leader>whh, <Leader>wha
|
|
text_objects = true, -- ah, ih, aH, iH, al, il, a\, i\, ac, ic
|
|
mouse = false, -- <2-LeftMouse>, <S-2-LeftMouse>, <C-2-LeftMouse>, <MiddleMouse>, <RightMouse> (opt-in)
|
|
},
|
|
|
|
-- Folding. `'lsp'` uses the server's `foldingRange`
|
|
-- provider (Neovim 0.11+ wires it automatically). `'expr'` falls
|
|
-- back to a regex-based `foldexpr`. `'off'` skips folding setup.
|
|
folding = 'lsp',
|
|
|
|
-- vimwiki `autowriteall` (default on): while a wiki buffer is current,
|
|
-- mirror Vim's global `'autowriteall'` so a modified buffer auto-saves on
|
|
-- page switch / `:make` etc., restoring the prior value on leave.
|
|
autowriteall = true,
|
|
|
|
-- vimwiki `table_auto_fmt` (default on): re-align the table under the
|
|
-- cursor when leaving insert mode.
|
|
table_auto_fmt = true,
|
|
|
|
-- vimwiki `auto_chdir` (default off): `:lcd` into the owning wiki's root
|
|
-- when a wiki buffer becomes current.
|
|
auto_chdir = false,
|
|
|
|
-- vimwiki `auto_header` (default off): insert a level-1 header from the
|
|
-- filename on new wiki pages.
|
|
auto_header = false,
|
|
|
|
-- Broken-link diagnostic severity. Sent to the server, which downgrades
|
|
-- or suppresses the diagnostic accordingly.
|
|
-- 'off' | 'hint' | 'warn' | 'error'
|
|
diagnostic = {
|
|
link_severity = 'warn',
|
|
},
|
|
|
|
-- Calendar-vim integration. On by default — set to `false` to opt out.
|
|
-- When on, nuwiki detects calendar-vim on the runtimepath and wires
|
|
-- `g:calendar_action` / `g:calendar_sign` automatically.
|
|
-- Also respects `g:nuwiki_no_calendar` set before setup() to disable.
|
|
use_calendar = true,
|
|
}
|
|
|
|
M.options = vim.deepcopy(M.defaults)
|
|
|
|
-- The raw table the user passed to setup(), kept separate from the
|
|
-- defaults-merged `options`. Used to tell an explicitly-set value apart from
|
|
-- a built-in default — e.g. so the LSP client only treats a per-wiki key as a
|
|
-- global default when the user actually set it.
|
|
M.user = {}
|
|
|
|
function M.apply(user)
|
|
M.user = user or {}
|
|
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.
|
|
-- Returns { name, root, ext, idx, diary_rel, diary_idx, space }.
|
|
function M.wiki_cfg(n)
|
|
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'),
|
|
root = root,
|
|
ext = ext,
|
|
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 M.options.links_space_char
|
|
or vim.g.nuwiki_links_space_char or ' ',
|
|
}
|
|
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.wikis()
|
|
local list = {}
|
|
if #wikis > 0 then
|
|
for i = 1, #wikis do
|
|
list[i] = M.wiki_cfg(i - 1)
|
|
end
|
|
else
|
|
list[1] = M.wiki_cfg(0)
|
|
end
|
|
return list
|
|
end
|
|
|
|
-- Absolute root (trailing slash) of the wiki that owns `path`, or nil when the
|
|
-- file is under no configured wiki (callers no-op / fall back to CWD).
|
|
-- Used by auto_chdir + search scoping.
|
|
function M.wiki_root_for(path)
|
|
for _, w in ipairs(M.wiki_list()) do
|
|
local wroot = vim.fn.fnamemodify(vim.fn.expand(w.root), ':p')
|
|
if wroot:sub(-1) ~= '/' then wroot = wroot .. '/' end
|
|
if path:sub(1, #wroot) == wroot then
|
|
return wroot
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
return M
|