feat(parity): close the entire P3 Mappings section

Both remaining mapping gaps (client-side, both clients):

- Visual <CR>: upstream binds it to NormalizeLinkVisualCR (== visual `+`).
  Added `x <CR>` -> normalize_link(true) (wrap the selection as a wikilink)
  in both clients.

- Insert <S-CR>: upstream's multiline-list-item continuation (VimwikiReturn
  2 2 -> kbd_cr with no new marker). New smart_shift_return (both clients,
  <expr> insert mapping): on a list item returns <CR> + spaces aligning under
  the item text (marker width + 1, +4 for a `[ ] ` checkbox), no marker; off a
  list item, a plain <CR>. Mirrors smart_return's auto-indent handling.

Tests: map.visual_cr_wraps_selection + map.insert_shift_cr_multiline
(test-keymaps.lua, the latter exercising the handler directly since <S-CR>
doesn't round-trip headless feedkeys), and map.visual_cr_wraps_selection +
cr.shift_cr_multiline{,_checkbox} (test-keymaps-vim.vim). Docs (README +
doc/nuwiki.txt) and the gap doc updated. Neovim 305, Vim 299/18/21 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 11:04:56 +00:00
parent 305324c6e9
commit 724712121d
9 changed files with 146 additions and 7 deletions
+37 -1
View File
@@ -208,6 +208,7 @@ vim.defer_fn(function()
{ '<CR>', 'n' }, { '<S-CR>', 'n' }, { '<C-CR>', 'n' }, { '<C-S-CR>', 'n' },
{ '<M-CR>', 'n' }, { '<D-CR>', 'n' },
{ '<BS>', 'n' }, { '<Tab>', 'n' }, { '<S-Tab>', 'n' }, { '+', 'nx' },
{ '<CR>', 'x' }, -- visual normalize-link (== visual `+`)
-- Lists
{ '<C-Space>', 'nx' }, { '<C-@>', 'nx' }, { '<Nul>', 'nx' },
{ 'gnt', 'n' }, { 'gln', 'nx' }, { 'glp', 'nx' }, { 'glx', 'nx' },
@@ -242,7 +243,7 @@ vim.defer_fn(function()
{ 'al', 'ox' }, { 'il', 'ox' }, { 'a\\', 'ox' }, { 'i\\', 'ox' },
{ 'ac', 'ox' }, { 'ic', 'ox' },
-- Insert-mode
{ '<CR>', 'i' }, { '<Tab>', 'i' }, { '<S-Tab>', 'i' },
{ '<CR>', 'i' }, { '<S-CR>', 'i' }, { '<Tab>', 'i' }, { '<S-Tab>', 'i' },
{ '<C-D>', 'i' }, { '<C-T>', 'i' },
{ '<C-L><C-J>', 'i' }, { '<C-L><C-K>', 'i' }, { '<C-L><C-M>', 'i' },
}
@@ -1009,6 +1010,41 @@ vim.defer_fn(function()
end
end)
-- Visual <CR> mapping wraps the selection (upstream parity with visual `+`).
-- Select via `normal!` (sets the '<,'> marks reliably), then `gv` reselects
-- and the fed <CR> fires the x-mode mapping.
tobj_case('map.visual_cr_wraps_selection', function()
set_buf({ 'alpha beta gamma' })
vim.cmd('normal! 0wviw\27') -- select 'beta', leave visual → marks set
send('gv<CR>')
local got = vim.api.nvim_get_current_line()
if got ~= 'alpha [[beta]] gamma' then
error('visual <CR> did not wrap selection: ' .. got)
end
end)
-- Insert <S-CR> continues a list item with no marker, aligned under the text.
-- Test the `<expr>` handler directly — `<S-CR>` doesn't round-trip through
-- headless feedkeys, but the handler is what the mapping invokes.
tobj_case('map.insert_shift_cr_multiline', function()
local cr = vim.api.nvim_replace_termcodes('<CR>', true, false, true)
set_buf({ '- item' }) -- "- " is 2 cols → continuation aligns at column 2
local got = require('nuwiki.commands').smart_shift_return()
if got ~= cr .. ' ' then
error('S-CR (bullet) wrong: ' .. vim.inspect(got))
end
set_buf({ '- [ ] item' }) -- "- [ ] " is 6 cols
got = require('nuwiki.commands').smart_shift_return()
if got ~= cr .. ' ' then
error('S-CR (checkbox) wrong: ' .. vim.inspect(got))
end
set_buf({ 'plain text' }) -- not a list → plain <CR>
got = require('nuwiki.commands').smart_shift_return()
if got ~= cr then
error('S-CR (non-list) should be plain CR: ' .. vim.inspect(got))
end
end)
-- ===== Configurable map_prefix (vimwiki g:vimwiki_map_prefix) =====
-- Overriding map_prefix must relocate the whole <prefix>* family. We attach
-- to a throwaway scratch buffer with a custom prefix and assert the new