diff --git a/site-modules/core/files/vim/plugin/snippets.lua b/site-modules/core/files/vim/plugin/snippets.lua index dede647..422afc8 100644 --- a/site-modules/core/files/vim/plugin/snippets.lua +++ b/site-modules/core/files/vim/plugin/snippets.lua @@ -1,100 +1,98 @@ -local ls = require('luasnip') -local s = ls.snippet -local sn = ls.snippet_node -local i = ls.insert_node -local f = ls.function_node -local t = ls.text_node -local d = ls.dynamic_node -local fmt = require('luasnip.extras.fmt').fmt +-- 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" -function p (trig, desc, snip) - return ls.parser.parse_snippet( - { trig = trig, dscr = desc }, - table.concat(snip, '\n') - ) +-- 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 -ls.config.setup({ - store_selection_keys="", - update_events="InsertLeave,TextChangedI", -}) +-- 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 -ls.add_snippets("all", { - p('todo', 'Todo comment', { 'TODO(${1:ade}): $0' }) -}) + 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 -ls.add_snippets("org", { - p('org-header', 'Org mode header block', { - '#+TITLE: $0', - '#+AUTHOR: Ade Attwood', - '#+EMAIL: hello@adeattwood.co.uk', - '#+DATE: $CURRENT_YEAR-$CURRENT_MONTH-${CURRENT_DATE}' - }) -}) + 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 -ls.add_snippets("php", { - p('#!', 'Shebang', { '#!/usr/bin/env php' }), - p( '/**', 'Block comment', { - '/**', - ' * ${0}', - ' */' - }), - s( - {trig = 'this', dscr = 'This shorthand'}, - fmt("$this->{}", { - i(0), - }) - ), - s( - {trig = 'ai', dscr = 'Array item'}, - fmt("'{}' => {}", { - i(1), - i(0), - }) - ) -}) +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 js_ts = { - p('#!', 'Shebang', { '#!/usr/bin/env node' }), - s( - {trig = 'import', dscr = 'Import statement'}, - fmt("import {} from '{}'", { - i(0), - i(1) - }) - ), + local body = table.concat(snippet.body, "\n") + snippet.body = nil - s({trig = 'fn', dscr = 'Function'}, { - t('function '), - i(1), - t('('), - i(2), - t(')'), - t({' {', '\t'}), - i(0), - t({'', '}'}) - }), + if snippet.key ~= nil then + snippet.trig = snippet.key + end - s({trig = 'useState', dscr = 'React useState hook'}, { - t('const ['), - i(1, 'state'), - t(', '), - f(function (args) - if args[1] == nil then - return '' - end + if snippet.description ~= nil then + snippet.desc = snippet.description + end - return 'set' .. args[1][1]:gsub("^%l", string.upper) - end, {1}), - t('] = React.useState('), - i(0), - t(');') - }), - p('log', 'Console log statement', { 'console.log(${0});' }) -} + 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 - -ls.add_snippets("typescriptreact", js_ts) -ls.add_snippets("typescript", js_ts) +for filetype, snippets_to_add in pairs(snippets) do + ls.add_snippets(filetype, snippets_to_add) +end diff --git a/site-modules/core/files/vim/snippets/snippets/core/block-comment.snippet b/site-modules/core/files/vim/snippets/snippets/core/block-comment.snippet new file mode 100644 index 0000000..73594c1 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/core/block-comment.snippet @@ -0,0 +1,8 @@ +# name: Block comment +# key: /** +# contributor: Ade Attwood +# filetypes: javascript,javascriptreact,typescript,typescriptreact,php +# -- +/** + * $0 + */ diff --git a/site-modules/core/files/vim/snippets/snippets/core/todo.snippet b/site-modules/core/files/vim/snippets/snippets/core/todo.snippet new file mode 100644 index 0000000..5eada0d --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/core/todo.snippet @@ -0,0 +1,6 @@ +# name: Todo comment +# key: todo +# contributor: Ade Attwood +# filetypes: all +# -- +TODO(${1:ade}): $0 diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/bc.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/bc.snippet new file mode 100644 index 0000000..85abfab --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/bc.snippet @@ -0,0 +1,6 @@ +# name: Breaking change block in commit message +# key: bc +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +BREAKING CHANGE: ${0:Description} diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/chore.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/chore.snippet new file mode 100644 index 0000000..9f5620a --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/chore.snippet @@ -0,0 +1,6 @@ +# name: Chore commit message +# key: chore +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +chore(${1:scope}): ${2:title} diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/ci.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/ci.snippet new file mode 100644 index 0000000..19c920d --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/ci.snippet @@ -0,0 +1,6 @@ +# name: Continuous intergration commit message +# key: ci +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +ci(${1:scope}): ${2:title} diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/docs.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/docs.snippet new file mode 100644 index 0000000..3c3e6c0 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/docs.snippet @@ -0,0 +1,6 @@ +# name: Documentation commit message +# key: docs +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +docs(${1:scope}): ${2:title} diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/feat.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/feat.snippet new file mode 100644 index 0000000..a8ac92e --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/feat.snippet @@ -0,0 +1,6 @@ +# name: Feature commit message +# key: feat +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +feat(${1:scope}): ${2:title} diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/fix.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/fix.snippet new file mode 100644 index 0000000..bdf2849 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/fix.snippet @@ -0,0 +1,10 @@ +# name: Bug fix commit message +# key: fix +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +fix(${1:scope}): ${2:title} + +${3:discription} + +fixes issue ${3:issue number} diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/perf.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/perf.snippet new file mode 100644 index 0000000..f2d1689 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/perf.snippet @@ -0,0 +1,6 @@ +# name: Performance commit message +# key: perf +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +perf(${1:scope}): ${2:title} \ No newline at end of file diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/refactor.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/refactor.snippet new file mode 100644 index 0000000..9728183 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/refactor.snippet @@ -0,0 +1,6 @@ +# name: Refactor commit message +# key: refactor +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +refactor(${1:scope}): ${2:title} \ No newline at end of file diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/sec.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/sec.snippet new file mode 100644 index 0000000..d33a112 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/sec.snippet @@ -0,0 +1,6 @@ +# name: Security footer in a commit message +# key: sec +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +SECURITY: ${0:Description} \ No newline at end of file diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/style.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/style.snippet new file mode 100644 index 0000000..a8c8363 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/style.snippet @@ -0,0 +1,6 @@ +# name: Code styling commit message +# key: style +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +style(${1:scope}): ${2:title} \ No newline at end of file diff --git a/site-modules/core/files/vim/snippets/snippets/gitcommit/test.snippet b/site-modules/core/files/vim/snippets/snippets/gitcommit/test.snippet new file mode 100644 index 0000000..070f307 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/gitcommit/test.snippet @@ -0,0 +1,6 @@ +# name: Test commit message +# key: test +# contributor: Ade Attwood +# filetypes: gitcommit +# -- +test(${1:scope}): ${2:title} \ No newline at end of file diff --git a/site-modules/core/files/vim/snippets/snippets/js/import.snippet b/site-modules/core/files/vim/snippets/snippets/js/import.snippet new file mode 100644 index 0000000..e1239db --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/js/import.snippet @@ -0,0 +1,6 @@ +# name: ESM import statement +# key: import +# contributor: Ade Attwood +# filetypes: javascript,javascriptreact,typescript,typescriptreact +# -- +import { $2 } from '${1:package}';${0} diff --git a/site-modules/core/files/vim/snippets/snippets/js/it.snippet b/site-modules/core/files/vim/snippets/snippets/js/it.snippet new file mode 100644 index 0000000..900aace --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/js/it.snippet @@ -0,0 +1,8 @@ +# name: It test function +# key: it +# contributor: Ade Attwood +# filetypes: javascript,javascriptreact,typescript,typescriptreact +# -- +it('${1}', ${2:async}() => { + ${0} +}); diff --git a/site-modules/core/files/vim/snippets/snippets/js/log.snippet b/site-modules/core/files/vim/snippets/snippets/js/log.snippet new file mode 100644 index 0000000..0d5dc54 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/js/log.snippet @@ -0,0 +1,6 @@ +# name: Console lot statement +# key: log +# contributor: Ade Attwood +# filetypes: javascript,javascriptreact,typescript,typescriptreact +# -- +console.log(${0}); diff --git a/site-modules/core/files/vim/snippets/snippets/react/functional-component-javascript.snippet b/site-modules/core/files/vim/snippets/snippets/react/functional-component-javascript.snippet new file mode 100644 index 0000000..e5baef6 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/react/functional-component-javascript.snippet @@ -0,0 +1,15 @@ +# name: React functional component +# key: rfc +# contributor: Ade Attwood +# filetypes: javascriptreact +# -- +const $1PropTypes = {}; + +/** + * @type {React.FC>} + */ +const ${1:Component} = () => { + return
$0
+} + +$1.propTypes = $1PropTypes; diff --git a/site-modules/core/files/vim/snippets/snippets/react/functional-component-typescript.snippet b/site-modules/core/files/vim/snippets/snippets/react/functional-component-typescript.snippet new file mode 100644 index 0000000..e73379c --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/react/functional-component-typescript.snippet @@ -0,0 +1,12 @@ +# name: React functional component +# key: rfc +# contributor: Ade Attwood +# filetypes: typescriptreact +# -- +export interface $1Props {}; + +export const ${1:Component}: React.FC<$1Props> = () => { + return ( + ${0:
Component
} + ); +}; diff --git a/site-modules/core/files/vim/snippets/snippets/react/import-javascript.snippet b/site-modules/core/files/vim/snippets/snippets/react/import-javascript.snippet new file mode 100644 index 0000000..5c1cfe0 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/react/import-javascript.snippet @@ -0,0 +1,7 @@ +# name: React imports +# key: react +# contributor: Ade Attwood +# filetypes: javascriptreact +# -- +import React from 'react'; +import PropTypes from 'prop-types'; diff --git a/site-modules/core/files/vim/snippets/snippets/react/import-typescript.snippet b/site-modules/core/files/vim/snippets/snippets/react/import-typescript.snippet new file mode 100644 index 0000000..0693e39 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/react/import-typescript.snippet @@ -0,0 +1,6 @@ +# name: React imports +# key: react +# contributor: Ade Attwood +# filetypes: typescriptreact +# -- +import React from 'react'; diff --git a/site-modules/core/files/vim/snippets/snippets/react/use-state.snippet b/site-modules/core/files/vim/snippets/snippets/react/use-state.snippet new file mode 100644 index 0000000..e6bbe42 --- /dev/null +++ b/site-modules/core/files/vim/snippets/snippets/react/use-state.snippet @@ -0,0 +1,6 @@ +# name: React useState +# key: useState +# contributor: Ade Attwood +# filetypes: javascriptreact,typescriptreact +# -- +const [${1:state}, set${1/(.*)/${1:/capitalize}/}] = React.useState($2);$0