summaryrefslogtreecommitdiff
path: root/config/essentials/vis/vis-ultisnips/snipmate-parser.lua
diff options
context:
space:
mode:
authorRaymaekers Luca <raymaekers.luca@gmail.com>2024-06-22 02:05:44 +0200
committerRaymaekers Luca <raymaekers.luca@gmail.com>2024-06-22 02:05:44 +0200
commit36d2972c60ec86b873fa496d1f5ea95cf748cf49 (patch)
treea6d6750fa17c2964cd241afa8e963cac6106b390 /config/essentials/vis/vis-ultisnips/snipmate-parser.lua
parent4914b43f642e2772a140a8f9b1f26b4e555ed88b (diff)
parent32256e087aaf7744348a5ba33e802d5c8d9d97dd (diff)
Merge branch 'main' of db:dotfiles
Diffstat (limited to 'config/essentials/vis/vis-ultisnips/snipmate-parser.lua')
-rw-r--r--config/essentials/vis/vis-ultisnips/snipmate-parser.lua128
1 files changed, 128 insertions, 0 deletions
diff --git a/config/essentials/vis/vis-ultisnips/snipmate-parser.lua b/config/essentials/vis/vis-ultisnips/snipmate-parser.lua
new file mode 100644
index 0000000..9d735f1
--- /dev/null
+++ b/config/essentials/vis/vis-ultisnips/snipmate-parser.lua
@@ -0,0 +1,128 @@
+--------------------------------------------------------------------------------
+-- Module table
+
+local M = {}
+
+local lpeg = require('lpeg')
+
+
+
+--------------------------------------------------------------------------------
+-- lpeg rules
+
+-- Base definitions
+-- local tws = lpeg.S' ' ^ 1
+local tnewline = lpeg.S'\n'
+-- local tlowcasedword = lpeg.R'az' ^ 1
+local tdigit = lpeg.locale()['digit']
+local talphanum = lpeg.locale()['alnum']
+local tanyprintable = lpeg.locale()['print']
+-- local tcontrol = lpeg.locale()['cntrl']
+local ttabtrigger = tanyprintable ^ 1
+local ttag = lpeg.Cg(lpeg.Cp(), 'selstart')
+ * lpeg.P'${'
+ * lpeg.Cg(tdigit^1, 'tag-order')
+ * (
+ (lpeg.S':' * lpeg.Cg(talphanum^1, 'default-value') * lpeg.S'}')
+ + lpeg.S'}'
+ )
+ * lpeg.Cg(lpeg.Cp(), 'selend')
+local tsnippetdecl = lpeg.P'snippet' * lpeg.S' ' * lpeg.Cg(ttabtrigger, 'tabtrigger') * tnewline
+local tsnippetcontent = lpeg.C(
+ lpeg.Cp() *
+ (lpeg.S'\t '^1
+ * (lpeg.Ct(ttag) + tanyprintable)^1
+ * tnewline
+ )^1
+ )
+
+-- Constructs
+local tsnippet = tsnippetdecl * tsnippetcontent
+local tcomment = lpeg.S'#' * tanyprintable^0 * tnewline
+
+-- The way grammar captures:
+-- Every snippet gets its own table, and every table has:
+-- 'tabtrigger' - the tabtrigger
+-- [1] - full content
+-- [2] - start of snippet content (need to subtract from selstart/selend
+-- [3..n] - tags
+local tsnippetsfile = lpeg.Ct((tcomment + lpeg.Ct(tsnippet) + tnewline) ^1)
+
+--------------------------------------------------------------------------------
+-- Functions
+
+local function trim_tabs(content)
+ local trim = function (s)
+ return (string.gsub(s, "^\t(.-)$", "%1"))
+ end
+
+ local ret=''
+ for str in string.gmatch(content, '([^\n]+)') do
+ ret = ret .. trim(str) .. '\n'
+ end
+ return ret
+end
+
+-- Tags are on the top level of th table,
+-- defined starting with index '3'
+-- Index '2' is start of the content
+-- Structure:
+-- { tag-order: int
+-- , selstart: int
+-- , selend: int
+-- , default-value: str
+-- }
+local function extract_tags(tableau)
+ local tags = {}
+ for k,v in ipairs(tableau) do
+ if k >= 3 then -- Only process starting with ix 2
+ tags[k - 2] = { selstart = v.selstart - tableau[2] - 1
+ , selend = v.selend - tableau[2] - 1
+ , default = v['default-value']
+ , order = v['tag-order']
+ }
+-- vis:message('snippet ' .. tableau.tabtrigger .. ' tag ' ..
+-- tostring(tags[k - 1].order) .. ' has start/end: ' ..
+-- tostring(tags[k - 1].selstart) .. '/' ..
+-- tostring(tags[k - 1].selend))
+ end
+ end
+ return tags
+end
+
+M.load_snippets = function(snippetfile)
+ local snippets = {}
+
+ local f = io.open(snippetfile, 'r')
+ if f then
+ local content = f:read("*all")
+
+ -- TODO hmmm, this'll make whole file unsuable, when it could
+ -- in fact have usable snippets
+ local m = tsnippetsfile:match(content)
+ if not m then
+ vis:info('Failed to parse SnipMate file: '.. snippetfile)
+ return nil
+ else
+ -- k is index of snippet definition, v is table of snippet def
+ for _,v in pairs(m) do
+ snippets[v.tabtrigger] = { description = nil
+ , options = {}
+ , content = { str = trim_tabs(v[1])
+ , tags = extract_tags(v)
+ }
+ }
+ end
+ end
+
+ f:close()
+ return snippets, true
+ else
+ return snippets, false
+ end
+end
+
+--------------------------------------------------------------------------------
+-- End module
+
+return M