Fix glp backward cycle and gl<Space> current-list scope
CI / cargo fmt --check (push) Successful in 16s
CI / cargo clippy (push) Successful in 21s
CI / cargo test (push) Successful in 37s
CI / cargo fmt --check (pull_request) Successful in 34s
CI / cargo clippy (pull_request) Successful in 36s
CI / cargo test (pull_request) Successful in 38s
CI / editor keymaps (push) Successful in 1m23s
CI / editor keymaps (pull_request) Successful in 1m31s
CI / cargo fmt --check (push) Successful in 16s
CI / cargo clippy (push) Successful in 21s
CI / cargo test (push) Successful in 37s
CI / cargo fmt --check (pull_request) Successful in 34s
CI / cargo clippy (pull_request) Successful in 36s
CI / cargo test (pull_request) Successful in 38s
CI / editor keymaps (push) Successful in 1m23s
CI / editor keymaps (pull_request) Successful in 1m31s
Two documented checkbox-list mappings did not match their spec: - `glp` dispatched the same forward-only cycleCheckbox as `gln`, so it could never "cycle the checkbox state backward". Add `ops::cycle_state_back` and thread a `reverse` flag through the dispatcher and both clients. - `gl<Space>` and `gL<Space>` both swept the whole buffer, making them identical. `gl<Space>` now passes the cursor position and the server scopes deletion to the contiguous list block under the cursor (current list, cascading into sublists); `gL<Space>` stays whole-buffer. Adds Rust unit tests, plus behavioral and full-registration coverage for the documented mapping surface in the Neovim and Vim keymap harnesses, and a command-coverage suite mirroring the doc's command groups. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,107 @@ else
|
||||
call s:record(0, 'cmd.NuwikiIndex_defined', ':NuwikiIndex not registered')
|
||||
endif
|
||||
|
||||
" ===== Documented command surface (doc/nuwiki.txt §5) =====
|
||||
" Every command must be reachable in BOTH the canonical :Nuwiki* form and
|
||||
" the vimwiki-compatible :Vimwiki* form. The suffixes below are the §5 list
|
||||
" minus the prefix. :NuwikiInstall is the one exception — it's a nuwiki-only
|
||||
" maintenance command with no :Vimwiki* alias, so it's checked separately.
|
||||
|
||||
let s:both_forms = [
|
||||
\ 'Index', 'TabIndex', 'UISelect', 'Goto', 'FollowLink', 'Backlinks',
|
||||
\ 'NextLink', 'PrevLink', 'BaddLink', 'RenameFile', 'DeleteFile',
|
||||
\ 'MakeDiaryNote', 'MakeYesterdayDiaryNote', 'MakeTomorrowDiaryNote',
|
||||
\ 'DiaryIndex', 'DiaryGenerateLinks', 'DiaryNextDay', 'DiaryPrevDay',
|
||||
\ 'TOC', 'GenerateLinks', 'CheckLinks', 'SearchTags', 'GenerateTagLinks',
|
||||
\ 'RebuildTags', '2HTML', '2HTMLBrowse', 'All2HTML', 'Rss',
|
||||
\ ]
|
||||
for s:suffix in s:both_forms
|
||||
for s:prefix in ['Nuwiki', 'Vimwiki']
|
||||
let s:cmd = s:prefix . s:suffix
|
||||
let s:ok = exists(':' . s:cmd) == 2
|
||||
call s:record(s:ok ? 1 : 0, 'surface.' . s:cmd,
|
||||
\ s:ok ? '' : ':' . s:cmd . ' not registered')
|
||||
endfor
|
||||
endfor
|
||||
let s:ok = exists(':NuwikiInstall') == 2
|
||||
call s:record(s:ok ? 1 : 0, 'surface.NuwikiInstall',
|
||||
\ s:ok ? '' : ':NuwikiInstall not registered')
|
||||
|
||||
" ===== Pure-VimL command invocation (cursor movement) =====
|
||||
" :NuwikiNextLink / :NuwikiPrevLink wrap search('\[\[', …) so they run
|
||||
" entirely in VimL and move the cursor without touching the LSP.
|
||||
|
||||
call s:set_buf(['intro [[A]] more [[B]] end'])
|
||||
call cursor(1, 1)
|
||||
silent NuwikiNextLink
|
||||
call s:record(
|
||||
\ col('.') == 7 ? 1 : 0,
|
||||
\ 'invoke.NuwikiNextLink_jumps_to_first_link',
|
||||
\ 'col=' . col('.'))
|
||||
silent NuwikiNextLink
|
||||
call s:record(
|
||||
\ col('.') == 18 ? 1 : 0,
|
||||
\ 'invoke.NuwikiNextLink_jumps_to_second_link',
|
||||
\ 'col=' . col('.'))
|
||||
silent NuwikiPrevLink
|
||||
call s:record(
|
||||
\ col('.') == 7 ? 1 : 0,
|
||||
\ 'invoke.NuwikiPrevLink_jumps_back',
|
||||
\ 'col=' . col('.'))
|
||||
|
||||
" The :Vimwiki* alias must drive the identical motion.
|
||||
call cursor(1, 1)
|
||||
silent VimwikiNextLink
|
||||
call s:record(
|
||||
\ col('.') == 7 ? 1 : 0,
|
||||
\ 'invoke.VimwikiNextLink_jumps_to_first_link',
|
||||
\ 'col=' . col('.'))
|
||||
|
||||
" ===== Documented mapping surface (doc §6/§7/§8) =====
|
||||
" Every documented mapping must resolve to a buffer-local mapping in the
|
||||
" mode(s) the doc lists it under. The mouse group is opt-in — the shell
|
||||
" wrapper sets g:nuwiki_mouse_mappings before the ftplugin loads.
|
||||
|
||||
function! s:has_map(lhs, mode) abort
|
||||
let l:d = maparg(a:lhs, a:mode, 0, 1)
|
||||
return !empty(l:d) && get(l:d, 'buffer', 0)
|
||||
endfunction
|
||||
|
||||
let s:mapping_surface = [
|
||||
\ ['<CR>', 'n'], ['<S-CR>', 'n'], ['<C-CR>', 'n'], ['<C-S-CR>', 'n'],
|
||||
\ ['<BS>', 'n'], ['<Tab>', 'n'], ['<S-Tab>', 'n'], ['+', 'nx'],
|
||||
\ ['<C-Space>', 'nx'], ['<C-@>', 'nx'], ['<Nul>', 'nx'],
|
||||
\ ['gnt', 'n'], ['gln', 'nx'], ['glp', 'nx'], ['glx', 'nx'],
|
||||
\ ['glh', 'n'], ['gll', 'n'], ['gLh', 'n'], ['gLl', 'n'],
|
||||
\ ['glr', 'n'], ['gLr', 'n'], ['gl<Space>', 'n'], ['gL<Space>', 'n'],
|
||||
\ ['o', 'n'], ['O', 'n'],
|
||||
\ ['=', 'n'], ['-', 'n'], [']]', 'n'], ['[[', 'n'],
|
||||
\ [']=', 'n'], ['[=', 'n'], [']u', 'n'], ['[u', 'n'],
|
||||
\ ['gqq', 'n'], ['gq1', 'n'], ['gww', 'n'], ['gw1', 'n'],
|
||||
\ ['<A-Left>', 'n'], ['<A-Right>', 'n'],
|
||||
\ ['<Leader>ww', 'n'], ['<Leader>ws', 'n'], ['<Leader>wi', 'n'],
|
||||
\ ['<Leader>w<Leader>w', 'n'], ['<Leader>w<Leader>y', 'n'],
|
||||
\ ['<Leader>w<Leader>t', 'n'], ['<Leader>w<Leader>i', 'n'],
|
||||
\ ['<Leader>wn', 'n'], ['<Leader>wd', 'n'], ['<Leader>wr', 'n'],
|
||||
\ ['<Leader>wh', 'n'], ['<Leader>whh', 'n'], ['<Leader>wha', 'n'],
|
||||
\ ['<Leader>wc', 'nx'], ['<C-Down>', 'n'], ['<C-Up>', 'n'],
|
||||
\ ['<2-LeftMouse>', 'n'], ['<S-2-LeftMouse>', 'n'], ['<C-2-LeftMouse>', 'n'],
|
||||
\ ['<MiddleMouse>', 'n'], ['<RightMouse>', 'n'],
|
||||
\ ['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'],
|
||||
\ ['<C-D>', 'i'], ['<C-T>', 'i'],
|
||||
\ ['<C-L><C-J>', 'i'], ['<C-L><C-K>', 'i'], ['<C-L><C-M>', 'i'],
|
||||
\ ]
|
||||
for s:entry in s:mapping_surface
|
||||
for s:m in split(s:entry[1], '\zs')
|
||||
let s:ok = s:has_map(s:entry[0], s:m)
|
||||
call s:record(s:ok ? 1 : 0, 'map[' . s:m . '].' . s:entry[0],
|
||||
\ s:ok ? '' : s:entry[0] . ' (' . s:m . ') not mapped buffer-local')
|
||||
endfor
|
||||
endfor
|
||||
|
||||
" ===== Header nav (pure VimL) =====
|
||||
|
||||
call s:run('headers.]]_jumps_to_next', {
|
||||
@@ -121,6 +222,12 @@ call s:run('headers.]=_jumps_to_next_sibling', {
|
||||
\ 'keys': ']=',
|
||||
\ 'expect_cursor_line': 4,
|
||||
\ })
|
||||
call s:run('headers.[=_jumps_to_prev_sibling', {
|
||||
\ 'lines': ['= A =', '== child ==', 'body', '= B ='],
|
||||
\ 'cursor': [4, 1],
|
||||
\ 'keys': '[=',
|
||||
\ 'expect_cursor_line': 1,
|
||||
\ })
|
||||
|
||||
" ===== Link nav (pure VimL) =====
|
||||
|
||||
|
||||
Reference in New Issue
Block a user