mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	feat(snippet): set snippet keymaps permanent instead of dynamic (#31887)
Problem:
Given that `vim.snippet.expand()` sets temporary `<tab>`/`<s-tab>`
keymaps there is no way to build "smart-tab" functionality where `<tab>`
chooses the next completion candidate if the popup menu is visible.
Solution:
Set the keymap permanent in `_defaults`.
The downside of this approach is that users of multiple snippet engine's
need to adapt their keymaps to handle all their engines that are in use.
For example:
    vim.keymap.set({ 'i', 's' }, "<Tab>", function()
      if foreign_snippet.active() then
        return "<Cmd>lua require('foreign_snippet').jump()<CR>"
      elseif vim.snippet.active({ direction = 1 }) then
        return "<Cmd>lua vim.snippet.jump(1)<CR>"
      else
        return key
      end
    end, { expr = true })
Upside is that using `vim.keymap.set` to override keymaps is a well
established pattern and `vim.snippet.expand` calls made by nvim itself
or plugins have working keymaps out of the box.
Co-authored-by: Maria José Solano <majosolano99@gmail.com>
			
			
This commit is contained in:
		 Mathias Fußenegger
					Mathias Fußenegger
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							6401b433f7
						
					
				
				
					commit
					123f8d229e
				
			| @@ -18,6 +18,20 @@ local retry = t.retry | ||||
| describe('vim.snippet', function() | ||||
|   before_each(function() | ||||
|     clear() | ||||
|     exec_lua(function() | ||||
|       local function set_snippet_jump(direction, key) | ||||
|         vim.keymap.set({ 'i', 's' }, key, function() | ||||
|           if vim.snippet.active({ direction = direction }) then | ||||
|             return string.format('<Cmd>lua vim.snippet.jump(%d)<CR>', direction) | ||||
|           else | ||||
|             return key | ||||
|           end | ||||
|         end, { silent = true, expr = true }) | ||||
|       end | ||||
|  | ||||
|       set_snippet_jump(1, '<Tab>') | ||||
|       set_snippet_jump(-1, '<S-Tab>') | ||||
|     end) | ||||
|   end) | ||||
|   after_each(clear) | ||||
|  | ||||
| @@ -289,24 +303,4 @@ describe('vim.snippet', function() | ||||
|     ]] | ||||
|     ) | ||||
|   end) | ||||
|  | ||||
|   it('restores snippet navigation keymaps', function() | ||||
|     -- Create a buffer keymap in insert mode that deletes all lines. | ||||
|     local curbuf = api.nvim_get_current_buf() | ||||
|     exec_lua('vim.api.nvim_buf_set_keymap(..., "i", "<Tab>", "<cmd>normal ggdG<cr>", {})', curbuf) | ||||
|  | ||||
|     test_expand_success({ 'var $1 = $2' }, { 'var  = ' }) | ||||
|  | ||||
|     -- While the snippet is active, <Tab> should navigate between tabstops. | ||||
|     feed('x') | ||||
|     poke_eventloop() | ||||
|     feed('<Tab>0') | ||||
|     eq({ 'var x = 0' }, buf_lines(0)) | ||||
|  | ||||
|     exec_lua('vim.snippet.stop()') | ||||
|  | ||||
|     -- After exiting the snippet, the buffer keymap should be restored. | ||||
|     feed('<Esc>O<cr><Tab>') | ||||
|     eq({ '' }, buf_lines(0)) | ||||
|   end) | ||||
| end) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user