This moves all of the snippets into a yasnippet file format so I can better manage and edit the snippets. I did not like having them all in one file stored as strings. This implements a custom file parser that will convert the snippet file into a luasnip parsed snippet that uses the LSP snippet syntax. It also ports over some of my most used snippets from the emacs config, maybe one day I could share the snippet in vim and emacs.
98 lines
3.2 KiB
Lua
98 lines
3.2 KiB
Lua
-- Add lua snippets from a yasnippet style snippet format. This is so I can
|
|
-- manage the snippet in file format rather than in json or lua. Supports
|
|
-- adding attributes that will be added to `context` of the luasnip. The body
|
|
-- of the snippets are in lsp-snippets format and will be run though the
|
|
-- `parse_snippet` function from luasnip
|
|
--
|
|
-- See: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#snippet_syntax
|
|
-- See: https://github.com/L3MON4D3/LuaSnip/blob/master/DOC.md#snippets
|
|
--
|
|
local ls = require "luasnip"
|
|
|
|
-- Parse a line in the snippet. Will parse a key value attribute in the the line
|
|
-- formatted `# key: value` if a key is not found then the key will be `body`
|
|
-- and the hole line will be added to the value.
|
|
local function parse_snippet_line(line)
|
|
-- This is the body separator for the metadata to the body of the snippet
|
|
if line == "# --" then
|
|
return { mode = "skip" }
|
|
end
|
|
|
|
local key = line:match "#%s+(.*):"
|
|
-- If there is no key then its part of the body and it needs to be
|
|
-- concatenated to the other lines
|
|
if key == nil then
|
|
return { key = "body", mode = "concat", value = line }
|
|
end
|
|
|
|
local value = line:match ":%s+(.*)$"
|
|
|
|
-- Split the string on `,` if its the filetypes so we can add the snippet to
|
|
-- multiple filetypes
|
|
if key == "filetypes" then
|
|
value = vim.split(value, ",")
|
|
end
|
|
|
|
return { key = key, value = value, mode = "set" }
|
|
end
|
|
|
|
-- Parses a hole snippet file into a snippet table that can be added as luasnip
|
|
-- snippet. Header key value attribute are parsed into a table and the body of
|
|
-- the snippet (anything after the "# --") is added as the `body` as a table
|
|
-- of lines
|
|
local function parse_snippet_file(file_path)
|
|
local file = io.open(file_path, "r")
|
|
local snippet = {}
|
|
if file == nil then
|
|
return snippet
|
|
end
|
|
|
|
for line in file:lines() do
|
|
local line_content = parse_snippet_line(line)
|
|
if line_content.mode == "concat" then
|
|
-- Set the key attribute if it dose not exists already we will get a nil
|
|
-- error if we try to append to a key that is not in the snippet table
|
|
if snippet[line_content.key] == nil then
|
|
snippet[line_content.key] = {}
|
|
end
|
|
|
|
table.insert(snippet[line_content.key], line_content.value)
|
|
elseif line_content.mode == "set" then
|
|
snippet[line_content.key] = line_content.value
|
|
end
|
|
end
|
|
|
|
return snippet
|
|
end
|
|
|
|
local snippets = {}
|
|
local paths = vim.split(vim.fn.glob "~/.config/nvim/snippets/**/*.snippet", "\n")
|
|
for paths_index = 1, #paths do
|
|
local file = paths[paths_index]
|
|
local snippet = parse_snippet_file(file)
|
|
|
|
local body = table.concat(snippet.body, "\n")
|
|
snippet.body = nil
|
|
|
|
if snippet.key ~= nil then
|
|
snippet.trig = snippet.key
|
|
end
|
|
|
|
if snippet.description ~= nil then
|
|
snippet.desc = snippet.description
|
|
end
|
|
|
|
local parsed = ls.parser.parse_snippet(snippet, body, {})
|
|
for filetype_index = 1, #snippet.filetypes do
|
|
local filetype = snippet.filetypes[filetype_index]
|
|
if snippets[filetype] == nil then
|
|
snippets[filetype] = {}
|
|
end
|
|
|
|
table.insert(snippets[filetype], parsed)
|
|
end
|
|
end
|
|
|
|
for filetype, snippets_to_add in pairs(snippets) do
|
|
ls.add_snippets(filetype, snippets_to_add)
|
|
end
|