fix(follow-link): resolve+open definitions ourselves on the Vim clients
The Vim follow-link path delegated to the LSP client's jump UI
(:LspDefinition / coc jumpDefinition), which broke two ways for wiki
link-following:
1. **No create-on-follow (vim-lsp + coc).** vim-lsp's location handler
readfile()s the target to build a quickfix entry; for a not-yet-created
page that throws E484 and aborts the jump, so <CR> on [[NewPage]] did
nothing. The server was correct throughout — textDocument/definition
returns a *synthesised* location for missing pages (verified over
JSON-RPC).
2. **Wrong window placement (coc).** Without an explicit open command coc
fell back to coc.preferences.jumpCommand (e.g. a tab command).
Stop delegating: nuwiki#commands#follow_link_or_create() /
follow_link_drop() now resolve textDocument/definition directly and open
the URI themselves via a shared s:open_definition(open_cmd) helper — :edit
for <CR>, `tab drop` for <C-S-CR>. :edit opens a buffer for a missing path
(save creates it, matching vimwiki) and gives exact current-window
placement regardless of the user's coc jumpCommand. Removes
s:jump_definition / s:drop_from_response.
Also fix the coc action name: CocAction('getDefinition') does not exist
(E605 "Action getDefinition does not exist") — the registered action is
'definitions'. Fixed in s:open_definition and badd_link.
coc config delivery: the setup guidance shipped without
initializationOptions, so coc users never sent wiki_root and the server
resolved links against its default root (existing pages flagged broken,
follow-to-create landed in the cwd). The printed snippet
(autoload/nuwiki/lsp.vim) now emits initializationOptions populated with
the resolved settings, and the README coc snippet documents it as required.
Add development/start-vim-coc.sh — a coc.nvim dev launcher (sibling of
start-vim.sh) that wires coc's prebuilt release branch + a generated
coc-settings.json (with initializationOptions), deliberately omitting
vim-lsp so the coc path is exercised; doubles as a reproducer.
Tests: new cr.follow_opens_missing_page_in_current_window case in
test-keymaps-vim.vim (stubs CocAction to a missing page, asserts
current-window :edit). Keymap suite 254+18 green; config-parity (Vim +
Neovim) green. Neovim path unchanged and re-confirmed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -477,6 +477,50 @@ call s:record(
|
||||
\ 'ext=' . get(get(s:wl, 1, {}), 'ext', ''))
|
||||
unlet g:nuwiki_wikis
|
||||
|
||||
" ===== Follow-link resolves + opens in the current window (regression) =====
|
||||
" follow_link_or_create() must resolve the definition itself and `:edit` the
|
||||
" target in the CURRENT window — including a page that does not exist yet
|
||||
" (create-on-follow). We open the URI ourselves rather than delegating to
|
||||
" :LspDefinition / coc's jumpDefinition because those fetch the target text
|
||||
" (vim-lsp readfile()s it, throwing E484 for a missing page and aborting the
|
||||
" jump). This harness loads only nuwiki, so :LspDefinition is absent and the
|
||||
" coc branch of s:open_definition() runs once CocAction* are stubbed.
|
||||
" The stubbed getDefinition points at a NON-EXISTENT file, so a green result
|
||||
" proves both current-window placement and create-on-follow.
|
||||
let g:_nuwiki_target = tempname() . '-newpage.wiki'
|
||||
function! CocActionAsync(...) abort
|
||||
endfunction
|
||||
function! CocAction(action, ...) abort
|
||||
if a:action ==# 'definitions'
|
||||
return [{ 'uri': 'file://' . g:_nuwiki_target,
|
||||
\ 'range': { 'start': { 'line': 0, 'character': 0 },
|
||||
\ 'end': { 'line': 0, 'character': 0 } } }]
|
||||
endif
|
||||
return []
|
||||
endfunction
|
||||
" `:edit` must be able to abandon the (modified) scratch buffer.
|
||||
let s:had_hidden = &hidden
|
||||
set hidden
|
||||
let s:seed = expand('%:p')
|
||||
call s:set_buf(['[[NewPage]] rest'])
|
||||
call cursor(1, 4)
|
||||
call nuwiki#commands#follow_link_or_create()
|
||||
let s:now = expand('%:p')
|
||||
call s:record(
|
||||
\ (s:now =~# 'newpage\.wiki$' && s:now !=# s:seed) ? 1 : 0,
|
||||
\ 'cr.follow_opens_missing_page_in_current_window',
|
||||
\ 'buf=' . s:now)
|
||||
let &hidden = s:had_hidden
|
||||
delfunction CocAction
|
||||
delfunction CocActionAsync
|
||||
unlet g:_nuwiki_target
|
||||
" NOTE: the vim-lsp branch of s:open_definition() can't be driven headlessly —
|
||||
" it gates on `exists('*lsp#send_request')`, which returns 0 for an inline stub
|
||||
" (Vim only resolves real autoload files). It shares the same s:open_location()
|
||||
" open logic the coc case above exercises, and mirrors the shipped
|
||||
" follow_link_drop() request mechanism; its end-to-end coverage is the manual
|
||||
" development/start-vim.sh check.
|
||||
|
||||
" ===== Wrap up =====
|
||||
|
||||
call add(s:results, '')
|
||||
|
||||
Reference in New Issue
Block a user