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
+25 -1
View File
@@ -186,6 +186,7 @@ let s:mapping_surface = [
\ ['<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'],
\ ['<C-Space>', 'nx'], ['<C-@>', 'nx'], ['<Nul>', 'nx'],
\ ['gnt', 'n'], ['gln', 'nx'], ['glp', 'nx'], ['glx', 'nx'],
\ ['glh', 'n'], ['gll', 'n'], ['gLh', 'n'], ['gLl', 'n'],
@@ -212,7 +213,7 @@ let s:mapping_surface = [
\ ['ah', 'ox'], ['ih', 'ox'], ['aH', 'ox'], ['iH', 'ox'],
\ ['al', 'ox'], ['il', 'ox'], ['a\', 'ox'], ['i\', 'ox'],
\ ['ac', 'ox'], ['ic', 'ox'],
\ ['<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'],
\ ]
@@ -335,6 +336,20 @@ call s:run('cr.adds_new_table_row', {
\ 'keys': "A\<CR>x\<Esc>",
\ 'expect_lines': ['| a | b |', '|x | |'],
\ })
" Insert <S-CR>: multiline list item — continue with NO marker, aligned under
" the text ("- " → 2 cols; "- [ ] " → 6 cols).
call s:run('cr.shift_cr_multiline', {
\ 'lines': ['- item'],
\ 'cursor': [1, 6],
\ 'keys': "A\<S-CR>x\<Esc>",
\ 'expect_lines': ['- item', ' x'],
\ })
call s:run('cr.shift_cr_multiline_checkbox', {
\ 'lines': ['- [ ] item'],
\ 'cursor': [1, 10],
\ 'keys': "A\<S-CR>x\<Esc>",
\ 'expect_lines': ['- [ ] item', ' x'],
\ })
" ===== Insert-mode smart_tab / smart_shift_tab (Cluster 6) =====
@@ -589,6 +604,15 @@ call s:record(
\ 'normalize.visual_wraps_selection',
\ 'got ' . string(getline(1)))
" ===== Visual <CR> mapping wraps the selection (== visual `+`) =====
call s:set_buf(['alpha beta gamma'])
call cursor(1, 7)
call feedkeys("viw\<CR>", 'tx')
call s:record(
\ getline(1) ==# 'alpha [[beta]] gamma' ? 1 : 0,
\ 'map.visual_cr_wraps_selection',
\ 'got ' . string(getline(1)))
" ===== 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