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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -569,8 +569,20 @@ fix site.
|
||||
- [ ] `list_ignore_newline` / `text_ignore_newline` — export newline handling.
|
||||
|
||||
### Mappings
|
||||
- [ ] Visual `<CR>` normalize-link (visual `+` covers the same intent).
|
||||
- [ ] Insert `<S-CR>` multiline list item.
|
||||
- [x] **Visual `<CR>` normalize-link** _(fixed 2026-06-03)_ — upstream binds
|
||||
visual `<CR>` to `<Plug>VimwikiNormalizeLinkVisualCR` → `:VimwikiNormalizeLink 1`,
|
||||
identical to visual `+`. nuwiki had only visual `+`. _Fix:_ added `x <CR>` →
|
||||
the same wrap-selection handler (`normalize_link(true)`) in both clients
|
||||
(`lua/nuwiki/keymaps.lua`, `ftplugin/vimwiki.vim`). Covered by
|
||||
`map.visual_cr_wraps_selection` in both harnesses.
|
||||
- [x] **Insert `<S-CR>` multiline list item** _(fixed 2026-06-03)_ — upstream's
|
||||
insert `<S-CR>` (`VimwikiReturn 2 2` → `kbd_cr` with no new marker) continues
|
||||
the current list item on a new line indented to align under the item's text.
|
||||
_Fix:_ new `smart_shift_return` (both clients, `<expr>` insert mapping): on a
|
||||
list item returns `<CR>` + (indent +) `marker-width + 1 (+4 for a checkbox)`
|
||||
spaces — no marker; off a list item, a plain `<CR>`. Mirrors `smart_return`'s
|
||||
auto-indent handling. Covered by `map.insert_shift_cr_multiline`
|
||||
(`test-keymaps.lua`) + `cr.shift_cr_multiline{,_checkbox}` (`test-keymaps-vim.vim`).
|
||||
- [x] **`gLH` / `gLL` / `gLR`** _(fixed 2026-06-03)_ — upstream binds these as
|
||||
case-variant **aliases** of `gLh` / `gLl` / `gLr` (dedent / indent whole item,
|
||||
renumber all lists; upstream `ftplugin/vimwiki.vim:553,555,561`). nuwiki had
|
||||
@@ -713,3 +725,8 @@ audits don't re-flag them.
|
||||
`use_calendar` opt-out (`g:nuwiki_no_calendar` / setup `use_calendar = false`).
|
||||
So `use_calendar` is no longer an intentional divergence — removed from that
|
||||
list above. See `development/calendar-vim-integration.md`.
|
||||
- Cleared the **entire P3 Mappings section** (2026-06-03): visual `<CR>` →
|
||||
normalize-link (same handler as visual `+`), and insert `<S-CR>` → multiline
|
||||
list item (`smart_shift_return`, continuation with no new marker aligned under
|
||||
the text). Both client-side, both clients, tested in both harnesses (Neovim
|
||||
305, Vim 299/18/21). Only P3 Config items now remain open.
|
||||
|
||||
Reference in New Issue
Block a user