Files
typstar/lua/typstar/autosnippets.lua

107 lines
3.6 KiB
Lua

local M = require('typstar.engine') -- inherit all functions
local luasnip = require('luasnip')
function M.cap(i)
return luasnip.function_node(function(_, snip) return snip.captures[i] end)
end
local compute_leading_white_spaces = function(snip, i)
local capture = snip.captures[i] or ''
return capture:match('^%s*') or ''
end
function M.leading_white_spaces(i)
return luasnip.function_node(function(_, snip) return compute_leading_white_spaces(snip, i) end)
end
function M.visual(idx, default, line_prefix, indent_capture_idx)
default = default or ''
line_prefix = line_prefix or ''
return luasnip.dynamic_node(idx, function(_, snip)
local select_raw = snip.snippet.env.LS_SELECT_RAW
if #select_raw > 0 then
if line_prefix ~= '' then -- e.g. indentation
for i, s in ipairs(select_raw) do
select_raw[i] = line_prefix .. s
end
end
return luasnip.snippet_node(nil, luasnip.text_node(select_raw))
else -- If LS_SELECT_RAW is empty, return an insert node
local leading = ''
if indent_capture_idx ~= nil then leading = compute_leading_white_spaces(snip, indent_capture_idx) end
return luasnip.snippet_node(nil, {
luasnip.text_node(leading .. line_prefix),
luasnip.insert_node(1, default),
})
end
end)
end
function M.ri(insert_node_id)
return luasnip.function_node(function(args) return args[1][1] end, insert_node_id)
end
function M.start_snip(trigger, expand, insert, condition, priority, options)
return M.snip('^(\\s*)' .. trigger, '<>' .. expand, { M.cap(1), unpack(insert) }, condition, priority, options)
end
-- transform the snippet expand by inserting indentation and/or a prefix after each newline
function M.blocktransform(expand, insert, prepend, indent_capture_idx)
local indent = indent_capture_idx ~= nil
if not indent and not prepend then return expand, insert end
prepend = prepend or ''
local modified_expand = expand
local modified_insert = {}
for i, v in pairs(insert) do
modified_insert[i] = v
end
local offset = 0
local last_pos = 0
while true do
local newline_pos = string.find(expand, '\n', last_pos + 1)
if not newline_pos then break end
-- prepend string
local insert_pos = newline_pos + offset + 1
local prefix = (indent and '<>' or '') .. prepend
modified_expand = string.sub(modified_expand, 1, insert_pos - 1)
.. prefix
.. string.sub(modified_expand, insert_pos)
offset = offset + #prefix
-- indent node
if indent then
local expand_before = string.sub(modified_expand, 1, insert_pos + 1)
local indent_pos = select(2, string.gsub(expand_before, '<>', ''))
table.insert(modified_insert, indent_pos, M.leading_white_spaces(indent_capture_idx))
end
last_pos = newline_pos
end
return modified_expand, modified_insert
end
function M.start_snip_in_newl(trigger, expand, insert, condition, priority, options)
return M.snip(
'([^\\s]\\s+)' .. trigger,
'<>\n' .. expand,
{ M.cap(1), unpack(insert) },
condition,
priority,
options
)
end
function M.bulletpoint_snip(trigger, expand, insert, condition, priority, options)
return M.snip(
'(^\\s*\\-\\s+.*\\s*)' .. trigger,
'<>' .. expand,
{ M.cap(1), unpack(insert) },
condition,
priority,
vim.tbl_deep_extend('keep', { indentCaptureIdx = 1 }, options or {})
)
end
return M