feat(client): add per-subgroup Vim mapping opt-out globals
The plain-Vim ftplugin only exposed a whole-layer
g:nuwiki_no_default_mappings gate, so Vim users could not drop a single
keymap group the way Neovim users can via mappings.<group> = false. Add
g:nuwiki_no_{wiki_prefix,links,lists,headers,table_editing,diary,
html_export,text_objects}_mappings, each wrapping its group block, to
reach parity with lua/nuwiki/keymaps.lua. Cover them with a dedicated
opt-out harness and document them in the README and help file.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -257,6 +257,8 @@ let g:nuwiki_link_severity = 'warn' " 'off'|'hint'|'warn'|'error'
|
||||
let g:nuwiki_no_default_mappings = 0 " set to 1 to skip the keymap layer
|
||||
let g:nuwiki_no_folding = 0 " set to 1 to skip foldexpr setup
|
||||
let g:nuwiki_mouse_mappings = 0 " set to 1 to enable mouse maps
|
||||
" Drop individual keymap subgroups (mirror the Lua `mappings.<group>` toggles):
|
||||
" g:nuwiki_no_{wiki_prefix,links,lists,headers,table_editing,diary,html_export,text_objects}_mappings
|
||||
```
|
||||
|
||||
### Reference
|
||||
@@ -337,7 +339,15 @@ For users configuring without Lua.
|
||||
| `g:nuwiki_file_extension` | `'.wiki'` | wiki file extension |
|
||||
| `g:nuwiki_log_level` | `'warn'` | `error` \| `warn` \| `info` \| `debug` |
|
||||
| `g:nuwiki_link_severity` | `'warn'` | broken-link severity: `off` \| `hint` \| `warn` \| `error` |
|
||||
| `g:nuwiki_no_default_mappings` | `0` | `1` skips the keymap layer |
|
||||
| `g:nuwiki_no_default_mappings` | `0` | `1` skips the whole keymap layer |
|
||||
| `g:nuwiki_no_wiki_prefix_mappings` | `0` | `1` skips the `<Leader>w*` group |
|
||||
| `g:nuwiki_no_links_mappings` | `0` | `1` skips the link group (`<CR>`, `+`, …) |
|
||||
| `g:nuwiki_no_lists_mappings` | `0` | `1` skips the list group (`<C-Space>`, `gl*`, `o`/`O`, …) |
|
||||
| `g:nuwiki_no_headers_mappings` | `0` | `1` skips the header group (`=`, `-`, `]]`, …) |
|
||||
| `g:nuwiki_no_table_editing_mappings` | `0` | `1` skips the table group (`gqq`, `<A-Left>`, insert `<Tab>`) |
|
||||
| `g:nuwiki_no_diary_mappings` | `0` | `1` skips the diary nav group (`<C-Down>`, `<C-Up>`) |
|
||||
| `g:nuwiki_no_html_export_mappings` | `0` | `1` skips the HTML export group (`<Leader>wh*`) |
|
||||
| `g:nuwiki_no_text_objects_mappings` | `0` | `1` skips the text-object group (`ah`, `il`, …) |
|
||||
| `g:nuwiki_no_folding` | `0` | `1` skips foldexpr setup |
|
||||
| `g:nuwiki_mouse_mappings` | `0` | `1` enables mouse maps |
|
||||
|
||||
@@ -443,8 +453,10 @@ instead.
|
||||
|
||||
### Default keymaps
|
||||
|
||||
All buffer-local. Disable any group via `mappings.<group> = false` in
|
||||
Neovim, or `let g:nuwiki_no_default_mappings = 1` in Vim.
|
||||
All buffer-local. Disable the whole layer via `mappings.enabled = false` in
|
||||
Neovim, or `let g:nuwiki_no_default_mappings = 1` in Vim. Drop a single group
|
||||
via `mappings.<group> = false` in Neovim, or
|
||||
`let g:nuwiki_no_<group>_mappings = 1` in Vim.
|
||||
|
||||
**Links** (normal mode)
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
" development/tests/test-keymaps-vim-optout.vim — driven by
|
||||
" development/tests/test-keymaps-vim.sh.
|
||||
"
|
||||
" Per-subgroup mapping opt-out regression. The shell driver sets a subset
|
||||
" of `g:nuwiki_no_<group>_mappings = 1` globals *before* the ftplugin loads,
|
||||
" so this harness asserts that the disabled groups leave no buffer-local
|
||||
" mappings while the still-enabled groups keep theirs. Mirrors the Lua-side
|
||||
" subgroup toggles in lua/nuwiki/keymaps.lua.
|
||||
|
||||
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
|
||||
|
||||
" Groups the driver disabled (g:nuwiki_no_<group>_mappings = 1): every
|
||||
" representative LHS below must be ABSENT.
|
||||
let s:disabled = [
|
||||
\ ['wiki_prefix', '<Leader>ww', 'n'],
|
||||
\ ['wiki_prefix', '<Leader>w<Leader>w', 'n'],
|
||||
\ ['links', '<CR>', 'n'],
|
||||
\ ['links', '+', 'n'],
|
||||
\ ['links', '<Leader>wr', 'n'],
|
||||
\ ['headers', '=', 'n'],
|
||||
\ ['headers', ']]', 'n'],
|
||||
\ ['headers', ']u', 'n'],
|
||||
\ ['text_objects', 'ah', 'x'],
|
||||
\ ['text_objects', 'il', 'o'],
|
||||
\ ]
|
||||
for s:e in s:disabled
|
||||
let s:ok = !s:has_map(s:e[1], s:e[2])
|
||||
call s:record(s:ok ? 1 : 0, 'optout.' . s:e[0] . '.' . s:e[2] . '.' . s:e[1],
|
||||
\ s:ok ? '' : s:e[1] . ' (' . s:e[2] . ') still mapped despite opt-out')
|
||||
endfor
|
||||
|
||||
" Groups left enabled: every representative LHS must still be PRESENT.
|
||||
let s:enabled = [
|
||||
\ ['lists', 'gln', 'n'],
|
||||
\ ['lists', 'gnt', 'n'],
|
||||
\ ['lists', '<C-Space>', 'n'],
|
||||
\ ['diary', '<C-Down>', 'n'],
|
||||
\ ['table_editing', 'gqq', 'n'],
|
||||
\ ['table_editing', '<A-Left>', 'n'],
|
||||
\ ['html_export', '<Leader>wh', 'n'],
|
||||
\ ['html_export', '<Leader>wha', 'n'],
|
||||
\ ]
|
||||
for s:e in s:enabled
|
||||
let s:ok = s:has_map(s:e[1], s:e[2])
|
||||
call s:record(s:ok ? 1 : 0, 'kept.' . s:e[0] . '.' . s:e[2] . '.' . s:e[1],
|
||||
\ s:ok ? '' : s:e[1] . ' (' . s:e[2] . ') unexpectedly absent')
|
||||
endfor
|
||||
|
||||
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!')
|
||||
@@ -59,7 +59,44 @@ fi
|
||||
|
||||
cat "$RESULTS"
|
||||
|
||||
if grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$RESULTS"; then
|
||||
if ! grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$RESULTS"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ===== Per-subgroup opt-out run =====
|
||||
# Fresh Vim instance with a subset of g:nuwiki_no_<group>_mappings set
|
||||
# *before* the ftplugin loads, so we can assert the disabled groups drop
|
||||
# their bindings while the rest survive.
|
||||
|
||||
VIMRC_OPTOUT="$TMP/vimrc-optout"
|
||||
cat > "$VIMRC_OPTOUT" <<EOF
|
||||
set nocompatible
|
||||
let &runtimepath = '$REPO_ROOT' . ',' . &runtimepath
|
||||
let g:nuwiki_no_wiki_prefix_mappings = 1
|
||||
let g:nuwiki_no_links_mappings = 1
|
||||
let g:nuwiki_no_headers_mappings = 1
|
||||
let g:nuwiki_no_text_objects_mappings = 1
|
||||
filetype plugin indent on
|
||||
syntax enable
|
||||
EOF
|
||||
|
||||
RESULTS_OPTOUT="$TMP/results-optout.txt"
|
||||
|
||||
log "running opt-out harness…"
|
||||
NUWIKI_KEYMAP_RESULTS="$RESULTS_OPTOUT" \
|
||||
timeout 30 vim -e -s -u "$VIMRC_OPTOUT" -c "edit $SEED" -c "source $REPO_ROOT/development/tests/test-keymaps-vim-optout.vim" \
|
||||
</dev/null >"$TMP/vim-optout.log" 2>&1 || true
|
||||
|
||||
if [[ ! -f "$RESULTS_OPTOUT" ]]; then
|
||||
echo 'keymap opt-out harness produced no output' >&2
|
||||
echo '--- vim log ---' >&2
|
||||
cat "$TMP/vim-optout.log" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "$RESULTS_OPTOUT"
|
||||
|
||||
if grep -qE '^SUMMARY: [0-9]+ passed, 0 failed' "$RESULTS_OPTOUT"; then
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
|
||||
+27
-2
@@ -207,6 +207,28 @@ Vim-specific globals ~
|
||||
When 1, the Vim path skips every buffer-local keymap. Equivalent to
|
||||
`mappings.enabled = false` in Neovim.
|
||||
|
||||
*g:nuwiki_no_wiki_prefix_mappings*
|
||||
*g:nuwiki_no_links_mappings*
|
||||
*g:nuwiki_no_lists_mappings*
|
||||
*g:nuwiki_no_headers_mappings*
|
||||
*g:nuwiki_no_table_editing_mappings*
|
||||
*g:nuwiki_no_diary_mappings*
|
||||
*g:nuwiki_no_html_export_mappings*
|
||||
*g:nuwiki_no_text_objects_mappings*
|
||||
`g:nuwiki_no_<group>_mappings` 0
|
||||
Per-subgroup opt-outs, each defaulting to 0. Setting one to 1 drops just
|
||||
that group's buffer-local keymaps while leaving the rest in place; the
|
||||
whole-layer |g:nuwiki_no_default_mappings| still wins over all of them.
|
||||
These mirror the Lua-side `mappings.<group>` booleans. Valid groups:
|
||||
`wiki_prefix` `<Leader>w*`
|
||||
`links` `<CR>`, `<S-CR>`, `<Tab>`, `<BS>`, `+`, …
|
||||
`lists` `<C-Space>`, `gl*`, `o`/`O`, insert-mode list edits
|
||||
`headers` `=`, `-`, `]]`, `[[`, `]=`, `[=`, `]u`, `[u`
|
||||
`table_editing` `gqq`, `<A-Left>`, `<A-Right>`, insert `<Tab>`
|
||||
`diary` `<C-Down>`, `<C-Up>`
|
||||
`html_export` `<Leader>wh`, `<Leader>whh`, `<Leader>wha`
|
||||
`text_objects` `ah`, `ih`, `al`, `il`, `a\`, `i\`, `ac`, `ic`
|
||||
|
||||
*g:nuwiki_no_folding*
|
||||
`g:nuwiki_no_folding` 0
|
||||
When 1, the Vim path skips `foldexpr` / `foldmethod` setup.
|
||||
@@ -378,8 +400,11 @@ Other ~
|
||||
==============================================================================
|
||||
6. KEYMAPS *nuwiki-keymaps*
|
||||
|
||||
Every keymap is buffer-local. Disable a group via `mappings.<group> =
|
||||
false` in Neovim, or `let g:nuwiki_no_default_mappings = 1` in Vim.
|
||||
Every keymap is buffer-local. Disable the whole layer via
|
||||
`mappings.enabled = false` in Neovim, or `let g:nuwiki_no_default_mappings
|
||||
= 1` in Vim. Drop a single group via `mappings.<group> = false` in Neovim,
|
||||
or `let g:nuwiki_no_<group>_mappings = 1` in Vim (see
|
||||
|g:nuwiki_no_links_mappings| for the group list).
|
||||
|
||||
Links (normal mode) ~
|
||||
|
||||
|
||||
+24
-5
@@ -171,11 +171,15 @@ if !has('nvim')
|
||||
|
||||
" ===== Default key mappings (parity with upstream vimwiki) =====
|
||||
"
|
||||
" Users can opt out by setting `g:nuwiki_no_default_mappings = 1`
|
||||
" (whole layer) or by adding their own competing buffer-local maps.
|
||||
" Users can opt out of the whole layer with `g:nuwiki_no_default_mappings = 1`,
|
||||
" or flip individual subgroups off via `g:nuwiki_no_<group>_mappings = 1`
|
||||
" (group ∈ wiki_prefix, links, lists, headers, table_editing, diary,
|
||||
" html_export, text_objects). These mirror the Lua-side `mappings.<group>`
|
||||
" toggles in lua/nuwiki/keymaps.lua.
|
||||
|
||||
if !get(g:, 'nuwiki_no_default_mappings', 0)
|
||||
" Wiki prefix
|
||||
if !get(g:, 'nuwiki_no_wiki_prefix_mappings', 0)
|
||||
nnoremap <silent><buffer> <Leader>ww :call nuwiki#commands#wiki_index(0)<CR>
|
||||
nnoremap <silent><buffer> <Leader>wt :call nuwiki#commands#wiki_tab_index(0)<CR>
|
||||
nnoremap <silent><buffer> <Leader>ws :call nuwiki#commands#wiki_ui_select()<CR>
|
||||
@@ -185,8 +189,10 @@ if !has('nvim')
|
||||
nnoremap <silent><buffer> <Leader>w<Leader>t :call nuwiki#commands#diary_tomorrow()<CR>
|
||||
nnoremap <silent><buffer> <Leader>w<Leader>m :call nuwiki#commands#diary_tomorrow()<CR>
|
||||
nnoremap <silent><buffer> <Leader>w<Leader>i :call nuwiki#commands#diary_generate_index()<CR>
|
||||
endif
|
||||
|
||||
" Links
|
||||
if !get(g:, 'nuwiki_no_links_mappings', 0)
|
||||
nnoremap <silent><buffer> <CR> :call nuwiki#commands#follow_link_or_create()<CR>
|
||||
nnoremap <silent><buffer> <S-CR> :split<CR>:call nuwiki#commands#follow_link_or_create()<CR>
|
||||
nnoremap <silent><buffer> <C-CR> :vsplit<CR>:call nuwiki#commands#follow_link_or_create()<CR>
|
||||
@@ -201,12 +207,16 @@ if !has('nvim')
|
||||
nnoremap <silent><buffer> <Leader>wr :call nuwiki#commands#rename_file()<CR>
|
||||
nnoremap <silent><buffer> <Leader>wc :call nuwiki#commands#colorize('')<CR>
|
||||
xnoremap <silent><buffer> <Leader>wc :<C-u>call nuwiki#commands#colorize('')<CR>
|
||||
endif
|
||||
|
||||
" Diary nav
|
||||
if !get(g:, 'nuwiki_no_diary_mappings', 0)
|
||||
nnoremap <silent><buffer> <C-Down> :call nuwiki#commands#diary_next()<CR>
|
||||
nnoremap <silent><buffer> <C-Up> :call nuwiki#commands#diary_prev()<CR>
|
||||
endif
|
||||
|
||||
" Lists
|
||||
if !get(g:, 'nuwiki_no_lists_mappings', 0)
|
||||
nnoremap <silent><buffer> <C-Space> :call nuwiki#commands#toggle_list_item()<CR>
|
||||
xnoremap <silent><buffer> <C-Space> :<C-u>call nuwiki#commands#toggle_list_item()<CR>
|
||||
nnoremap <silent><buffer> <C-@> :call nuwiki#commands#toggle_list_item()<CR>
|
||||
@@ -238,10 +248,10 @@ if !has('nvim')
|
||||
inoremap <silent><buffer> <C-L><C-K> <C-o>:call nuwiki#commands#list_cycle_symbol(-1)<CR>
|
||||
inoremap <silent><buffer> <C-L><C-M> <C-o>:call nuwiki#commands#list_toggle_or_add_checkbox()<CR>
|
||||
inoremap <silent><buffer><expr> <CR> nuwiki#commands#smart_return()
|
||||
inoremap <silent><buffer><expr> <Tab> nuwiki#commands#smart_tab()
|
||||
inoremap <silent><buffer><expr> <S-Tab> nuwiki#commands#smart_shift_tab()
|
||||
endif
|
||||
|
||||
" Headers
|
||||
if !get(g:, 'nuwiki_no_headers_mappings', 0)
|
||||
nnoremap <silent><buffer> = :call nuwiki#commands#heading_add()<CR>
|
||||
nnoremap <silent><buffer> - :call nuwiki#commands#heading_remove()<CR>
|
||||
nnoremap <silent><buffer> ]] :call nuwiki#commands#next_header()<CR>
|
||||
@@ -250,11 +260,14 @@ if !has('nvim')
|
||||
nnoremap <silent><buffer> [= :call nuwiki#commands#prev_sibling_header()<CR>
|
||||
nnoremap <silent><buffer> ]u :call nuwiki#commands#parent_header()<CR>
|
||||
nnoremap <silent><buffer> [u :call nuwiki#commands#parent_header()<CR>
|
||||
endif
|
||||
|
||||
" HTML export
|
||||
if !get(g:, 'nuwiki_no_html_export_mappings', 0)
|
||||
nnoremap <silent><buffer> <Leader>wh :call nuwiki#commands#export_current()<CR>
|
||||
nnoremap <silent><buffer> <Leader>whh :call nuwiki#commands#export_browse()<CR>
|
||||
nnoremap <silent><buffer> <Leader>wha :call nuwiki#commands#export_all()<CR>
|
||||
endif
|
||||
|
||||
" Mouse (opt-in via g:nuwiki_mouse_mappings = 1).
|
||||
if get(g:, 'nuwiki_mouse_mappings', 0)
|
||||
@@ -265,13 +278,17 @@ if !has('nvim')
|
||||
nnoremap <silent><buffer> <RightMouse> <C-o>
|
||||
endif
|
||||
|
||||
" Tables
|
||||
" Tables (and insert-mode table-cell navigation, same surface).
|
||||
if !get(g:, 'nuwiki_no_table_editing_mappings', 0)
|
||||
nnoremap <silent><buffer> gqq :call nuwiki#commands#table_align()<CR>
|
||||
nnoremap <silent><buffer> gq1 :call nuwiki#commands#table_align()<CR>
|
||||
nnoremap <silent><buffer> gww :call nuwiki#commands#table_align()<CR>
|
||||
nnoremap <silent><buffer> gw1 :call nuwiki#commands#table_align()<CR>
|
||||
nnoremap <silent><buffer> <A-Left> :call nuwiki#commands#table_move_left()<CR>
|
||||
nnoremap <silent><buffer> <A-Right> :call nuwiki#commands#table_move_right()<CR>
|
||||
inoremap <silent><buffer><expr> <Tab> nuwiki#commands#smart_tab()
|
||||
inoremap <silent><buffer><expr> <S-Tab> nuwiki#commands#smart_shift_tab()
|
||||
endif
|
||||
|
||||
" Folding — heading-block fold structure (matches lua/nuwiki/folding.lua).
|
||||
" Opt-out via `let g:nuwiki_no_folding = 1` (mirrors the Lua-side
|
||||
@@ -290,6 +307,7 @@ if !has('nvim')
|
||||
" Text objects — vimwiki parity (matches lua/nuwiki/textobjects.lua).
|
||||
" The `:<C-u>` clears any prefix count and the visual mode; the
|
||||
" autoload function re-establishes the selection at the right range.
|
||||
if !get(g:, 'nuwiki_no_text_objects_mappings', 0)
|
||||
xnoremap <silent><buffer> ah :<C-u>call nuwiki#textobjects#heading(0, 0)<CR>
|
||||
onoremap <silent><buffer> ah :<C-u>call nuwiki#textobjects#heading(0, 0)<CR>
|
||||
xnoremap <silent><buffer> ih :<C-u>call nuwiki#textobjects#heading(1, 0)<CR>
|
||||
@@ -311,6 +329,7 @@ if !has('nvim')
|
||||
xnoremap <silent><buffer> ic :<C-u>call nuwiki#textobjects#table_column(1)<CR>
|
||||
onoremap <silent><buffer> ic :<C-u>call nuwiki#textobjects#table_column(1)<CR>
|
||||
endif
|
||||
endif
|
||||
|
||||
finish
|
||||
endif
|
||||
|
||||
Reference in New Issue
Block a user