The vim.snippet module provides functionality for expanding and navigating LSP-style snippets. Snippets support placeholders, tabstops, variables, and transformations according to the LSP snippet specification.
-- Simple tabstopvim.snippet.expand('$1 and $2 and $0')-- Tabstop with placeholdervim.snippet.expand('${1:default value}')-- Final tabstop (always $0)vim.snippet.expand('function() {\n\t$0\n}')
True if snippet is active (and jumpable in direction, if specified)
-- Check if any snippet is activeif vim.snippet.active() then print('Snippet is active')end-- Check if can jump forwardif vim.snippet.active({ direction = 1 }) then vim.snippet.jump(1)end-- Check if can jump backwardif vim.snippet.active({ direction = -1 }) then vim.snippet.jump(-1)end
-- Snippet databaselocal snippets = { lua = { fn = 'function ${1:name}(${2:args})\n\t$0\nend', req = 'local ${1:module} = require("${2:module}")', }, python = { def = 'def ${1:name}(${2:args}):\n\t${0:pass}', cls = 'class ${1:Name}:\n\tdef __init__(self, ${2:args}):\n\t\t${0:pass}', },}-- Expand snippet by triggerlocal function expand_snippet(trigger) local ft = vim.bo.filetype local snippet = snippets[ft] and snippets[ft][trigger] if snippet then vim.snippet.expand(snippet) return true end return falseend-- Use in insert modevim.keymap.set('i', '<C-k>', function() local line = vim.api.nvim_get_current_line() local col = vim.api.nvim_win_get_cursor(0)[2] local before = line:sub(1, col) local trigger = before:match('[%w_]+$') if trigger and expand_snippet(trigger) then -- Delete trigger text vim.api.nvim_set_current_line( line:sub(1, col - #trigger) .. line:sub(col + 1) ) return '' end return '<C-k>'end, { expr = true })
local function smart_expand() -- Check if in comment local node = vim.treesitter.get_node() if node and node:type() == 'comment' then return false end -- Check if can expand local line = vim.api.nvim_get_current_line() local col = vim.api.nvim_win_get_cursor(0)[2] if line:sub(col, col):match('%w') then return false end -- Expand snippet vim.snippet.expand('${1:placeholder}') return trueend
local try_catch = [[try { ${1:// try block}} catch (${2:error}) { ${3:// error handling}} finally { ${4:// cleanup}}$0]]vim.snippet.expand(try_catch)-- Automatically indents based on current line
vim.api.nvim_create_autocmd('CompleteDone', { callback = function() local completed_item = vim.v.completed_item if completed_item and completed_item.kind == vim.lsp.protocol.CompletionItemKind.Snippet then local snippet = completed_item.textEdit and completed_item.textEdit.newText or completed_item.insertText if snippet then -- Remove inserted text local line = vim.api.nvim_get_current_line() local col = vim.api.nvim_win_get_cursor(0)[2] local before = line:sub(1, col - #completed_item.word) local after = line:sub(col + 1) vim.api.nvim_set_current_line(before .. after) -- Expand snippet vim.snippet.expand(snippet) end end end,})