feat(keymaps): configurable map_prefix for the wiki command family (P2)
Mirror vimwiki's g:vimwiki_map_prefix. The whole <Leader>w* family was
hardcoded across the map layer; it is now built from a configurable prefix:
- Neovim: `map_prefix` setup() option (default '<Leader>w'), read by
lua/nuwiki/keymaps.lua (buffer-local) and lua/nuwiki/init.lua (global
entry points).
- Vim: g:nuwiki_map_prefix, applied via :exe in plugin/nuwiki.vim (global)
and ftplugin/vimwiki.vim (buffer-local).
Setting a custom prefix relocates <prefix>{w,t,s,i,n,d,r,c,h,hh,ha} and
<prefix><Leader>{w,y,t,m,i}, leaving nothing under the old <Leader>w*.
Non-prefix maps (<CR>, gl*, headers, …) are untouched.
Tests: new test-keymaps-vim-prefix.vim harness (21 cases, wired into
test-keymaps-vim.sh) + map_prefix.relocates_wiki_family in test-keymaps.lua.
Docs: README, doc/nuwiki.txt, lua config comment, vimwiki-gap.md ticked.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
" development/tests/test-keymaps-vim-prefix.vim — driven by
|
||||
" development/tests/test-keymaps-vim.sh.
|
||||
"
|
||||
" Custom-prefix regression. The shell driver sets
|
||||
" `g:nuwiki_map_prefix = '<Leader>n'` *before* the ftplugin loads, so this
|
||||
" harness asserts the whole wiki command family relocates under `<Leader>n*`
|
||||
" while nothing remains under the default `<Leader>w*`. Mirrors vimwiki's
|
||||
" `g:vimwiki_map_prefix` and the Lua-side `map_prefix` option.
|
||||
|
||||
let s:results = []
|
||||
let s:pass = 0
|
||||
let s:fail = 0
|
||||
let s:out = $NUWIKI_KEYMAP_RESULTS
|
||||
|
||||
function! s:record(ok, name, detail) abort
|
||||
let l:line = (a:ok ? 'PASS' : 'FAIL') . ' ' . a:name
|
||||
if a:detail !=# ''
|
||||
let l:line .= ' — ' . a:detail
|
||||
endif
|
||||
call add(s:results, l:line)
|
||||
if a:ok
|
||||
let s:pass += 1
|
||||
else
|
||||
let s:fail += 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
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
|
||||
|
||||
" Every <prefix>* mapping must now live under <Leader>n (prefix = <Leader>n).
|
||||
let s:relocated = [
|
||||
\ ['<Leader>nw', 'n'], ['<Leader>nt', 'n'], ['<Leader>ns', 'n'], ['<Leader>ni', 'n'],
|
||||
\ ['<Leader>n<Leader>w', 'n'], ['<Leader>n<Leader>y', 'n'], ['<Leader>n<Leader>t', 'n'],
|
||||
\ ['<Leader>n<Leader>m', 'n'], ['<Leader>n<Leader>i', 'n'],
|
||||
\ ['<Leader>nn', 'n'], ['<Leader>nd', 'n'], ['<Leader>nr', 'n'], ['<Leader>nc', 'n'],
|
||||
\ ['<Leader>nh', 'n'], ['<Leader>nhh', 'n'], ['<Leader>nha', 'n'],
|
||||
\ ]
|
||||
for s:e in s:relocated
|
||||
let s:ok = s:has_map(s:e[0], s:e[1])
|
||||
call s:record(s:ok ? 1 : 0, 'prefix.relocated.' . s:e[1] . '.' . s:e[0],
|
||||
\ s:ok ? '' : s:e[0] . ' not bound under custom prefix')
|
||||
endfor
|
||||
|
||||
" The default <Leader>w* family must be GONE (relocated, not duplicated).
|
||||
let s:gone = [
|
||||
\ ['<Leader>ww', 'n'], ['<Leader>wr', 'n'], ['<Leader>wh', 'n'],
|
||||
\ ['<Leader>w<Leader>w', 'n'],
|
||||
\ ]
|
||||
for s:e in s:gone
|
||||
let s:ok = !s:has_map(s:e[0], s:e[1])
|
||||
call s:record(s:ok ? 1 : 0, 'prefix.default_gone.' . s:e[1] . '.' . s:e[0],
|
||||
\ s:ok ? '' : s:e[0] . ' still mapped despite custom prefix')
|
||||
endfor
|
||||
|
||||
" Non-prefix maps (links group) are unaffected by the prefix change.
|
||||
let s:cr = s:has_map('<CR>', 'n')
|
||||
call s:record(s:cr ? 1 : 0, 'prefix.cr_unaffected', s:cr ? '' : '<CR> lost')
|
||||
|
||||
call add(s:results, '')
|
||||
call add(s:results, printf('SUMMARY: %d passed, %d failed', s:pass, s:fail))
|
||||
call writefile(s:results, s:out)
|
||||
execute (s:fail == 0 ? 'qall!' : 'cquit!')
|
||||
@@ -96,7 +96,41 @@ fi
|
||||
|
||||
cat "$RESULTS_OPTOUT"
|
||||
|
||||
if grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$RESULTS_OPTOUT"; then
|
||||
if ! grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$RESULTS_OPTOUT"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ===== Custom map_prefix run =====
|
||||
# Fresh Vim instance with g:nuwiki_map_prefix set *before* the ftplugin
|
||||
# loads, so we can assert the whole wiki command family relocates under the
|
||||
# custom prefix and nothing remains under the default <Leader>w*.
|
||||
|
||||
VIMRC_PREFIX="$TMP/vimrc-prefix"
|
||||
cat > "$VIMRC_PREFIX" <<EOF
|
||||
set nocompatible
|
||||
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
|
||||
let g:nuwiki_map_prefix = '<Leader>n'
|
||||
filetype plugin indent on
|
||||
syntax enable
|
||||
EOF
|
||||
|
||||
RESULTS_PREFIX="$TMP/results-prefix.txt"
|
||||
|
||||
log "running custom-prefix harness…"
|
||||
NUWIKI_KEYMAP_RESULTS="$RESULTS_PREFIX" \
|
||||
timeout 30 vim -e -s -u "$VIMRC_PREFIX" -c "edit $SEED" -c "source $REPO_ROOT/development/tests/test-keymaps-vim-prefix.vim" \
|
||||
</dev/null >"$TMP/vim-prefix.log" 2>&1 || true
|
||||
|
||||
if [[ ! -f "$RESULTS_PREFIX" ]]; then
|
||||
echo 'keymap custom-prefix harness produced no output' >&2
|
||||
echo '--- vim log ---' >&2
|
||||
cat "$TMP/vim-prefix.log" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "$RESULTS_PREFIX"
|
||||
|
||||
if grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$RESULTS_PREFIX"; then
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
|
||||
@@ -820,6 +820,36 @@ vim.defer_fn(function()
|
||||
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
|
||||
-- bindings exist there while the default <Leader>w* ones do not.
|
||||
tobj_case('map_prefix.relocates_wiki_family', function()
|
||||
local config = require('nuwiki.config')
|
||||
local keymaps = require('nuwiki.keymaps')
|
||||
local saved = config.options.map_prefix
|
||||
config.options.map_prefix = '<Leader>n'
|
||||
local buf = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_set_current_buf(buf)
|
||||
local ok, err = pcall(function()
|
||||
keymaps.attach(buf, { enabled = true, wiki_prefix = true, links = true, html_export = true })
|
||||
local function bmap(lhs)
|
||||
local d = vim.fn.maparg(lhs, 'n', false, true)
|
||||
return not vim.tbl_isempty(d) and d.buffer == 1
|
||||
end
|
||||
for _, lhs in ipairs({
|
||||
'<Leader>nw', '<Leader>nt', '<Leader>n<Leader>w', '<Leader>nr', '<Leader>nh', '<Leader>nha',
|
||||
}) do
|
||||
if not bmap(lhs) then error('relocated map missing: ' .. lhs) end
|
||||
end
|
||||
if bmap('<Leader>ww') then error('<Leader>ww still bound under custom prefix') end
|
||||
end)
|
||||
-- Always restore global state so later cases see the default prefix.
|
||||
config.options.map_prefix = saved
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
if not ok then error(err) end
|
||||
end)
|
||||
|
||||
-- ===== Wiki picker (config-driven, no LSP) =====
|
||||
-- The picker must build its list from config so it works from any buffer
|
||||
-- before the server attaches.
|
||||
|
||||
Reference in New Issue
Block a user