Skip to content

Conversation

@soifou
Copy link
Collaborator

@soifou soifou commented Nov 21, 2025

Things I want to test/fix:

{
    ['jk'] = { 'hide', 'fallback' },
    ['<C-x><C-o>'] = { 'show', 'fallback' },
    ['<Leader>cc'] = { 'show', 'fallback' },
}
vim.keymap.set('i', '<C-i>', function() vim.print('fallback to <C-i>') end, { unique = false })
vim.keymap.set('i', '<Tab>', function() vim.print('fallback to <Tab>') end, { unique = false })
vim.keymap.set('i', '<C-m>', function() vim.print('fallback to <C-m>') end, { unique = false })

{       
    ['<C-i>'] = { 'accept', 'snippet_forward', 'fallback' }, -- when fall back prints "fallback to <C-i>"
    ['<C-m>'] = { 'accept', 'fallback' }, -- when fall back prints "fallback to <C-m>"
}
  • Key composition
{
    ['<C-n>'] = { 'select_next' },
    ['<Tab>'] = {
       function() return '' end, -- would fallback
       function() return '<C-n>' end, -- would call `select_next`
    },
},
  • Recursive keymap
vim.keymap.set('i', '<F2>', '<Esc>:echo "Hello from F2"<CR>a', { noremap = true, silent = true })
{
   ['<Space><Space>'] = { function() return '<F2>' end }, -- would print "Hello from F2"
}
vim.cmd([[
  function! s:MyFunction()
    echo "script local function invoked"
  endfunction

  nnoremap <silent> <SNR>42_mykey :call <SID>MyFunction()<CR>
  nnoremap <silent> <Plug>(MyPlug) :echo "Plug mapping triggered"<CR>
]])

{
    ['<Leader>m'] = { function() return '<Esc><Plug>(MyPlug)a' end }, -- prints "Plug mapping triggered"
}
-  vim.schedule(function() completion_list.accept(opts) end)
-  return true
+  return completion_list.accept(opts)

Multi-key sequences like `<C-x><C-o>` were breaking because `expr=true`
triggers immediately on the first key.

We should detect multi-key mappings and wrap the callback to manually
feed returned keys back to Neovim.

Closes #453
@soifou

This comment was marked as outdated.

@saghen
Copy link
Owner

saghen commented Nov 21, 2025

Does calling feedkeys have any caveats that we should be aware of? If not, I'd like to adopt it for all the keymaps! Avoiding expr = true would avoid having to vim.schedule anything that edits the buffer, which would be great for scriptability. I don't mind the way you're detecting multi-key mappings but it would be great if there was a less hacky way (maybe replace_keycodes could help?)

@soifou
Copy link
Collaborator Author

soifou commented Nov 22, 2025

Thanks for the feedback, you give me some additional thinking! I'd like to explore this approach a bit more. The feedkeys solution does seem cleaner and we could get rid of multi-key detection if we turn off expr.

Edit: Updated PR description

@soifou soifou changed the title fix(keymap): handle multi-key mappings correctly refactor(keymap): improve fallback and key handling Nov 24, 2025
@soifou soifou marked this pull request as draft November 24, 2025 18:27
@saghen
Copy link
Owner

saghen commented Nov 25, 2025

Wow this is quite a bit of work, you'd end up fixing all the major issues with keymaps! These changes would be breaking, since theyre no longer vim.schedule so it might make sense to artificially vim.schedule or merge this into a new v2 branch.

Fyi, I got a bit ambitious with v2 so I'm going to reduce its scope. Just planning some light refactoring, these keymap changes, source-per-LSP, adopt blink.lib, and the improved API (for keymaps, enable, vim.g, dynamic config, etc)

@soifou
Copy link
Collaborator Author

soifou commented Nov 25, 2025

Yeah, as long as I'm here, I might as well fix these issues once and for all. I've had promising results locally. I don't mind working on this for v2, but last time I switched to this branch, everything was so broken that it was hard to make any convincing commits. Feel free to keep in touch on Matrix to coordinate!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants