From 4905858d5e822d93aa3e9d4e07ff2dcc28ad4f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Fr=C3=B3es=20Franco?= Date: Tue, 12 May 2026 01:55:20 +0000 Subject: [PATCH] =?UTF-8?q?fix(follow-link):=20two-step=20=20=E2=80=94?= =?UTF-8?q?=20first=20wraps,=20second=20follows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User feedback: the smart `` should give the user a chance to review/edit the freshly-created wikilink before committing to the follow. Matches upstream vimwiki's flow. `follow_link_or_create` (Lua + VimL) now: 1. Cursor already inside `[[…]]` → follow immediately. 2. Cursor on a bare word → wrap it as `[[word]]`, place cursor inside, and STOP. A second `` then follows. 3. Neither — fall through to plain definition request so users can still chord follow without a target word. Verified: cursor on `MyPage rest` → 1st `` → `[[MyPage]] rest` (buffer unchanged) 2nd `` → opens `MyPage.wiki` (the synthesised future page). 381 tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- autoload/nuwiki/commands.vim | 24 ++++++++++++++++++------ lua/nuwiki/commands.lua | 21 ++++++++++++++++----- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/autoload/nuwiki/commands.vim b/autoload/nuwiki/commands.vim index c32c281..daaedbf 100644 --- a/autoload/nuwiki/commands.vim +++ b/autoload/nuwiki/commands.vim @@ -144,16 +144,28 @@ function! s:wrap_cword_as_wikilink() abort return 1 endfunction +" Two-step behaviour matching vimwiki: +" 1. First press on a bare word → wrap it as `[[word]]` and stop. +" 2. Cursor is now inside `[[…]]`; next press follows the link. +" 3. Press inside an existing `[[…]]` follows immediately. function! nuwiki#commands#follow_link_or_create() abort - if !s:cursor_inside_wikilink() - call s:wrap_cword_as_wikilink() + if s:cursor_inside_wikilink() + if exists(':LspDefinition') == 2 + LspDefinition + else + echohl WarningMsg + echom 'nuwiki: :LspDefinition unavailable; install vim-lsp' + echohl None + endif + return endif + if s:wrap_cword_as_wikilink() + " Wrapped — wait for the user's second to follow. + return + endif + " Nothing to wrap — fall through. if exists(':LspDefinition') == 2 LspDefinition - else - echohl WarningMsg - echom 'nuwiki: :LspDefinition unavailable; install vim-lsp' - echohl None endif endfunction diff --git a/lua/nuwiki/commands.lua b/lua/nuwiki/commands.lua index 9db0d2f..49e760e 100644 --- a/lua/nuwiki/commands.lua +++ b/lua/nuwiki/commands.lua @@ -159,13 +159,24 @@ local function wrap_cword_as_wikilink() return true end +--- Two-step behaviour matching vimwiki: +--- 1. First press on a bare word → wrap it as `[[word]]` and stop. +--- 2. Cursor is now inside `[[…]]`; next press follows the link. +--- 3. Press inside an existing `[[…]]` follows immediately. +--- "Not on a word" falls through to plain definition so users can +--- still chord a definition request anywhere. function M.follow_link_or_create() - if not cursor_inside_wikilink() then - if not wrap_cword_as_wikilink() then - -- Not on a word either — fall through to plain definition; the - -- LSP will simply do nothing if there's no target. - end + if cursor_inside_wikilink() then + vim.lsp.buf.definition() + return end + if wrap_cword_as_wikilink() then + -- Wrapped — leave the user inside the new `[[…]]` and stop. A + -- second `` follows it, matching vimwiki's review-then-follow + -- flow. + return + end + -- No word under cursor either — fall through. vim.lsp.buf.definition() end