feat(vim): close keymap gap with Neovim (47 → 63 maps)
The previous commit registered the parity surface on Neovim but only ported ~75% to plain Vim. Filling the remaining 16: autoload/nuwiki/commands.vim — new functions: - `wiki_ui_select` — Vim has no `vim.ui.select`, so route through `inputlist()` after fetching the wiki list via the LSP. - `open_below_with_bullet` / `open_above_with_bullet` — port of the Lua `o` / `O` continuation that preserves the list marker (and a `[ ]` checkbox when present) on the new line. - `next_header` / `prev_header` / `next_sibling_header` / `prev_sibling_header` / `parent_header` — port of the Lua heading jumper. Pure VimL, no LSP round-trip. ftplugin/vimwiki.vim (Vim path) new mappings: - `<Leader>ws` → `wiki_ui_select` - `]=` / `[=` → next / prev sibling header - `]u` / `[u` → parent header - `o` / `O` → bullet continuation - `gl<Space>` / `gL<Space>` → :VimwikiRemove*CB stubs - `gq1` / `gw1` → :VimwikiTableAlignQ1/W1 stubs - x-mode variants for `+`, `<Leader>wc`, `gln`, `glp`, `glx` Replaced the regex-based `]]` / `[[` (which just searched `^\s*=\+\s`) with calls into the new heading nav so they skip non-heading `=` runs and respect heading levels. Verified end-to-end: `silent map <buffer>` reports 63 maps on Vim, matching Neovim's 63. All 377 Rust tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,123 @@ function! nuwiki#commands#wiki_index(count) abort
|
||||
\ function('s:open_uri_from'))
|
||||
endfunction
|
||||
|
||||
" Vim equivalent of the Lua `wiki_ui_select` — receives the list, asks
|
||||
" via `inputlist()` (no `vim.ui.select` on plain Vim), then opens.
|
||||
function! nuwiki#commands#wiki_ui_select() abort
|
||||
call s:exec('nuwiki.wiki.select', [{}],
|
||||
\ function('s:wiki_pick'))
|
||||
endfunction
|
||||
|
||||
function! s:wiki_pick(notification) abort
|
||||
let l:rows = get(get(a:notification, 'response', {}), 'result', [])
|
||||
if type(l:rows) != type([]) || empty(l:rows)
|
||||
echom 'nuwiki: no wikis configured'
|
||||
return
|
||||
endif
|
||||
let l:prompt = ['Pick a wiki:']
|
||||
let l:i = 0
|
||||
for l:w in l:rows
|
||||
let l:i += 1
|
||||
call add(l:prompt, l:i . '. ' . get(l:w, 'name', '?')
|
||||
\ . ' (' . get(l:w, 'root', '?') . ')')
|
||||
endfor
|
||||
let l:choice = inputlist(l:prompt)
|
||||
if l:choice < 1 || l:choice > len(l:rows)
|
||||
return
|
||||
endif
|
||||
let l:wiki_id = get(l:rows[l:choice - 1], 'id', l:choice - 1)
|
||||
call s:exec('nuwiki.wiki.openIndex', [{ 'wiki': l:wiki_id }],
|
||||
\ function('s:open_uri_from'))
|
||||
endfunction
|
||||
|
||||
" Pure-VimL bullet-continuation for `o` / `O` — mirrors the Lua side
|
||||
" so re-pressing the key keeps the list marker (and checkbox if any).
|
||||
function! nuwiki#commands#open_below_with_bullet() abort
|
||||
let l:line = getline('.')
|
||||
let l:match = matchlist(l:line, '^\(\s*\)\([-*#]\)\s')
|
||||
if empty(l:match)
|
||||
call feedkeys('o', 'n')
|
||||
return
|
||||
endif
|
||||
let l:prefix = l:match[1] . l:match[2] . ' '
|
||||
if l:line =~# '^\s*[-*#]\s\+\[[ xXoO.\-]\]'
|
||||
let l:prefix .= '[ ] '
|
||||
endif
|
||||
call feedkeys('o' . l:prefix, 'n')
|
||||
endfunction
|
||||
|
||||
function! nuwiki#commands#open_above_with_bullet() abort
|
||||
let l:line = getline('.')
|
||||
let l:match = matchlist(l:line, '^\(\s*\)\([-*#]\)\s')
|
||||
if empty(l:match)
|
||||
call feedkeys('O', 'n')
|
||||
return
|
||||
endif
|
||||
let l:prefix = l:match[1] . l:match[2] . ' '
|
||||
call feedkeys('O' . l:prefix, 'n')
|
||||
endfunction
|
||||
|
||||
" ===== Heading navigation (pure VimL) =====
|
||||
|
||||
function! s:heading_level(line) abort
|
||||
let l:lead = matchstr(a:line, '^\s*\zs=\+\ze\s')
|
||||
if l:lead ==# ''
|
||||
return 0
|
||||
endif
|
||||
let l:trail = matchstr(a:line, '\s\zs=\+\ze\s*$')
|
||||
if len(l:trail) != len(l:lead)
|
||||
return 0
|
||||
endif
|
||||
return len(l:lead)
|
||||
endfunction
|
||||
|
||||
function! s:current_heading_level() abort
|
||||
let l:lnum = line('.')
|
||||
while l:lnum > 0
|
||||
let l:lvl = s:heading_level(getline(l:lnum))
|
||||
if l:lvl > 0
|
||||
return [l:lvl, l:lnum]
|
||||
endif
|
||||
let l:lnum -= 1
|
||||
endwhile
|
||||
return [0, 0]
|
||||
endfunction
|
||||
|
||||
function! s:jump_heading(direction, predicate) abort
|
||||
let l:total = line('$')
|
||||
let l:i = line('.') + a:direction
|
||||
while l:i >= 1 && l:i <= l:total
|
||||
let l:lvl = s:heading_level(getline(l:i))
|
||||
if l:lvl > 0 && a:predicate(l:lvl, l:i)
|
||||
call cursor(l:i, 1)
|
||||
return
|
||||
endif
|
||||
let l:i += a:direction
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! nuwiki#commands#next_header() abort
|
||||
call s:jump_heading(1, {l, n -> 1})
|
||||
endfunction
|
||||
function! nuwiki#commands#prev_header() abort
|
||||
call s:jump_heading(-1, {l, n -> 1})
|
||||
endfunction
|
||||
function! nuwiki#commands#next_sibling_header() abort
|
||||
let [l:lvl, _] = s:current_heading_level()
|
||||
call s:jump_heading(1, {l, n -> l <= l:lvl})
|
||||
endfunction
|
||||
function! nuwiki#commands#prev_sibling_header() abort
|
||||
let [l:lvl, _] = s:current_heading_level()
|
||||
call s:jump_heading(-1, {l, n -> l <= l:lvl})
|
||||
endfunction
|
||||
function! nuwiki#commands#parent_header() abort
|
||||
let [l:lvl, _] = s:current_heading_level()
|
||||
if l:lvl <= 1
|
||||
return
|
||||
endif
|
||||
call s:jump_heading(-1, {l, n -> l < l:lvl})
|
||||
endfunction
|
||||
|
||||
function! nuwiki#commands#wiki_tab_index(count) abort
|
||||
let l:args = a:count > 0 ? [{ 'wiki': a:count - 1 }] : [{}]
|
||||
call s:exec('nuwiki.wiki.tabOpenIndex', l:args,
|
||||
|
||||
Reference in New Issue
Block a user