-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Snippets
Yifan Hu edited this page Aug 4, 2023
·
25 revisions
Snippet support can be easily added to your config by installing an autocompletion plugin (such as nvim-cmp) and a snippets plugins (such as LuaSnip):
To enable snippets support for a given server with LuaSnip, the main steps are to:
- override the capabilities we send to a language server to let it know we support snippets
- set up your snippets source, and the autocompletion plugin to acknowledge the snippets source
- map the confirm and expand snippets keybinds.
local use = require('packer').use
require('packer').startup(function()
use 'neovim/nvim-lspconfig' -- Collection of configurations for built-in LSP client
use 'hrsh7th/nvim-cmp' -- Autocompletion plugin
use 'hrsh7th/cmp-nvim-lsp' -- LSP source for nvim-cmp
use 'saadparwaiz1/cmp_luasnip' -- Snippets source for nvim-cmp
use 'L3MON4D3/LuaSnip' -- Snippets plugin
end)
-- Add additional capabilities supported by nvim-cmp
local capabilities = require('cmp_nvim_lsp').default_capabilities()
local lspconfig = require('lspconfig')
-- Enable some language servers with the additional completion capabilities offered by nvim-cmp
local servers = { 'clangd', 'rust_analyzer', 'pyright', 'tsserver' }
for _, lsp in ipairs(servers) do
lspconfig[lsp].setup {
-- on_attach = my_custom_on_attach,
capabilities = capabilities,
}
end
-- luasnip setup
local luasnip = require 'luasnip'
-- nvim-cmp setup
local cmp = require 'cmp'
cmp.setup {
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
['<C-d>'] = cmp.mapping.scroll_docs(-4),
['<C-f>'] = cmp.mapping.scroll_docs(4),
['<C-Space>'] = cmp.mapping.complete(),
['<CR>'] = cmp.mapping.confirm {
behavior = cmp.ConfirmBehavior.Replace,
select = true,
},
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { 'i', 's' }),
}),
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
}),
}
local use = require('packer').use
require('packer').startup(function()
use 'neovim/nvim-lspconfig' -- Collection of configurations for built-in LSP client
use 'ms-jpq/coq_nvim'
use 'ms-jpq/coq.artifacts'
use 'ms-jpq/coq.thirdparty'
end)
local lspconfig = require('lspconfig')
-- Automatically start coq
vim.g.coq_settings = { auto_start = true }
-- Enable some language servers with the additional completion capabilities offered by nvim-cmp
local servers = { 'clangd', 'rust_analyzer', 'pyright', 'tsserver' }
for _, lsp in ipairs(servers) do
lspconfig[lsp].setup(require('coq').lsp_ensure_capabilities({
-- on_attach = my_custom_on_attach,
}))
end
Setup is similar to the luasnip
section above, but instead use calls to vsnips
functions inside cmp.setup
.
-- install cmp-vsnip and vim-vsnip with your plugin manager of choice
-- Setup nvim-cmp.
local cmp = require'cmp'
local feedkeys = require'cmp.utils.feedkeys'
local t = function (str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end
-- define other bindings and settings in this setup, only the relevant vsnips bindings are shown here
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
end,
},
mapping = cmp.mapping.preset.insert({
-- snippet movement with vsnips
['<C-j>'] = cmp.mapping(function (fallback)
if vim.fn['vsnip#jumpable'](1) == 1 then
feedkeys.call(t"<Plug>(vsnip-jump-next)", "")
else
fallback()
end
end, { 'i', 's', 'c' }),
['<C-h>'] = cmp.mapping(function (fallback)
if vim.fn['vsnip#jumpable'](-1) == 1 then
feedkeys.call(t"<Plug>(vsnip-jump-prev)", "")
else
fallback()
end
end, { 'i', 's', 'c' }),
}),
sources = cmp.config.sources({
{ name = 'path' },
{ name = 'buffer' },
{ name = 'nvim_lsp' },
{ name = 'vsnip' },
}),
})
local null_ls = require('null-ls')
null_ls.setup({
sources = {
-- snippets support
null_ls.builtins.completion.luasnip
},
})
Keymaps for LuaSnip are still handled by them.
" press <Tab> to expand or jump in a snippet. These can also be mapped separately
" via <Plug>luasnip-expand-snippet and <Plug>luasnip-jump-next.
imap <silent><expr> <Tab> luasnip#expand_or_jumpable() ? '<Plug>luasnip-expand-or-jump' : '<Tab>'
" -1 for jumping backwards.
inoremap <silent> <S-Tab> <cmd>lua require'luasnip'.jump(-1)<Cr>
snoremap <silent> <Tab> <cmd>lua require('luasnip').jump(1)<Cr>
snoremap <silent> <S-Tab> <cmd>lua require('luasnip').jump(-1)<Cr>
" For changing choices in choiceNodes (not strictly necessary for a basic setup).
imap <silent><expr> <C-E> luasnip#choice_active() ? '<Plug>luasnip-next-choice' : '<C-E>'
smap <silent><expr> <C-E> luasnip#choice_active() ? '<Plug>luasnip-next-choice' : '<C-E>'
Snippets can be loaded from vscode, snipmate, etc.