feat: forward expr/silent/noremap/replace_keycodes on KeySpec#19
Merged
feat: forward expr/silent/noremap/replace_keycodes on KeySpec#19
Conversation
Addresses #18. Lazy.nvim-style KeySpec entries that set expr=true (and related boolean opts) were silently dropped because keymap.map only forwarded desc/remap/nowait. Refactor M.map to an opts table and plumb all four standard vim.keymap.set booleans through apply_keys so migrations from lazy.nvim work without surprise. vim.keymap.set ignores noremap and derives it from remap, so translate the lazy.nvim noremap alias into remap before forwarding — otherwise noremap = false would silently still produce a non-remappable keymap. The lazy-trigger proxy mapping intentionally stays non-expr: it must feed the original lhs through nvim_feedkeys so the real (post-load) expr mapping fires.
80272f7 to
551cd25
Compare
Per code-review on #19, the proxy installer in lazy_trigger/keys.lua forwarded desc/mode/nowait/silent but omitted remap, leaving the proxy mapping inconsistent with the post-load real keymap when the user's KeySpec set remap=true (or noremap=false). The user's intent should apply to every press, not just post-load — `<plug>`-style remap chains and inspection tools alike read the proxy attributes. Forward remap with the same noremap→remap alias translation that apply_keys performs. expr/replace_keycodes remain the only deliberate omissions — the proxy's rhs is a Lua callback returning nil, so an expr proxy would feed nil keys and the plugin would never load. Tests: - replace_keycodes=false explicit override survives the expr-implied default mirror in keymap.lua (regression test for the `== nil` check that gates the auto-default). - Lazy proxy reflects remap=true and translates noremap=false. - Post-load handoff: pressing the proxy lhs deletes the proxy, runs process_spec, and installs the real expr=true keymap.
vim.keymap.set raises "replace_keycodes requires expr" if the option
is forwarded without expr. The SUPPORTED_OPTS pass-through made a
KeySpec like { lhs, rhs, replace_keycodes = true } crash apply_keys.
Gate the forward on expr inside M.map.
The noremap→remap alias translation was duplicated byte-for-byte in
keymap.apply_keys and lazy_trigger/keys.lua. Move it into M.map so
there is one source of truth, and let apply_keys pass the KeySpec
directly (the SUPPORTED_OPTS whitelist filters [1]/[2]/mode out).
Tests:
- KeySpec drops replace_keycodes when expr is unset (regression).
- Lazy proxy load handoff: post-load real keymap forwards silent and
the noremap alias (covers the plugin_loader → apply_keys path that
the existing eager `lazy = false` tests don't exercise).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #18.
What
Forward four
vim.keymap.setboolean options throughKeySpec→apply_keysso they aren't silently dropped:expr— the option originally requested in [Feature Request] support for expr option in keys? #18silentnoremap(lazy.nvim alias for!remap)replace_keycodesRefactors
keymap.M.mapto take an opts table instead of a positional arg list, and uses aSUPPORTED_OPTSwhitelist to keep forwarding closed over future additions.Why
Migrating a
keys = { ... }block from lazy.nvim should preserve behavior. Before this change,expr = true,silent = true, and friends were quietly ignored — the keymap was still installed, but without the requested attribute, which is a surprising failure mode for new users.Edge cases handled
noremapalias.vim.keymap.setexplicitly does not supportnoremapand derives it fromremap. Passingnoremapstraight through silently does nothing.keymap.luatranslatesnoremap→remapbefore forwarding, sonoremap = falseactually produces a remappable keymap. Explicitremapwins when both are provided.lazy_trigger/keys.luaruns a Lua closure that loads the plugin thennvim_feedkeys-replays the original lhs — it must not be an expr mapping itself. The proxy forwardsdesc/mode/nowait/silent/remap/noremapso the first (proxy) press matches subsequent presses through the real keymap;exprandreplace_keycodesare the only omissions, since the proxy's rhs is a Lua callback returning nil and making it expr would feed nil keys.replace_keycodesdefault. Documented to match Neovim's actual behavior (defaults totruewhenexpristrue), not the previously-claimedfalse.Tests
tests/lazy_keys_test.luaadds coverage for:expr=trueforwarded tovim.keymap.set(attribute check + end-to-end feedkeys round-trip)silent=trueforwardednoremap=trueforwardednoremap=falseproduces a remappable keymap (regression test for the alias translation)remap=true, noremap=trueresolves to remappable (explicitremapwins)replace_keycodes=trueforwarded withexprAll 322 tests pass.
Files
lua/zpack/keymap.luanoremapalias translationlua/zpack/lazy_trigger/keys.luaM.mapsignaturelua/zpack/types.luaKeySpecfieldsdoc/zpack.txt,docs/spec.mdreplace_keycodesdefaulttests/lazy_keys_test.lua