fix(commands): route Neovim *Link Ex-commands through follow_link_or_create
Audit follow-up on the two link-path items flagged during the command-attribute pass: - REAL (bug #2): all eight Neovim Ex-command link defs (Vimwiki/Nuwiki × FollowLink/SplitLink/VSplitLink/TabnewLink) dispatched to raw `lua vim.lsp.buf.definition()`, bypassing the bare-word → [[link]] wrap + create-on-follow that the Vim commands and the Neovim <CR> family already do. All eight now call follow_link_or_create() (keeping their split/vsplit/tabnew prefixes). TabDropLink already used follow_link_drop and is unchanged. - FALSE ALARM (bug #1): the audit's claim that lua follow_link_or_create was "botched" (double definition() with dead pos_args code, no wrap) was a mis-read — it was a single correct definition that already wrapped bare words and is dispatched by <CR>. Tidied anyway: collapsed its two definition() call sites into one tail call; behaviour is identical (wrap still skipped when already inside a link, via short-circuit). Tests: cmd.VimwikiFollowLink_wraps_bare_word + cmd.VimwikiSplitLink_wraps_bare_word (test-keymaps.lua). Both harnesses green (lua 280, vim 269/18/21, 0 failed); gap doc corrected for both entries. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+23
-13
@@ -195,19 +195,29 @@ fix site.
|
||||
`cmd.ListChangeLvl_range_indents` (`test-keymaps.lua`) and
|
||||
`cmd.VimwikiListChangeLvl_accepts_range_and_args` (`test-keymaps-vim.vim`,
|
||||
no E481/E488).
|
||||
- [ ] **Neovim `follow_link_or_create` is botched** _(new, 2026-05-31
|
||||
command-attribute audit)_ — `lua/nuwiki/commands.lua` calls
|
||||
`vim.lsp.buf.definition()` **twice** with dead code between
|
||||
(`local p = pos_args()[1]` … `local _ = p`), and never does the bare-word →
|
||||
`[[link]]` wrap its docstring promises (the Vim side does, via
|
||||
`s:wrap_word_under_cursor`). So on Neovim, `<CR>` on a bare word doesn't
|
||||
create/follow a link, and link-follow fires a redundant second jump. _Fix:_
|
||||
rewrite to wrap-then-jump once, mirroring the Vim path.
|
||||
- [ ] **Neovim SplitLink/VSplitLink skip the bare-word wrap** _(new, same
|
||||
audit)_ — the Neovim defs dispatch to raw `vim.lsp.buf.definition()` while
|
||||
the Vim defs (and Neovim `FollowLink`/`TabnewLink`) use
|
||||
`follow_link_or_create`. Once the above is fixed, route Neovim
|
||||
Split/VSplitLink through `follow_link_or_create` too for cross-client parity.
|
||||
- [x] **Neovim `follow_link_or_create` "botched"** _(new, 2026-05-31
|
||||
command-attribute audit; FALSE ALARM — verified + tidied)_ — the audit
|
||||
mis-read the function. `lua/nuwiki/commands.lua` had a single, correct
|
||||
definition that already did the bare-word → `[[link]]` wrap (via
|
||||
`wrap_cword_as_wikilink`) and was dispatched by the `<CR>` keymap — there was
|
||||
no dead `pos_args()` code and no `s:wrap_word_under_cursor` (that name doesn't
|
||||
exist). The only real artifact was two separate `vim.lsp.buf.definition()`
|
||||
call sites for the "inside a wikilink" and "nothing to wrap" branches.
|
||||
_Done:_ collapsed to one tail call (`if not cursor_inside_wikilink() and
|
||||
wrap_cword_as_wikilink() then return end; vim.lsp.buf.definition()`) —
|
||||
behaviour identical (wrap still skipped when already inside a link, via
|
||||
short-circuit), just tidier. No `<CR>` behaviour change.
|
||||
- [x] **Neovim `*Link` Ex-commands skip the bare-word wrap** _(new, same audit;
|
||||
broader than first noted)_ — not just Split/VSplit: all eight Neovim
|
||||
Ex-command link defs (`Vimwiki/Nuwiki` × `FollowLink`/`SplitLink`/
|
||||
`VSplitLink`/`TabnewLink`) dispatched to raw `lua vim.lsp.buf.definition()`,
|
||||
bypassing the wrap + create-on-follow that the Vim commands and the Neovim
|
||||
`<CR>` family provide. _Fix:_ all eight now call
|
||||
`lua require('nuwiki.commands').follow_link_or_create()` (keeping their
|
||||
`split`/`vsplit`/`tabnew` prefixes); `TabDropLink` already used
|
||||
`follow_link_drop` and is unchanged. Covered by
|
||||
`cmd.VimwikiFollowLink_wraps_bare_word` +
|
||||
`cmd.VimwikiSplitLink_wraps_bare_word` (`test-keymaps.lua`).
|
||||
- [x] `VimwikiRebuildTags` `-bang` ("rebuild all") — `:…RebuildTags!` now passes
|
||||
`{ all: true }`; the server (`tags_rebuild`) re-indexes **every** configured
|
||||
wiki (via `wikis_snapshot()`) instead of just the current one. `-bang` added to
|
||||
|
||||
@@ -403,11 +403,11 @@ command! -buffer VimwikiDiaryNextDay lua require('nuwiki.commands').dia
|
||||
command! -buffer VimwikiDiaryPrevDay lua require('nuwiki.commands').diary_prev()
|
||||
command! -buffer VimwikiDiaryGenerateLinks lua require('nuwiki.commands').diary_generate_index()
|
||||
|
||||
command! -buffer VimwikiFollowLink lua vim.lsp.buf.definition()
|
||||
command! -buffer VimwikiFollowLink lua require('nuwiki.commands').follow_link_or_create()
|
||||
command! -buffer VimwikiGoBackLink execute "normal! \<C-o>"
|
||||
command! -buffer -nargs=* VimwikiSplitLink split | lua vim.lsp.buf.definition()
|
||||
command! -buffer -nargs=* VimwikiVSplitLink vsplit | lua vim.lsp.buf.definition()
|
||||
command! -buffer VimwikiTabnewLink tabnew | lua vim.lsp.buf.definition()
|
||||
command! -buffer -nargs=* VimwikiSplitLink split | lua require('nuwiki.commands').follow_link_or_create()
|
||||
command! -buffer -nargs=* VimwikiVSplitLink vsplit | lua require('nuwiki.commands').follow_link_or_create()
|
||||
command! -buffer VimwikiTabnewLink tabnew | lua require('nuwiki.commands').follow_link_or_create()
|
||||
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()
|
||||
@@ -477,7 +477,7 @@ command! -buffer NuwikiDiaryTomorrow lua require('nuwiki.commands').diar
|
||||
command! -buffer NuwikiDiaryNext lua require('nuwiki.commands').diary_next()
|
||||
command! -buffer NuwikiDiaryPrev lua require('nuwiki.commands').diary_prev()
|
||||
command! -buffer NuwikiDiaryGenerateLinks lua require('nuwiki.commands').diary_generate_index()
|
||||
command! -buffer NuwikiFollowLink lua vim.lsp.buf.definition()
|
||||
command! -buffer NuwikiFollowLink lua require('nuwiki.commands').follow_link_or_create()
|
||||
command! -buffer NuwikiBacklinks lua vim.lsp.buf.references()
|
||||
command! -buffer NuwikiDeleteFile lua require('nuwiki.commands').delete_file()
|
||||
command! -buffer NuwikiRenameFile lua require('nuwiki.commands').rename_file()
|
||||
@@ -513,9 +513,9 @@ command! -buffer Nuwiki2HTMLBrowse lua require('nuwiki.command
|
||||
command! -buffer -bang NuwikiAll2HTML execute (<bang>0 ? "lua require('nuwiki.commands').export_all_force()" : "lua require('nuwiki.commands').export_all()")
|
||||
|
||||
command! -buffer NuwikiGoBackLink execute "normal! \<C-o>"
|
||||
command! -buffer -nargs=* NuwikiSplitLink split | lua vim.lsp.buf.definition()
|
||||
command! -buffer -nargs=* NuwikiVSplitLink vsplit | lua vim.lsp.buf.definition()
|
||||
command! -buffer NuwikiTabnewLink tabnew | lua vim.lsp.buf.definition()
|
||||
command! -buffer -nargs=* NuwikiSplitLink split | lua require('nuwiki.commands').follow_link_or_create()
|
||||
command! -buffer -nargs=* NuwikiVSplitLink vsplit | lua require('nuwiki.commands').follow_link_or_create()
|
||||
command! -buffer NuwikiTabnewLink tabnew | lua require('nuwiki.commands').follow_link_or_create()
|
||||
command! -buffer NuwikiTabDropLink lua require('nuwiki.commands').follow_link_drop()
|
||||
command! -buffer -bang NuwikiRemoveDone lua require('nuwiki.commands')[('<bang>' == '!') and 'list_remove_done_all' or 'list_remove_done']()
|
||||
command! -buffer -range NuwikiRemoveCheckbox lua require('nuwiki.commands').list_remove_checkbox()
|
||||
|
||||
@@ -237,17 +237,13 @@ function M.follow_link_drop()
|
||||
end
|
||||
|
||||
function M.follow_link_or_create()
|
||||
if cursor_inside_wikilink() then
|
||||
vim.lsp.buf.definition()
|
||||
-- Already on a wikilink → follow it. Otherwise try to wrap the bare word
|
||||
-- under the cursor as `[[word]]` and stop (a second press follows it,
|
||||
-- matching vimwiki's review-then-follow flow). If there's nothing to wrap,
|
||||
-- fall through to a plain definition request so a chord still works anywhere.
|
||||
if not cursor_inside_wikilink() and wrap_cword_as_wikilink() then
|
||||
return
|
||||
end
|
||||
if wrap_cword_as_wikilink() then
|
||||
-- Wrapped — leave the user inside the new `[[…]]` and stop. A
|
||||
-- second `<CR>` follows it, matching vimwiki's review-then-follow
|
||||
-- flow.
|
||||
return
|
||||
end
|
||||
-- No word under cursor either — fall through.
|
||||
vim.lsp.buf.definition()
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user