fix(vim): buffer commands honour g:vimwiki_list (<Leader>ww opened ~/vimwiki)
The g:vimwiki_* drop-in only fed the LSP payload (lsp.vim s:settings). The buffer-side commands — <Leader>ww (wiki_index), :VimwikiSearch, auto_chdir, diary, completion — resolve the wiki list independently via s:wiki_cfg / nuwiki#commands#wiki_list, which read only g:nuwiki_wikis / g:nuwiki_wiki_root. So with a g:vimwiki_list config the server knew the wikis but <Leader>ww fell back to the default ~/vimwiki and opened an empty index. Extract the resolution into a single source of truth, autoload/nuwiki/config.vim (nuwiki#config#wikis / #scalar_globals), which resolves g:nuwiki_wikis or an upstream g:vimwiki_list and folds the global scalar defaults. lsp.vim (payload), commands.vim, and diary.vim all route through it — also dedups the s:wiki_cfg copy that lived in both commands.vim and diary.vim. Regression guard in test-vimwiki-compat-vim: nuwiki#commands#wiki_list() must resolve the g:vimwiki_list roots (21 checks). All Vim harnesses + config-parity goldens green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -588,14 +588,13 @@ endfunction
|
||||
" open their wiki from any buffer. Files are opened directly from config;
|
||||
" the LSP auto-starts via the FileType autocmd once the buffer loads.
|
||||
|
||||
" Return a dict with {root, ext, idx, diary_rel, diary_idx} for wiki #n
|
||||
" (0-based). Prefers g:nuwiki_wikis[n]; falls back to scalar g:nuwiki_*
|
||||
" vars and finally to built-in defaults.
|
||||
" Return a dict with {root, ext, idx, diary_rel, diary_idx, space} for wiki #n
|
||||
" (0-based). Resolves through nuwiki#config#wikis() — so g:nuwiki_wikis AND an
|
||||
" upstream g:vimwiki_list both work — and falls back to the scalar g:nuwiki_*
|
||||
" vars (single-wiki shorthand) and finally built-in defaults.
|
||||
function! s:wiki_cfg(n) abort
|
||||
let l:w = {}
|
||||
if exists('g:nuwiki_wikis') && len(g:nuwiki_wikis) > a:n
|
||||
let l:w = g:nuwiki_wikis[a:n]
|
||||
endif
|
||||
let l:wikis = nuwiki#config#wikis()
|
||||
let l:w = (a:n >= 0 && a:n < len(l:wikis)) ? l:wikis[a:n] : {}
|
||||
let l:root = expand(get(l:w, 'root',
|
||||
\ get(g:, 'nuwiki_wiki_root', '~/vimwiki')))
|
||||
let l:ext = get(l:w, 'file_extension',
|
||||
@@ -612,14 +611,15 @@ function! s:wiki_cfg(n) abort
|
||||
endfunction
|
||||
|
||||
" Build the list of configured wikis as {name, root, ext, idx, diary_rel,
|
||||
" diary_idx} dicts, straight from config — no LSP round-trip. Drives the wiki
|
||||
" picker so it works before any wiki buffer (and therefore the server) exists.
|
||||
" Falls back to a single entry from the scalar `g:nuwiki_wiki_root` config.
|
||||
" diary_idx, space} dicts, straight from config — no LSP round-trip. Drives the
|
||||
" wiki picker so it works before any wiki buffer (and therefore the server)
|
||||
" exists. Falls back to a single entry from the scalar `g:nuwiki_wiki_root`.
|
||||
function! nuwiki#commands#wiki_list() abort
|
||||
let l:wikis = nuwiki#config#wikis()
|
||||
let l:list = []
|
||||
if exists('g:nuwiki_wikis') && !empty(g:nuwiki_wikis)
|
||||
if !empty(l:wikis)
|
||||
let l:n = 0
|
||||
for l:w in g:nuwiki_wikis
|
||||
for l:w in l:wikis
|
||||
let l:c = s:wiki_cfg(l:n)
|
||||
let l:c['name'] = get(l:w, 'name', fnamemodify(l:c.root, ':t'))
|
||||
call add(l:list, l:c)
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
" autoload/nuwiki/config.vim — single source of truth for the configured wiki
|
||||
" list, shared by the LSP payload (lsp.vim) and the buffer-side commands
|
||||
" (commands.vim, diary.vim, complete.vim).
|
||||
"
|
||||
" Resolves wikis from g:nuwiki_wikis (native) or, when that's unset, an upstream
|
||||
" g:vimwiki_list (drop-in compatibility), translating upstream key names and
|
||||
" folding the global scalar defaults (g:vimwiki_* / g:nuwiki_*) into each entry.
|
||||
" Everything downstream — `<Leader>ww`, link resolution, the server payload —
|
||||
" then sees the same wikis.
|
||||
|
||||
" Per-wiki dict keys: upstream `g:vimwiki_list[i]` key -> nuwiki/server key.
|
||||
let s: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',
|
||||
\ }
|
||||
|
||||
" Global scalar settings vimwiki applies to every wiki (via wikilocal
|
||||
" defaults): upstream suffix (`g:vimwiki_<suffix>`) -> nuwiki/server key.
|
||||
let s:scalar_global_map = {
|
||||
\ 'toc_header': 'toc_header',
|
||||
\ 'toc_header_level': 'toc_header_level',
|
||||
\ 'toc_link_format': 'toc_link_format',
|
||||
\ 'links_header': 'links_header',
|
||||
\ 'links_header_level': 'links_header_level',
|
||||
\ 'tags_header': 'tags_header',
|
||||
\ 'tags_header_level': 'tags_header_level',
|
||||
\ 'html_header_numbering': 'html_header_numbering',
|
||||
\ 'html_header_numbering_sym': 'html_header_numbering_sym',
|
||||
\ 'links_space_char': 'links_space_char',
|
||||
\ 'list_margin': 'list_margin',
|
||||
\ 'listsyms': 'listsyms',
|
||||
\ 'listsym_rejected': 'listsym_rejected',
|
||||
\ 'auto_export': 'auto_export',
|
||||
\ 'auto_toc': 'auto_toc',
|
||||
\ 'auto_generate_links': 'auto_generate_links',
|
||||
\ 'auto_generate_tags': 'auto_generate_tags',
|
||||
\ 'auto_diary_index': 'auto_diary_index',
|
||||
\ }
|
||||
|
||||
" Resolve the per-wiki scalar globals: vimwiki values first (compat), then
|
||||
" nuwiki-native `g:nuwiki_<key>` overrides on top.
|
||||
function! nuwiki#config#scalar_globals() abort
|
||||
let l:g = {}
|
||||
for [l:src, l:dst] in items(s:scalar_global_map)
|
||||
if exists('g:vimwiki_' . l:src)
|
||||
let l:g[l:dst] = get(g:, 'vimwiki_' . l:src)
|
||||
endif
|
||||
endfor
|
||||
for l:dst in values(s:scalar_global_map)
|
||||
if exists('g:nuwiki_' . l:dst)
|
||||
let l:g[l:dst] = get(g:, 'nuwiki_' . l:dst)
|
||||
endif
|
||||
endfor
|
||||
return l:g
|
||||
endfunction
|
||||
|
||||
" Translate an upstream g:vimwiki_list into nuwiki's wiki list, folding the
|
||||
" given global scalars into each entry. Returns [] when unset/malformed.
|
||||
function! s:wikis_from_vimwiki(globals) abort
|
||||
if !exists('g:vimwiki_list') || type(g:vimwiki_list) != type([]) || empty(g:vimwiki_list)
|
||||
return []
|
||||
endif
|
||||
let l:wikis = []
|
||||
for l:vw in g:vimwiki_list
|
||||
if type(l:vw) != type({}) | continue | endif
|
||||
let l:w = copy(a:globals)
|
||||
for [l:src, l:dst] in items(s:vimwiki_wiki_map)
|
||||
if has_key(l:vw, l:src)
|
||||
let l:w[l:dst] = l:vw[l:src]
|
||||
endif
|
||||
endfor
|
||||
if has_key(l:w, 'root')
|
||||
call add(l:wikis, l:w)
|
||||
endif
|
||||
endfor
|
||||
return l:wikis
|
||||
endfunction
|
||||
|
||||
" The configured wikis as normalized dicts (nuwiki/server key names), with the
|
||||
" global scalar defaults folded in (per-wiki value wins). Priority:
|
||||
" 1. g:nuwiki_wikis (native)
|
||||
" 2. g:vimwiki_list (upstream drop-in)
|
||||
" Returns [] when neither is set — callers fall back to the single-wiki
|
||||
" shorthand (g:nuwiki_wiki_root).
|
||||
function! nuwiki#config#wikis() abort
|
||||
let l:globals = nuwiki#config#scalar_globals()
|
||||
if exists('g:nuwiki_wikis') && !empty(g:nuwiki_wikis)
|
||||
return map(copy(g:nuwiki_wikis), {_, w -> extend(copy(l:globals), w, 'force')})
|
||||
endif
|
||||
return s:wikis_from_vimwiki(l:globals)
|
||||
endfunction
|
||||
@@ -75,13 +75,12 @@ function! nuwiki#diary#calendar_sign(day, month, year) abort
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
" Helper: get wiki configuration for wiki n (0-based).
|
||||
" Mirrors the same logic used by nuwiki#commands#open_diary_path etc.
|
||||
" Helper: get wiki configuration for wiki n (0-based). Resolves through
|
||||
" nuwiki#config#wikis() so g:nuwiki_wikis AND an upstream g:vimwiki_list both
|
||||
" work, falling back to the scalar g:nuwiki_* single-wiki shorthand.
|
||||
function! s:wiki_cfg(n) abort
|
||||
let l:w = {}
|
||||
if exists('g:nuwiki_wikis') && len(g:nuwiki_wikis) > a:n
|
||||
let l:w = g:nuwiki_wikis[a:n]
|
||||
endif
|
||||
let l:wikis = nuwiki#config#wikis()
|
||||
let l:w = (a:n >= 0 && a:n < len(l:wikis)) ? l:wikis[a:n] : {}
|
||||
let l:root = expand(get(l:w, 'root',
|
||||
\ get(g:, 'nuwiki_wiki_root', '~/vimwiki')))
|
||||
let l:ext = get(l:w, 'file_extension',
|
||||
|
||||
+9
-113
@@ -12,97 +12,6 @@ let s:plugin_root = fnamemodify(resolve(expand('<sfile>:p')), ':h:h:h')
|
||||
|
||||
let s:started = 0
|
||||
|
||||
" ===== Upstream vimwiki config compatibility =====
|
||||
"
|
||||
" nuwiki is a drop-in vimwiki replacement, so a user who keeps their original
|
||||
" `g:vimwiki_list` + `g:vimwiki_*` globals shouldn't have to rewrite anything.
|
||||
" These tables translate the upstream names into the server's config schema.
|
||||
" nuwiki-native config (`g:nuwiki_wikis` / `g:nuwiki_*`) always wins.
|
||||
|
||||
" Per-wiki dict keys: upstream `g:vimwiki_list[i]` key -> server key.
|
||||
let s: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',
|
||||
\ }
|
||||
|
||||
" Global scalar settings vimwiki applies to every wiki (via wikilocal
|
||||
" defaults): upstream suffix (`g:vimwiki_<suffix>`) -> server key. The server
|
||||
" reads these per-wiki, so we fold them into each wiki entry (and into the
|
||||
" single-wiki shorthand payload).
|
||||
let s:scalar_global_map = {
|
||||
\ 'toc_header': 'toc_header',
|
||||
\ 'toc_header_level': 'toc_header_level',
|
||||
\ 'toc_link_format': 'toc_link_format',
|
||||
\ 'links_header': 'links_header',
|
||||
\ 'links_header_level': 'links_header_level',
|
||||
\ 'tags_header': 'tags_header',
|
||||
\ 'tags_header_level': 'tags_header_level',
|
||||
\ 'html_header_numbering': 'html_header_numbering',
|
||||
\ 'html_header_numbering_sym': 'html_header_numbering_sym',
|
||||
\ 'links_space_char': 'links_space_char',
|
||||
\ 'list_margin': 'list_margin',
|
||||
\ 'listsyms': 'listsyms',
|
||||
\ 'listsym_rejected': 'listsym_rejected',
|
||||
\ 'auto_export': 'auto_export',
|
||||
\ 'auto_toc': 'auto_toc',
|
||||
\ 'auto_generate_links': 'auto_generate_links',
|
||||
\ 'auto_generate_tags': 'auto_generate_tags',
|
||||
\ 'auto_diary_index': 'auto_diary_index',
|
||||
\ }
|
||||
|
||||
" Resolve the per-wiki scalar globals: vimwiki values first (compat), then
|
||||
" nuwiki-native `g:nuwiki_<key>` overrides on top.
|
||||
function! s:scalar_globals() abort
|
||||
let l:g = {}
|
||||
for [l:src, l:dst] in items(s:scalar_global_map)
|
||||
if exists('g:vimwiki_' . l:src)
|
||||
let l:g[l:dst] = get(g:, 'vimwiki_' . l:src)
|
||||
endif
|
||||
endfor
|
||||
for l:dst in values(s:scalar_global_map)
|
||||
if exists('g:nuwiki_' . l:dst)
|
||||
let l:g[l:dst] = get(g:, 'nuwiki_' . l:dst)
|
||||
endif
|
||||
endfor
|
||||
return l:g
|
||||
endfunction
|
||||
|
||||
" Build nuwiki's `wikis` list from an upstream `g:vimwiki_list`, folding the
|
||||
" global scalar settings into each entry. Returns [] when unset/malformed.
|
||||
function! s:wikis_from_vimwiki() abort
|
||||
if !exists('g:vimwiki_list') || type(g:vimwiki_list) != type([]) || empty(g:vimwiki_list)
|
||||
return []
|
||||
endif
|
||||
let l:globals = s:scalar_globals()
|
||||
let l:wikis = []
|
||||
for l:vw in g:vimwiki_list
|
||||
if type(l:vw) != type({}) | continue | endif
|
||||
let l:w = copy(l:globals)
|
||||
for [l:src, l:dst] in items(s:vimwiki_wiki_map)
|
||||
if has_key(l:vw, l:src)
|
||||
let l:w[l:dst] = l:vw[l:src]
|
||||
endif
|
||||
endfor
|
||||
" A wiki needs a root; skip entries without one.
|
||||
if has_key(l:w, 'root')
|
||||
call add(l:wikis, l:w)
|
||||
endif
|
||||
endfor
|
||||
return l:wikis
|
||||
endfunction
|
||||
|
||||
function! nuwiki#lsp#start() abort
|
||||
if s:started
|
||||
return
|
||||
@@ -225,29 +134,16 @@ function! s:settings() abort
|
||||
\ 'link_severity': get(g:, 'nuwiki_link_severity', 'warn'),
|
||||
\ },
|
||||
\ }
|
||||
" Global scalar settings (g:vimwiki_* then g:nuwiki_* overrides) act as
|
||||
" defaults applied to every wiki, vimwiki-style. A per-wiki value always
|
||||
" wins. Resolved once and folded into whichever wiki shape we send.
|
||||
let l:globals = s:scalar_globals()
|
||||
|
||||
" Wiki list resolution, in priority order:
|
||||
" 1. g:nuwiki_wikis (native multi-wiki config)
|
||||
" 2. g:vimwiki_list (upstream vimwiki config — drop-in compat)
|
||||
" 3. wiki_root shorthand (single wiki)
|
||||
" Without a list the server only sees wiki_root and resolves links relative
|
||||
" to that directory instead of each individual wiki's root.
|
||||
if exists('g:nuwiki_wikis') && !empty(g:nuwiki_wikis)
|
||||
let l:cfg['wikis'] = map(copy(g:nuwiki_wikis),
|
||||
\ {_, w -> extend(copy(l:globals), w, 'force')})
|
||||
" Wiki list comes from the shared resolver (nuwiki#config#wikis), so the
|
||||
" server payload and the buffer-side commands agree on which wikis exist —
|
||||
" native g:nuwiki_wikis or an upstream g:vimwiki_list, globals already folded.
|
||||
let l:wikis = nuwiki#config#wikis()
|
||||
if !empty(l:wikis)
|
||||
let l:cfg['wikis'] = l:wikis
|
||||
else
|
||||
let l:vw_wikis = s:wikis_from_vimwiki()
|
||||
if !empty(l:vw_wikis)
|
||||
let l:cfg['wikis'] = l:vw_wikis
|
||||
else
|
||||
" Single-wiki shorthand: fold the global scalars into the top-level
|
||||
" payload so the server's single-wiki desugaring honours them.
|
||||
call extend(l:cfg, l:globals, 'force')
|
||||
endif
|
||||
" Single-wiki shorthand: fold the global scalars into the top-level payload
|
||||
" so the server's single-wiki desugaring honours them.
|
||||
call extend(l:cfg, nuwiki#config#scalar_globals(), 'force')
|
||||
endif
|
||||
return l:cfg
|
||||
endfunction
|
||||
|
||||
Reference in New Issue
Block a user