feat(coc): auto-register the language server with coc.nvim
coc users had to hand-maintain a coc-settings.json `languageserver.nuwiki`
entry, which didn't track g:nuwiki_wikis / g:vimwiki_list / the global
shorthand and meant editing JSON per wiki. nuwiki now registers itself
programmatically: on the first .wiki buffer it calls
coc#config('languageserver.nuwiki', {…}) with the s:settings() payload
(same config the vim-lsp path sends). coc reacts to the languageserver
config change (onDidChangeConfiguration → registerClientsByConfig) and
starts the server for the open buffer.
Details:
- Reliable coc detection via :CocConfig (exists('*coc#config') can't be
trusted — it doesn't trigger autoload in Vim 9.2). The coc#config call
is wrapped in try/catch and autoloads coc.vim itself; falls back to the
printed snippet only if coc genuinely isn't there.
- Deferred to User CocNvimInit when coc's node service isn't up yet.
- Opt out with g:nuwiki_no_coc_register (then we just print the snippet).
Dogfooded in start-vim-coc.sh: dropped the manual coc-settings.json
languageserver block; the harness now relies on auto-registration from
g:nuwiki_* (real-user flow). New harness test-coc-register-vim (7 checks,
stubbed coc#config) asserts the injected payload incl. the folded global
shorthand; wired into CI. README coc section rewritten (zero-config).
Rust 573 passed, clippy clean, all harnesses green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+61
-16
@@ -136,22 +136,7 @@ function! nuwiki#lsp#start() abort
|
||||
endif
|
||||
|
||||
if exists(':CocConfig') == 2 || exists('*coc#config')
|
||||
" coc.nvim — coc reads its server list from coc-settings.json.
|
||||
" We can't inject it dynamically without owning the file, so just point
|
||||
" the user at the snippet. `initializationOptions` carries wiki_root etc.
|
||||
" to the server exactly like the vim-lsp registration above — without it
|
||||
" the server resolves links against its default root, so existing pages
|
||||
" look broken and follow-to-create lands in the wrong directory.
|
||||
echohl WarningMsg
|
||||
echom 'nuwiki: coc.nvim detected. Add this to your coc-settings.json:'
|
||||
echom ' "languageserver": {'
|
||||
echom ' "nuwiki": {'
|
||||
echom ' "command": "' . l:bin . '",'
|
||||
echom ' "filetypes": ["vimwiki"],'
|
||||
echom ' "initializationOptions": ' . json_encode(s:settings())
|
||||
echom ' }'
|
||||
echom ' }'
|
||||
echohl None
|
||||
call s:register_with_coc(l:bin)
|
||||
return
|
||||
endif
|
||||
|
||||
@@ -162,6 +147,66 @@ function! nuwiki#lsp#start() abort
|
||||
echohl None
|
||||
endfunction
|
||||
|
||||
" ===== coc.nvim integration =====
|
||||
"
|
||||
" Register the nuwiki language server with coc *programmatically* via
|
||||
" coc#config, so users don't have to hand-maintain a coc-settings.json entry
|
||||
" per wiki. The config (wiki roots, per-wiki keys, the vimwiki/nuwiki global
|
||||
" shorthand) comes from s:settings() — the same payload the vim-lsp path sends.
|
||||
" coc reacts to the `languageserver` config change, registers the server, and
|
||||
" starts it for the open vimwiki buffer.
|
||||
"
|
||||
" Opt out with `let g:nuwiki_no_coc_register = 1` to manage the entry in
|
||||
" coc-settings.json yourself (we then just print the snippet).
|
||||
function! s:register_with_coc(bin) abort
|
||||
if get(g:, 'nuwiki_no_coc_register', 0)
|
||||
call s:print_coc_snippet(a:bin)
|
||||
return
|
||||
endif
|
||||
let s:coc_bin = a:bin
|
||||
if get(g:, 'coc_service_initialized', 0)
|
||||
call s:coc_register()
|
||||
else
|
||||
" coc hasn't finished starting its node service yet — defer until it has,
|
||||
" otherwise the updateConfig notification is sent to a service that isn't
|
||||
" listening.
|
||||
augroup nuwiki_coc_register
|
||||
autocmd!
|
||||
autocmd User CocNvimInit ++once call s:coc_register()
|
||||
augroup END
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:coc_register() abort
|
||||
let l:cfg = s:settings()
|
||||
" Call coc#config directly — `exists('*coc#config')` can't be trusted because
|
||||
" it doesn't trigger autoloading, so we let the call autoload coc.vim and
|
||||
" fall back to the manual snippet only if coc genuinely isn't there.
|
||||
try
|
||||
call coc#config('languageserver.nuwiki', {
|
||||
\ 'command': s:coc_bin,
|
||||
\ 'filetypes': ['vimwiki'],
|
||||
\ 'initializationOptions': l:cfg,
|
||||
\ 'settings': { 'nuwiki': l:cfg },
|
||||
\ })
|
||||
catch /^Vim\%((\a\+)\)\=:E11[78]/
|
||||
call s:print_coc_snippet(s:coc_bin)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:print_coc_snippet(bin) abort
|
||||
echohl WarningMsg
|
||||
echom 'nuwiki: coc.nvim detected. Add this to your coc-settings.json:'
|
||||
echom ' "languageserver": {'
|
||||
echom ' "nuwiki": {'
|
||||
echom ' "command": "' . a:bin . '",'
|
||||
echom ' "filetypes": ["vimwiki"],'
|
||||
echom ' "initializationOptions": ' . json_encode(s:settings())
|
||||
echom ' }'
|
||||
echom ' }'
|
||||
echohl None
|
||||
endfunction
|
||||
|
||||
function! s:bin_path() abort
|
||||
if exists('g:nuwiki_binary_path') && filereadable(g:nuwiki_binary_path)
|
||||
return g:nuwiki_binary_path
|
||||
|
||||
Reference in New Issue
Block a user