ae96562969
Close the remaining Vim-vs-Neovim functional gaps:
* Text objects — new `autoload/nuwiki/textobjects.vim` mirroring
`lua/nuwiki/textobjects.lua`. All five pairs (ah/ih, aH/iH,
al/il, a\/i\, ac/ic) wired in the Vim path of `ftplugin/vimwiki.vim`
via the classic `:<C-u>call` idiom that works cleanly in both
operator-pending and visual modes.
* Folding — new `autoload/nuwiki/folding.vim` providing a regex
`foldexpr` over headings, plus a tidy `foldtext`. Wired in the
Vim path; opts out via `let g:nuwiki_no_folding = 1`.
* `smart_return` was using `setline()` / `append()` inside an
`<expr>` callback — fine on Neovim but plain Vim's stricter
textlock raised E565. Rewrote as pure keystrokes (matches the
Lua version): table rows insert via `<CR>...<Esc>0li`, empty
list lines break via `<Esc>0DA<CR>`.
* Function-name parity: added
`nuwiki#commands#heading_add_level`,
`nuwiki#commands#heading_remove_level`,
`nuwiki#commands#table_move_column_{left,right}` as thin
aliases over the original short names so the public
`nuwiki#commands#*` surface matches `require('nuwiki.commands').*`.
Test harness:
* `scripts/test-keymaps-vim.vim` extended from 12 to 30 cases:
4 smart_return, 3 smart_tab/<S-Tab>, 3 named-command exists,
4 text-object helpers, 1 `dah` end-to-end, 2 folding, and the
original 12 pure-VimL cases. (Visual-mode mark inspection in
`vim -e -s` stays unreliable, so text objects are exercised
at the helper level plus one operator-pending end-to-end.)
Gates: 456 Rust / 39 Neovim / 30 Vim.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
44 lines
1.4 KiB
VimL
44 lines
1.4 KiB
VimL
" autoload/nuwiki/folding.vim — `foldexpr` for vimwiki buffers.
|
|
"
|
|
" Mirrors lua/nuwiki/folding.lua. Pure regex over `getline()`, so works
|
|
" without a language server. Activated in `ftplugin/vimwiki.vim`:
|
|
"
|
|
" setlocal foldmethod=expr
|
|
" setlocal foldexpr=nuwiki#folding#expr()
|
|
" setlocal foldtext=nuwiki#folding#foldtext()
|
|
"
|
|
" Fold structure mirrors the document outline: each `= H1 =` opens a
|
|
" level-1 fold, each `== H2 ==` opens a level-2 fold, etc., and folds
|
|
" close implicitly at the next heading of same-or-shallower level (or
|
|
" end of buffer).
|
|
|
|
function! s:heading_level(line) abort
|
|
let l:lead = matchstr(a:line, '^\s*\zs=\+\ze\s')
|
|
if empty(l:lead) | return 0 | endif
|
|
let l:lvl = strlen(l:lead)
|
|
if l:lvl > 6 | return 0 | endif
|
|
let l:trail = matchstr(a:line, '\s\zs=\+\ze\s*$')
|
|
if empty(l:trail) || strlen(l:trail) != l:lvl
|
|
return 0
|
|
endif
|
|
return l:lvl
|
|
endfunction
|
|
|
|
function! nuwiki#folding#expr() abort
|
|
let l:line = getline(v:lnum)
|
|
let l:lvl = s:heading_level(l:line)
|
|
if l:lvl > 0
|
|
return '>' . l:lvl
|
|
endif
|
|
return '='
|
|
endfunction
|
|
|
|
function! nuwiki#folding#foldtext() abort
|
|
let l:line = getline(v:foldstart)
|
|
let l:title = substitute(l:line, '=', '', 'g')
|
|
let l:title = substitute(l:title, '^\s\+', '', '')
|
|
let l:title = substitute(l:title, '\s\+$', '', '')
|
|
let l:count = v:foldend - v:foldstart + 1
|
|
return '▸ ' . l:title . ' … (' . l:count . ' lines)'
|
|
endfunction
|