feat(client): add Vim split/tab/back link-follow commands + true tab-drop
The plain-Vim client only defined VimwikiFollowLink; the split/vsplit/
tabnew/tabdrop/back command surface existed only in the Neovim branch.
Add :Vimwiki{Split,VSplit,Tabnew,TabDrop,GoBack}Link (+ :Nuwiki* aliases)
to the Vim branch, backed by a new nuwiki#commands#follow_link_drop()
helper that runs `:tab drop` to reuse an already-open tab.
Both clients now implement real tab-drop: open_uri gains a 'tabdrop'
case and M.follow_link_drop(); the Neovim TabDropLink commands and the
<C-S-CR> mappings (Vim + Lua) are repointed off the old tabnew cheat.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -188,6 +188,47 @@ function! s:badd_from_response(notification) abort
|
||||
echom 'nuwiki: added ' . l:path
|
||||
endfunction
|
||||
|
||||
" `:VimwikiTabDropLink` — open the link target in a tab, reusing an
|
||||
" existing tab/window if the file is already shown (`:tab drop`). Routes
|
||||
" through vim-lsp's textDocument/definition like `badd_link`.
|
||||
function! nuwiki#commands#follow_link_drop() abort
|
||||
if s:has_vimlsp()
|
||||
call lsp#send_request(s:server, {
|
||||
\ 'method': 'textDocument/definition',
|
||||
\ 'params': s:cursor_position(),
|
||||
\ 'on_notification': function('s:drop_from_response'),
|
||||
\ })
|
||||
return
|
||||
endif
|
||||
if s:has_coc()
|
||||
let l:locs = CocAction('getDefinition')
|
||||
if type(l:locs) == type([]) && !empty(l:locs)
|
||||
let l:uri = get(l:locs[0], 'uri', get(l:locs[0], 'targetUri', ''))
|
||||
if !empty(l:uri)
|
||||
let l:path = substitute(l:uri, '^file://', '', '')
|
||||
execute 'tab drop ' . fnameescape(l:path)
|
||||
endif
|
||||
endif
|
||||
return
|
||||
endif
|
||||
echohl ErrorMsg | echom 'nuwiki: no supported LSP client for follow_link_drop' | echohl None
|
||||
endfunction
|
||||
|
||||
function! s:drop_from_response(notification) abort
|
||||
let l:result = get(get(a:notification, 'response', {}), 'result', {})
|
||||
let l:uri = ''
|
||||
if type(l:result) == type({})
|
||||
let l:uri = get(l:result, 'uri', get(l:result, 'targetUri', ''))
|
||||
elseif type(l:result) == type([]) && !empty(l:result)
|
||||
let l:uri = get(l:result[0], 'uri', get(l:result[0], 'targetUri', ''))
|
||||
endif
|
||||
if l:uri ==# ''
|
||||
return
|
||||
endif
|
||||
let l:path = substitute(l:uri, '^file://', '', '')
|
||||
execute 'tab drop ' . fnameescape(l:path)
|
||||
endfunction
|
||||
|
||||
" ===== Smart <CR>: follow or wrap-then-follow =====
|
||||
|
||||
function! s:cursor_inside_wikilink() abort
|
||||
|
||||
+13
-3
@@ -47,6 +47,11 @@ if !has('nvim')
|
||||
command! -buffer VimwikiDiaryPrevDay call nuwiki#commands#diary_prev()
|
||||
command! -buffer VimwikiDiaryGenerateLinks call nuwiki#commands#diary_generate_index()
|
||||
command! -buffer VimwikiFollowLink call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer VimwikiSplitLink split | call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer VimwikiVSplitLink vsplit | call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer VimwikiTabnewLink tabnew | call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer VimwikiTabDropLink call nuwiki#commands#follow_link_drop()
|
||||
command! -buffer VimwikiGoBackLink execute "normal! \<C-o>"
|
||||
command! -buffer VimwikiBacklinks call nuwiki#commands#backlinks()
|
||||
command! -buffer VWB call nuwiki#commands#backlinks()
|
||||
command! -buffer VimwikiNextLink call nuwiki#commands#link_next()
|
||||
@@ -113,6 +118,11 @@ if !has('nvim')
|
||||
command! -buffer NuwikiDiaryNext call nuwiki#commands#diary_next()
|
||||
command! -buffer NuwikiDiaryPrev call nuwiki#commands#diary_prev()
|
||||
command! -buffer NuwikiFollowLink call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer NuwikiSplitLink split | call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer NuwikiVSplitLink vsplit | call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer NuwikiTabnewLink tabnew | call nuwiki#commands#follow_link_or_create()
|
||||
command! -buffer NuwikiTabDropLink call nuwiki#commands#follow_link_drop()
|
||||
command! -buffer NuwikiGoBackLink execute "normal! \<C-o>"
|
||||
command! -buffer NuwikiBacklinks call nuwiki#commands#backlinks()
|
||||
command! -buffer NuwikiDeleteFile call nuwiki#commands#delete_file()
|
||||
command! -buffer NuwikiRenameFile call nuwiki#commands#rename_file()
|
||||
@@ -196,7 +206,7 @@ if !has('nvim')
|
||||
nnoremap <silent><buffer> <CR> :call nuwiki#commands#follow_link_or_create()<CR>
|
||||
nnoremap <silent><buffer> <S-CR> :split<CR>:call nuwiki#commands#follow_link_or_create()<CR>
|
||||
nnoremap <silent><buffer> <C-CR> :vsplit<CR>:call nuwiki#commands#follow_link_or_create()<CR>
|
||||
nnoremap <silent><buffer> <C-S-CR> :tabnew<CR>:call nuwiki#commands#follow_link_or_create()<CR>
|
||||
nnoremap <silent><buffer> <C-S-CR> :call nuwiki#commands#follow_link_drop()<CR>
|
||||
nnoremap <silent><buffer> <BS> <C-o>
|
||||
nnoremap <silent><buffer> <Tab> /\[\[<CR>:nohlsearch<CR>
|
||||
nnoremap <silent><buffer> <S-Tab> ?\[\[<CR>:nohlsearch<CR>
|
||||
@@ -357,7 +367,7 @@ command! -buffer VimwikiGoBackLink execute "normal! \<C-o>"
|
||||
command! -buffer VimwikiSplitLink split | lua vim.lsp.buf.definition()
|
||||
command! -buffer VimwikiVSplitLink vsplit | lua vim.lsp.buf.definition()
|
||||
command! -buffer VimwikiTabnewLink tabnew | lua vim.lsp.buf.definition()
|
||||
command! -buffer VimwikiTabDropLink tabnew | lua vim.lsp.buf.definition()
|
||||
command! -buffer VimwikiTabDropLink lua require('nuwiki.commands').follow_link_drop()
|
||||
command! -buffer VimwikiNextLink lua require('nuwiki.commands').link_next()
|
||||
command! -buffer VimwikiPrevLink lua require('nuwiki.commands').link_prev()
|
||||
command! -buffer VimwikiBaddLink lua require('nuwiki.commands').badd_link()
|
||||
@@ -465,7 +475,7 @@ command! -buffer NuwikiGoBackLink execute "normal! \<C-o>"
|
||||
command! -buffer NuwikiSplitLink split | lua vim.lsp.buf.definition()
|
||||
command! -buffer NuwikiVSplitLink vsplit | lua vim.lsp.buf.definition()
|
||||
command! -buffer NuwikiTabnewLink tabnew | lua vim.lsp.buf.definition()
|
||||
command! -buffer NuwikiTabDropLink tabnew | lua vim.lsp.buf.definition()
|
||||
command! -buffer NuwikiTabDropLink lua require('nuwiki.commands').follow_link_drop()
|
||||
command! -buffer NuwikiRemoveDone lua require('nuwiki.commands').list_remove_done()
|
||||
command! -buffer -range NuwikiRemoveCheckbox lua require('nuwiki.commands').list_remove_checkbox()
|
||||
command! -buffer NuwikiRemoveCheckboxInList lua require('nuwiki.commands').list_remove_checkbox_in_list()
|
||||
|
||||
@@ -73,6 +73,10 @@ local function open_uri(uri, tab)
|
||||
return
|
||||
end
|
||||
local path = vim.uri_to_fname(uri)
|
||||
if tab == 'tabdrop' then
|
||||
vim.cmd('tab drop ' .. vim.fn.fnameescape(path))
|
||||
return
|
||||
end
|
||||
local cmd
|
||||
if tab == 'split' then
|
||||
cmd = 'split'
|
||||
@@ -206,6 +210,32 @@ function M.badd_link()
|
||||
end
|
||||
end
|
||||
|
||||
--- `:VimwikiTabDropLink` — open the link target in a tab, reusing an
|
||||
--- existing tab/window if the file is already shown (`:tab drop`). Uses
|
||||
--- the LSP definition response to resolve the target file.
|
||||
function M.follow_link_drop()
|
||||
local client = find_client()
|
||||
if not client then
|
||||
vim.notify('nuwiki: language server not attached', vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
local params = position_params(client)
|
||||
params.textDocument = { uri = buf_uri() }
|
||||
local req = client.request
|
||||
local handler = function(_, result)
|
||||
local loc
|
||||
if type(result) == 'table' then
|
||||
loc = result[1] or result
|
||||
end
|
||||
local uri = type(loc) == 'table' and (loc.uri or loc.targetUri) or nil
|
||||
open_uri(uri, 'tabdrop')
|
||||
end
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
if type(req) == 'function' then
|
||||
client:request('textDocument/definition', params, handler, bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
function M.follow_link_or_create()
|
||||
if cursor_inside_wikilink() then
|
||||
vim.lsp.buf.definition()
|
||||
|
||||
@@ -164,8 +164,8 @@ function M.attach(bufnr, mappings)
|
||||
{ desc = 'nuwiki: follow link in split' }, bufnr)
|
||||
map('n', '<C-CR>', function() vim.cmd('vsplit'); cmd.follow_link_or_create() end,
|
||||
{ desc = 'nuwiki: follow link in vsplit' }, bufnr)
|
||||
map('n', '<C-S-CR>', function() vim.cmd('tabnew'); cmd.follow_link_or_create() end,
|
||||
{ desc = 'nuwiki: follow link in new tab' }, bufnr)
|
||||
map('n', '<C-S-CR>', cmd.follow_link_drop,
|
||||
{ desc = 'nuwiki: follow link in tab (reuse existing)' }, bufnr)
|
||||
map('n', '<BS>', '<C-o>', { desc = 'nuwiki: go back', remap = true }, bufnr)
|
||||
map('n', '<Tab>', link.next, { desc = 'nuwiki: next wikilink' }, bufnr)
|
||||
map('n', '<S-Tab>', link.prev, { desc = 'nuwiki: prev wikilink' }, bufnr)
|
||||
|
||||
Reference in New Issue
Block a user